├── version ├── Module ├── META-INF │ └── com │ │ └── google │ │ └── android │ │ ├── updater-script │ │ └── update-binary ├── webroot │ ├── common │ │ ├── lsposed2.sh │ │ ├── assets │ │ │ ├── icon │ │ │ │ ├── github.gif │ │ │ │ ├── telegram.gif │ │ │ │ ├── play.svg │ │ │ │ └── refresh.svg │ │ │ ├── navbar │ │ │ │ ├── android.png │ │ │ │ ├── community.png │ │ │ │ ├── home.svg │ │ │ │ ├── menu.svg │ │ │ │ └── settings.svg │ │ │ └── wallpaper │ │ │ │ └── sparkle.png │ │ ├── FixWidevineL1 │ │ │ ├── FixWidevineL1.sh │ │ │ └── attestation │ │ ├── pif2.sh │ │ ├── widevinel1.sh │ │ ├── twrp.sh │ │ ├── boot_hash.sh │ │ ├── device-info.sh │ │ └── theme-manager.sh │ ├── yurikey.png │ ├── json │ │ ├── device-info.json │ │ ├── dev.json │ │ └── theme-config.json │ ├── config.json │ ├── js │ │ ├── redirect.js │ │ ├── version.js │ │ ├── dev.js │ │ ├── device.js │ │ ├── language.js │ │ ├── file_selector.js │ │ ├── theme.js │ │ └── main.js │ ├── css │ │ ├── file_selector.css │ │ └── style.css │ ├── lang │ │ ├── zh-han.json │ │ ├── jp.json │ │ ├── ar.json │ │ ├── th.json │ │ ├── en.json │ │ ├── hi.json │ │ ├── tr.json │ │ ├── bn.json │ │ ├── id.json │ │ ├── ms.json │ │ ├── vn.json │ │ ├── pt-br.json │ │ ├── uka.json │ │ ├── pl.json │ │ ├── ro-md.json │ │ ├── hu.json │ │ ├── ru.json │ │ ├── es.json │ │ └── ph.json │ └── index.html ├── module.prop ├── Yuri │ ├── hma.sh │ ├── kill_google_process.sh │ ├── boot_hash.sh │ ├── kill_all.sh │ ├── select_app_neccesary.sh │ ├── security_patch.sh │ ├── target_txt.sh │ ├── yuri_keybox.sh │ └── clear_all_detection_traces.sh ├── uninstall.sh ├── action.sh └── customize.sh ├── doc ├── banner.webp └── README_ja-JP.md ├── update.json ├── changelog.md ├── .github └── workflows │ └── build.yml ├── README.md └── key /version: -------------------------------------------------------------------------------- 1 | v34 2 | -------------------------------------------------------------------------------- /Module/META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /doc/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii0307/yurikey/HEAD/doc/banner.webp -------------------------------------------------------------------------------- /Module/webroot/common/lsposed2.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | find /data/app -type f -name base.odex -delete -------------------------------------------------------------------------------- /Module/webroot/yurikey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii0307/yurikey/HEAD/Module/webroot/yurikey.png -------------------------------------------------------------------------------- /Module/webroot/json/device-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "android": "none", 3 | "kernel": "none", 4 | "root": "none" 5 | } 6 | -------------------------------------------------------------------------------- /Module/webroot/common/assets/icon/github.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii0307/yurikey/HEAD/Module/webroot/common/assets/icon/github.gif -------------------------------------------------------------------------------- /Module/webroot/common/assets/icon/telegram.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii0307/yurikey/HEAD/Module/webroot/common/assets/icon/telegram.gif -------------------------------------------------------------------------------- /Module/webroot/common/assets/navbar/android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii0307/yurikey/HEAD/Module/webroot/common/assets/navbar/android.png -------------------------------------------------------------------------------- /Module/webroot/common/assets/navbar/community.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii0307/yurikey/HEAD/Module/webroot/common/assets/navbar/community.png -------------------------------------------------------------------------------- /Module/webroot/common/assets/wallpaper/sparkle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yurii0307/yurikey/HEAD/Module/webroot/common/assets/wallpaper/sparkle.png -------------------------------------------------------------------------------- /Module/webroot/common/FixWidevineL1/FixWidevineL1.sh: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=/vendor/lib64/hw /vendor/bin/KmInstallKeybox /data/local/tmp/attestation attestation true -------------------------------------------------------------------------------- /Module/webroot/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Yurikey Manager", 3 | "icon": "yurikey.png", 4 | "windowResize": false, 5 | "exitConfirm": false 6 | } -------------------------------------------------------------------------------- /Module/webroot/common/pif2.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | su -c ' 4 | getprop | grep -E "pihook|pixelprops" | sed -E "s/^\[(.*)\]:.*/\1/" | while IFS= read -r prop; do 5 | resetprop -p -d "$prop" 6 | done 7 | ' -------------------------------------------------------------------------------- /Module/webroot/common/assets/icon/play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /update.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v2.32", 3 | "versionCode": 232, 4 | "zipUrl": "https://github.com/YurikeyDev/yurikey/releases/download/v2.32/YuriKey_v2.32.signed.zip", 5 | "changelog": "https://raw.githubusercontent.com/dpejoh/yurikey/main/changelog.md" 6 | } 7 | -------------------------------------------------------------------------------- /Module/webroot/common/assets/navbar/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Module/module.prop: -------------------------------------------------------------------------------- 1 | id=Yurikey 2 | name=Yuri Keybox Manager 3 | version=v2.32 4 | versionCode=232 5 | author=Yurikey Dev 6 | banner=https://raw.githubusercontent.com/YurikeyDev/yurikey/main/doc/banner.webp 7 | description=A systemless module to get strong integrity so easily 8 | updateJson=https://raw.githubusercontent.com/YurikeyDev/yurikey/main/update.json 9 | -------------------------------------------------------------------------------- /Module/webroot/common/assets/icon/refresh.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Module/Yuri/hma.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | mkdir -p /data/user/0/org.frknkrc44.hma_oss/files 3 | curl -L "https://raw.githubusercontent.com/YurikeyDev/yurikey/refs/heads/main/config.json" -o /data/user/0/org.frknkrc44.hma_oss/files/config.json 4 | chmod 777 /data/user/0/org.frknkrc44.hma_oss/files/config.json 5 | chown u0_a0:u0_a0 /data/user/0/org.frknkrc44.hma_oss/files/config.json 6 | -------------------------------------------------------------------------------- /Module/webroot/common/assets/navbar/menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Module/webroot/common/widevinel1.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | # Copy FixWidevineL1/* directory to /data/local/tmp 3 | cp -r ./FixWidevineL1/* /data/local/tmp/ 4 | 5 | # Set correct permissions 6 | chmod 777 /data/local/tmp/FixWidevineL1.sh 7 | chmod 777 /data/local/tmp/attestation 8 | 9 | # Set owner and group to root:root 10 | chown root:root /data/local/tmp/FixWidevineL1.sh 11 | chown root:root /data/local/tmp/attestation 12 | 13 | # Execute the script 14 | su -c sh /data/local/tmp/FixWidevineL1.sh 15 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | **_✨ v2.32 – Version Changes:_** 2 | 3 | → Improre code yurikey.sh, security patch.sh, clear_all_detection_traces.sh 4 | 5 | → Delete outdated Fix Detect HMA in webUI. Replace it with Clear All Detection Traces. 6 | 7 | → Correct some typos and spelling errors. 8 | 9 | **_📌 Other Changes:_** 10 | 11 | → Fix error why can't fetch the keybox and show instructions if need. 12 | 13 | → Various performance improvement 14 | 15 | → [All changes](https://github.com/YurikeyDev/yurikey/compare/v2.31...v2.32). 16 | -------------------------------------------------------------------------------- /Module/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | TRICKY_DIR="/data/adb/tricky_store" 4 | TARGET_FILE="$TRICKY_DIR/keybox.xml" 5 | BACKUP_FILE="$TRICKY_DIR/keybox.xml.bak" 6 | BBIN="/data/adb/Yurikey/bin" 7 | 8 | ui_print() { 9 | echo "$1" 10 | } 11 | 12 | backup () { 13 | if [ -f "$BACKUP_FILE" ]; then 14 | rm -f "$TARGET_FILE" 15 | mv "$BACKUP_FILE" "$TARGET_FILE" 16 | fi 17 | } 18 | 19 | if [ -f "$TARGET_FILE" ]; then 20 | if grep -q "yuriiroot" "$TARGET_FILE"; then 21 | backup 22 | fi 23 | fi 24 | 25 | if [ -d "$BBIN" ]; then 26 | rm -rf $BBIN 27 | fi 28 | -------------------------------------------------------------------------------- /Module/webroot/common/twrp.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | # delete_twrp_folder.sh 3 | # Script to delete TWRP folder from Android internal storage 4 | 5 | echo "Starting deletion of TWRP folder..." 6 | 7 | # Define the TWRP folder path (adjust if needed) 8 | TWRP_FOLDER="/sdcard/TWRP" 9 | 10 | if [ -d "$TWRP_FOLDER" ]; then 11 | echo "- Found folder $TWRP_FOLDER. Deleting..." 12 | rm -rf "$TWRP_FOLDER" 13 | echo "Folder deleted successfully." 14 | else 15 | echo "- Folder $TWRP_FOLDER not found. Nothing to delete." 16 | fi 17 | 18 | echo "TWRP folder deletion script completed." -------------------------------------------------------------------------------- /Module/Yuri/kill_google_process.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | log_message() { 4 | echo "$(date +%Y-%m-%d\ %H:%M:%S) [KILL_GOOGLE] $1" 5 | } 6 | 7 | # Start 8 | log_message "Start" 9 | 10 | # Writing 11 | log_message "Writing" 12 | PKGS="com.android.vending" 13 | 14 | for pkg in $PKGS; do 15 | if ! am force-stop "$pkg" >/dev/null 2>&1; then 16 | log_message "ERROR: Failed to force-stop $pkg" 17 | exit 1 18 | fi 19 | 20 | if ! cmd package trim-caches 0 "$pkg" >/dev/null 2>&1; then 21 | log_message "ERROR: Failed to clear cache for $pkg" 22 | exit 1 23 | fi 24 | done 25 | 26 | # Finish 27 | log_message "Finish" 28 | -------------------------------------------------------------------------------- /Module/Yuri/boot_hash.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | log_message() { 4 | echo "$(date +%Y-%m-%d\ %H:%M:%S) [SET_BOOT_HASH] $1" 5 | } 6 | 7 | log_message "Start" 8 | 9 | # Get vbmeta hash 10 | boot_hash=$(su -c "getprop ro.boot.vbmeta.digest" 2>/dev/null) 11 | [ -z "$boot_hash" ] && boot_hash="0000000000000000000000000000000000000000000000000000000000000000" 12 | 13 | file_path="/data/adb/boot_hash" 14 | 15 | # Create folder and write file 16 | log_message "Writing" 17 | mkdir -p "$(dirname "$file_path")" 18 | echo "$boot_hash" > "$file_path" 19 | chmod 644 "$file_path" 20 | su -c "resetprop -n ro.boot.vbmeta.digest $boot_hash" >/dev/null 2>&1 21 | 22 | log_message "Finish" -------------------------------------------------------------------------------- /Module/webroot/common/boot_hash.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | log_message() { 4 | echo "$(date +%Y-%m-%d\ %H:%M:%S) [SET_BOOT_HASH] $1" 5 | } 6 | 7 | log_message "Start" 8 | 9 | # Get vbmeta hash 10 | boot_hash=$(su -c "getprop ro.boot.vbmeta.digest" 2>/dev/null) 11 | [ -z "$boot_hash" ] && boot_hash="0000000000000000000000000000000000000000000000000000000000000000" 12 | 13 | file_path="/data/adb/boot_hash" 14 | 15 | # Create folder and write file 16 | log_message "Writing" 17 | mkdir -p "$(dirname "$file_path")" 18 | echo "$boot_hash" > "$file_path" 19 | chmod 644 "$file_path" 20 | su -c "resetprop -n ro.boot.vbmeta.digest $boot_hash" >/dev/null 2>&1 21 | 22 | log_message "Finish" -------------------------------------------------------------------------------- /Module/webroot/common/assets/navbar/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Module 2 | 3 | on: 4 | #push: 5 | # paths: 6 | # - 'Module/**' 7 | # branches: 8 | # - main 9 | # - dev 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | 19 | - name: Update version with git HEAD 20 | run: | 21 | RANDOM_STRING=$(git rev-parse --short HEAD | cut -c1-7) 22 | echo "BUILD_ID=${RANDOM_STRING}" >> $GITHUB_ENV 23 | sed -i "s/^version=.*/version=${RANDOM_STRING}/" Module/module.prop 24 | 25 | - name: Upload release artifact 26 | uses: actions/upload-artifact@v4 27 | with: 28 | name: YuriKey_${{ env.BUILD_ID }} 29 | path: | 30 | ${{ github.workspace }}/Module/* 31 | -------------------------------------------------------------------------------- /Module/Yuri/kill_all.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | log_message() { 4 | echo "$(date +%Y-%m-%d\ %H:%M:%S) [KILL_ALL] $1" 5 | } 6 | 7 | # Start 8 | log_message "Start" 9 | 10 | # Writing 11 | log_message "Writing" 12 | PKGS="com.android.vending com.google.android.gsf com.google.android.gms com.google.android.contactkeys com.google.android.ims com.google.android.safetycore com.google.android.apps.walletnfcrel com.google.android.apps.nbu.paisa.user com.zhenxi.hunter com.reveny.nativecheck io.github.vvb2060.keyattestation io.github.vvb2060.mahoshojo icu.nullptr.nativetest com.android.nativetest io.liankong.riskdetector me.garfieldhan.holmes luna.safe.luna com.zhenxi.hunter gr.nikolasspyr.integritycheck com.youhu.laifu" 13 | 14 | for pkg in $PKGS; do 15 | if ! am force-stop "$pkg" >/dev/null 2>&1; then 16 | log_message "ERROR: Failed to force-stop $pkg" 17 | exit 1 18 | fi 19 | 20 | if ! pm clear "$pkg" >/dev/null 2>&1; then 21 | log_message "ERROR: Failed to clear data for $pkg" 22 | exit 1 23 | fi 24 | done 25 | 26 | # Finish 27 | log_message "Finish" 28 | -------------------------------------------------------------------------------- /Module/action.sh: -------------------------------------------------------------------------------- 1 | MODPATH="${0%/*}" 2 | 3 | # Setup 4 | set +o standalone 5 | unset ASH_STANDALONE 6 | 7 | if ! command -v curl >/dev/null 2>&1 \ 8 | && ! command -v wget >/dev/null 2>&1 \ 9 | && ! command -v toybox >/dev/null 2>&1 10 | then 11 | log_message "- Cannot work without missing command." 12 | log_message "- Tip: You can install a working BusyBox with network tools from:" 13 | log_message "- https://mmrl.dev/repository/grdoglgmr/busybox-ndk" 14 | exit 1 15 | fi 16 | 17 | for SCRIPT in \ 18 | "kill_google_process.sh" \ 19 | "target_txt.sh" \ 20 | "security_patch.sh" \ 21 | "boot_hash.sh" \ 22 | "yuri_keybox.sh" 23 | do 24 | if ! sh "$MODPATH/Yuri/$SCRIPT"; then 25 | echo "- Error: $SCRIPT failed. Aborting." 26 | exit 1 27 | fi 28 | done 29 | 30 | 31 | if [ -f /data/adb/modules_update/Yurikey/webroot/common/device-info.sh ]; then 32 | sh /data/adb/modules_update/Yurikey/webroot/common/device-info.sh 33 | elif [ -f /data/adb/modules/yurikey/webroot/common/device-info.sh ]; then 34 | sh /data/adb/modules/yurikey/webroot/common/device-info.sh 35 | fi 36 | 37 | echo -e "$(date +%Y-%m-%d\ %H:%M:%S) Meets Strong Integrity with Yurikey Manager✨✨" 38 | -------------------------------------------------------------------------------- /Module/Yuri/select_app_neccesary.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | log_message() { 4 | echo "$(date +%Y-%m-%d\ %H:%M:%S) [KILL_ALL] $1" 5 | } 6 | 7 | # Start 8 | log_message "Start" 9 | 10 | t='/data/adb/tricky_store/target.txt' 11 | 12 | # Writing 13 | log_message "Writing" 14 | rm -rf "$t" 15 | # add list special 16 | fixed_targets="\ 17 | android 18 | com.android.vending! 19 | com.google.android.gsf! 20 | com.google.android.gms! 21 | io.github.vvb2060.keyattestation! 22 | io.github.vvb2060.mahoshojo! 23 | com.google.android.contactkeys! 24 | com.google.android.ims! 25 | com.google.android.safetycore! 26 | com.google.android.apps.walletnfcrel! 27 | com.google.android.apps.nbu.paisa.user! 28 | gr.nikolasspyr.integritycheck! 29 | com.youhu.laifu! 30 | com.whatsapp! 31 | com.whatsapp.w4b! 32 | com.openai.chatgpt! 33 | com.reveny.nativecheck! 34 | icu.nullptr.nativetest! 35 | com.android.nativetest! 36 | io.liankong.riskdetector! 37 | me.garfieldhan.holmes! 38 | luna.safe.luna! 39 | com.zhenxi.hunter!" 40 | for entry in $fixed_targets; do 41 | if ! echo "$entry" >> "$t"; then 42 | log_message "ERROR: Failed to write $entry to $t" 43 | exit 1 44 | fi 45 | done 46 | 47 | log_message "Finish" 48 | -------------------------------------------------------------------------------- /Module/webroot/common/device-info.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | # Specify the current root directory for both normal and update path 4 | if [ -d "/data/adb/modules_update/Yurikey" ]; then 5 | BASE_PATH="/data/adb/modules_update/Yurikey" 6 | else 7 | BASE_PATH="/data/adb/modules/Yurikey" 8 | fi 9 | 10 | INFO_PATH="$BASE_PATH/webroot/json/device-info.json" 11 | 12 | android_ver=$(getprop ro.build.version.release) 13 | kernel_ver=$(uname -r) 14 | 15 | # Root Implementation 16 | if [ -d "/data/adb/magisk" ] && [ -f "/data/adb/magisk.db" ]; then 17 | root_type="Magisk" 18 | elif [ -f "/data/apatch/apatch" ]; then 19 | root_type="Apatch" 20 | elif [ -d "/data/adb/ksu" ] && ( [ -d "/data/adb/kpm" ] || [ -f "/data/adb/ksu/.dynamic_sign" ] ); then 21 | root_type="SukiSU-Ultra" 22 | elif [ -d "/data/adb/ksu" ] && ( [ -f "/data/adb/ksud" ] || [ -f "/sys/module/kernelsu/parameters/expected_manager_size" ] ); then 23 | root_type="KernelSU-Next" 24 | elif [ -d "/data/adb/ksu" ]; then 25 | root_type="KernelSU" 26 | else 27 | root_type="Unknown" 28 | fi 29 | 30 | # Output JSON 31 | cat < "$INFO_PATH" 32 | { 33 | "android": "$android_ver", 34 | "kernel": "$kernel_ver", 35 | "root": "$root_type" 36 | } 37 | EOF -------------------------------------------------------------------------------- /Module/webroot/js/redirect.js: -------------------------------------------------------------------------------- 1 | // === Function: Open a URL using Android Intent via KernelSU === 2 | function openUrlViaIntent(url) { 3 | if (!url || typeof url !== "string") return; 4 | 5 | // Build the intent command to open the URL 6 | const intentCmd = `nohup am start -a android.intent.action.VIEW -d '${url}' >/dev/null 2>&1 &`; 7 | 8 | // Check if KernelSU is available and execute the intent command 9 | if (typeof ksu === "object" && typeof ksu.exec === "function") { 10 | const cbId = `cb_${Date.now()}`; 11 | window[cbId] = () => delete window[cbId]; 12 | ksu.exec(intentCmd, "{}", cbId); 13 | } else { 14 | console.warn("ksu.exec not available or unsupported."); 15 | } 16 | } 17 | 18 | // === Function: Attach click listeners to elements with [data-url] === 19 | function setupIntentLinks(selector = "[data-url]") { 20 | document.querySelectorAll(selector).forEach(button => { 21 | const url = button.dataset.url; 22 | if (url) { 23 | button.addEventListener("click", () => openUrlViaIntent(url)); 24 | } 25 | }); 26 | } 27 | 28 | // === Initialize: Run setup when the DOM is fully loaded === 29 | window.addEventListener("DOMContentLoaded", () => { 30 | setupIntentLinks(); 31 | }); 32 | -------------------------------------------------------------------------------- /Module/webroot/js/version.js: -------------------------------------------------------------------------------- 1 | // ========== EXECUTOR FUNCTION ========== 2 | // Executes a shell command using KernelSU and returns a Promise with the output 3 | function exec(command) { 4 | return new Promise((resolve, reject) => { 5 | const cb = `cb_${Date.now()}`; 6 | window[cb] = (code, out, err) => { 7 | delete window[cb]; 8 | code ? reject(err || "Unknown error") : resolve(out); 9 | }; 10 | ksu.exec(command, "{}", cb); 11 | }); 12 | } 13 | 14 | // ========== VERSION MODULE DETECTION ========== 15 | // Reads the 'version' from /data/adb/modules/Yurikey/module.prop 16 | async function loadVersionFromModuleProp() { 17 | const versionElement = document.getElementById('version-text'); 18 | try { 19 | const version = await exec("grep '^version=' /data/adb/modules/Yurikey/module.prop | cut -d'=' -f2"); 20 | versionElement.textContent = version.trim(); 21 | } catch (error) { 22 | appendToOutput("[!] Failed to read version from module.prop"); 23 | console.error("Failed to read version from module.prop:", error); 24 | } 25 | } 26 | 27 | // ========== DOM INITIALIZATION ========== 28 | document.addEventListener('DOMContentLoaded', () => { 29 | loadVersionFromModuleProp(); 30 | }); 31 | -------------------------------------------------------------------------------- /Module/Yuri/security_patch.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | log_message() { 4 | echo "$(date +%Y-%m-%d\ %H:%M:%S) [SET_SECURITY_PATCH] $1" 5 | } 6 | 7 | log_message "Start" 8 | 9 | sp="/data/adb/tricky_store/security_patch.txt" 10 | 11 | # Get current year / month 12 | current_year=$(date +%Y) || { 13 | log_message "ERROR: Failed to get current year" 14 | exit 1 15 | } 16 | 17 | current_month=$(date +%m | sed 's/^0*//') || { 18 | log_message "ERROR: Failed to get current month" 19 | exit 1 20 | } 21 | 22 | # Calculate previous month 23 | if [ "$current_month" -eq 1 ]; then 24 | prev_month=12 25 | prev_year=$((current_year - 1)) 26 | else 27 | prev_month=$((current_month - 1)) 28 | prev_year=$current_year 29 | fi 30 | 31 | formatted_month=$(printf "%02d" "$prev_month") || { 32 | log_message "ERROR: Failed to format month" 33 | exit 1 34 | } 35 | 36 | patch_date="${prev_year}-${formatted_month}-05" 37 | 38 | log_message "Writing" 39 | 40 | # Write correct Trickystore format 41 | cat > "$sp" < { 5 | if (!res.ok) throw new Error(`HTTP ${res.status}`); 6 | return res.json(); 7 | }) 8 | .then(data => { 9 | const container = document.getElementById("contrib-list"); 10 | if (!container || !Array.isArray(data.contributors)) return; 11 | 12 | container.innerHTML = ""; // Clear any existing entries 13 | 14 | // Render each contributor 15 | data.contributors.forEach(user => { 16 | const username = user.username || user.name || "unknown"; 17 | const avatar = `https://github.com/${encodeURIComponent(username)}.png`; 18 | const profileURL = user.url || "#"; 19 | const rawRole = user.role || "Unknown Role"; 20 | const roleKey = `role_${rawRole}`; // Use this for translation lookup 21 | 22 | const card = document.createElement("button"); 23 | card.className = "contrib-card"; 24 | card.setAttribute("type", "button"); 25 | card.addEventListener("click", () => openUrlViaIntent(profileURL)); 26 | 27 | card.innerHTML = ` 28 | ${user.name} 29 |
${user.name}
30 |
${rawRole}
31 | `; 32 | 33 | container.appendChild(card); 34 | }); 35 | 36 | // Re-apply language translation after cards are rendered 37 | const currentLang = localStorage.getItem("selectedLanguage") || "en"; 38 | setTimeout(() => applyLanguage(currentLang), 50); // delay to ensure DOM is updated 39 | }) 40 | .catch(err => { 41 | console.error("Failed to load contributors:", err); 42 | }); 43 | })(); 44 | -------------------------------------------------------------------------------- /Module/webroot/common/theme-manager.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | if [ -d "/data/adb/modules_update/Yurikey" ]; then 4 | BASE_PATH="/data/adb/modules_update/Yurikey" 5 | else 6 | BASE_PATH="/data/adb/modules/Yurikey" 7 | fi 8 | 9 | THEME_CONFIG_PATH="$BASE_PATH/webroot/json/theme-config.json" 10 | THEME_PARAM="$1" 11 | 12 | save_theme() { 13 | local theme_name="$1" 14 | 15 | if [ -z "$theme_name" ]; then 16 | echo "Error: Theme name is required" 17 | exit 1 18 | fi 19 | 20 | if [ ! -f "$THEME_CONFIG_PATH" ]; then 21 | echo "Error: Theme config file not found at $THEME_CONFIG_PATH" 22 | exit 1 23 | fi 24 | 25 | cp "$THEME_CONFIG_PATH" "$THEME_CONFIG_PATH.backup" 26 | 27 | TEMP_CONFIG="/tmp/yurikey-theme-config-temp.json" 28 | sed "s/\"selected_theme\": \"[^\"]*\"/\"selected_theme\": \"$theme_name\"/" "$THEME_CONFIG_PATH" > "$TEMP_CONFIG" 29 | 30 | if grep -q "selected_theme" "$TEMP_CONFIG" && grep -q "themes" "$TEMP_CONFIG"; then 31 | mv "$TEMP_CONFIG" "$THEME_CONFIG_PATH" 32 | chmod 644 "$THEME_CONFIG_PATH" 33 | echo "Theme '$theme_name' saved" 34 | else 35 | echo "Error: Failed to update theme config" 36 | rm -f "$TEMP_CONFIG" 37 | exit 1 38 | fi 39 | } 40 | 41 | get_theme() { 42 | if [ -f "$THEME_CONFIG_PATH" ]; then 43 | grep "selected_theme" "$THEME_CONFIG_PATH" | sed 's/.*"selected_theme": *"\([^"]*\)".*/\1/' | head -1 44 | else 45 | echo "dark-blue" 46 | fi 47 | } 48 | 49 | case "$THEME_PARAM" in 50 | "get") 51 | get_theme 52 | ;; 53 | "save") 54 | if [ -z "$2" ]; then 55 | echo "Error: Theme name required for save operation" 56 | exit 1 57 | fi 58 | save_theme "$2" 59 | ;; 60 | *) 61 | echo "Usage: $0 {get|save} [theme_name]" 62 | echo " get - Get the current theme" 63 | echo " save [theme_name] - Save the selected theme" 64 | exit 1 65 | ;; 66 | esac -------------------------------------------------------------------------------- /Module/webroot/lang/zh-han.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "主页", 3 | "nav_menu": "菜单", 4 | "nav_advancemenu": "菜单 +", 5 | "nav_update": "更新", 6 | "nav_settings": "设置", 7 | 8 | "home_version": "模块版本", 9 | "home_root": "Root 管理器", 10 | "home_refresh": "刷新数据", 11 | "home_refreshing": "正在刷新……", 12 | "home_status": "状态", 13 | "home_status_online": "在线", 14 | "home_status_offline": "离线", 15 | "home_clock_date": "日期", 16 | "home_clock_time": "时间", 17 | 18 | "menu_title": "主菜单", 19 | "menu_force_clear": "强制停止并清除 Play Store 数据", 20 | "menu_keybox": "设置 Yuri Keybox", 21 | "menu_target": "设置 target.txt", 22 | "menu_necessary": "设置必要的应用程序", 23 | "menu_patch": "应用安全补丁", 24 | "menu_keybox_title": "Keybox", 25 | "menu_keybox_restore": "恢复 Keybox 备份", 26 | 27 | "advance_menu_title": "高级菜单", 28 | "advance_fix_detect_hma": "修复 HMA 检测", 29 | "advance_fix_detect_lsposed": "修复 lsposed 检测 (2)", 30 | "advance_fix_detect_pif": "修复 PIF 检测 (1)", 31 | "advance_fix_detect_recovery_file": "修复恢复文件检测", 32 | "advance_kill_all": "终止所有进程", 33 | "advance_wdevinel1": "修复 Widevine L1", 34 | "advance_set_verified_boot": "设置 Verified Boothash", 35 | 36 | "update_title": "更新和支持", 37 | "update_desc": "关注最新的 Yurikey 版本、错误修复和新功能", 38 | "update_github": "在 GitHub 上查看", 39 | "update_telegram": "加入电报频道", 40 | "update_note": "加入我们的 Telegram 频道或查看我们的 GitHub 以获取更新、贡献和技术讨论", 41 | "settings_title": "设置", 42 | 43 | "settings_contributors": "项目联合开发者", 44 | 45 | "role_Founder & Module Developer": "创始人和模块开发人员", 46 | "role_Module Developer": "模块开发人员", 47 | "role_WebUI Developer": "WebUI 开发人员", 48 | "role_Ex Module Developer": "前模块开发人员", 49 | 50 | "executing": "正在执行 \"{script}\"...", 51 | "success": "脚本 \"{script}\" 已成功执行", 52 | "failed": "脚本 \"{script}\" 执行失败", 53 | "timeout": "脚本 \"{script}\" 超时", 54 | "ksu_not_available": "未找到 KernelSU 执行 API", 55 | 56 | "status_online": "状态:在线", 57 | "status_offline": "状态:离线", 58 | "home_refresh_failed": "刷新数据失败", 59 | "home_no_internet": "没有互联网连接", 60 | "home_connected": "已连接", 61 | "home_disconnected": "断开" 62 | } -------------------------------------------------------------------------------- /Module/webroot/lang/jp.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "ホーム", 3 | "nav_menu": "メニュー", 4 | "nav_update": "更新", 5 | "nav_advancemenu": "メニュー +", 6 | "nav_settings": "設定", 7 | 8 | "home_version": "モジュールのバージョン", 9 | "home_root": "Root の実装", 10 | "home_refresh": "情報を更新", 11 | "home_refreshing": "更新中...", 12 | "home_status": "ステータス", 13 | "home_status_online": "オンライン", 14 | "home_status_offline": "オフライン", 15 | "home_clock_date": "時計の日付", 16 | "home_clock_time": "時計の時刻", 17 | 18 | "menu_title": "メインメニュー", 19 | "menu_force_clear": "Play ストアの強制停止とデータ消去", 20 | "menu_keybox": "Yuri Keybox を設定", 21 | "menu_target": "Target.txt を設定", 22 | "menu_necessary": "必要なアプリのみを設定", 23 | "menu_patch": "セキュリティパッチを設定", 24 | 25 | "advance_menu_title": "高度なメニュー", 26 | "advance_fix_detect_hma": "HMA の検出を修正", 27 | "advance_fix_detect_lsposed": "LSPosed の検出を修正 (2)", 28 | "advance_fix_detect_pif": "PIF の検出を修正 (1)", 29 | "advance_fix_detect_recovery_file": "リカバリーファイルの検出を修正", 30 | "advance_kill_all": "すべてのプロセスを停止", 31 | "advance_wdevinel1": "Widevine L1 の修正", 32 | "advance_set_verified_boot": "確認付きブートハッシュを設定", 33 | 34 | "update_title": "更新とサポート", 35 | "update_desc": "YuriKey の最新バージョン、バグ修正、新機能についての最新情報を入手しましょう。", 36 | "update_github": "GitHub を表示", 37 | "update_telegram": "Telegram チャンネルに参加", 38 | "update_note": "更新、貢献、技術的な議論については Telegram チャンネルに参加するか、GitHub を確認してください。", 39 | 40 | "settings_contributors": "プロジェクトの貢献者", 41 | 42 | "role_Founder & Module Developer": "創設者とモジュールの開発者", 43 | "role_Module Developer": "モジュールの開発者", 44 | "role_WebUI Developer": "WebUI の開発者", 45 | "role_Ex Module Developer": "モジュールの元開発者", 46 | 47 | "executing": "「{script}」を実行中...", 48 | "success": "「{script}」の実行に成功しました。", 49 | "failed": "「{script}」の実行に失敗しました。", 50 | "timeout": "「{script}」がタイムアウトしました。", 51 | "ksu_not_available": "KernelSU exec API は使用できません。", 52 | 53 | "status_online": "ステータス: オンライン", 54 | "status_offline": "ステータス: オフライン", 55 | "home_refresh_failed": "情報を更新できませんでした。", 56 | "home_no_internet": "インターネット接続がありません。", 57 | "home_connected": "接続済み", 58 | "home_disconnected": "切断済み" 59 | } 60 | -------------------------------------------------------------------------------- /Module/webroot/lang/ar.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "الرئيسية", 3 | "nav_menu": "القائمة", 4 | "nav_update": "تحديث", 5 | "nav_advancemenu": "القائمة المتقدمة", 6 | "nav_settings": "الإعدادات", 7 | 8 | "home_version": "إصدار الإضافة", 9 | "home_root": "مدير الروت", 10 | "home_refresh": "تحديث المعلومات", 11 | "home_refreshing": "جارٍ التحديث...", 12 | "home_status": "الحالة", 13 | "home_status_online": "متصل", 14 | "home_status_offline": "غير متصل", 15 | "home_clock_date": "التاريخ", 16 | "home_clock_time": "الوقت", 17 | 18 | "menu_title": "القائمة الرئيسية", 19 | "menu_force_clear": "إيقاف إجباري ومسح بيانات تطبيق متجر بلاي", 20 | "menu_keybox": "إعداد Yuri Keybox", 21 | "menu_target": "إعداد target.txt", 22 | "menu_necessary": "تعيين التطبيق الضروري", 23 | "menu_patch": "تطبيق تصحيح الأمان", 24 | 25 | "advance_menu_title": "القائمة المتقدمة", 26 | "advance_fix_detect_hma": "إصلاح اكتشاف HMA", 27 | "advance_fix_detect_lsposed": "إصلاح اكتشاف lsposed (2)", 28 | "advance_fix_detect_pif": "إصلاح اكتشاف PIF (1)", 29 | "advance_fix_detect_recovery_file": "إصلاح اكتشاف ملف recovery", 30 | "advance_kill_all": "إنهاء كل العمليات", 31 | "advance_wdevinel1": "إصلاح Widevine L1", 32 | "advance_set_verified_boot": "تعيين verified boot hash", 33 | 34 | "update_title": "التحديث والدعم", 35 | "update_desc": "ابقَ على اطلاع بأحدث إصدار من Yurikey، إصلاحات الأخطاء، والميزات الجديدة.", 36 | "update_github": "عرض على GitHub", 37 | "update_telegram": "انضم إلى قناة Telegram", 38 | "update_note": "انضم إلى قناتنا على Telegram أو تحقق GitHub للحصول على التحديثات والمساهمات والنقاشات التقنية.", 39 | 40 | "settings_contributors": "المساهمون", 41 | 42 | "role_Founder & Module Developer": "المؤسس ومطور الإضافة", 43 | "role_Module Developer": "مطور الإضافة", 44 | "role_WebUI Developer": "مطور واجهة الويب", 45 | "role_Ex Module Developer": "مطور الإضافة السابق", 46 | 47 | "executing": "جارٍ تشغيل \"{script}\"...", 48 | "success": "تم تشغيل \"{script}\" بنجاح.", 49 | "failed": "فشل في تشغيل \"{script}\".", 50 | "timeout": "انتهت مهلة \"{script}\".", 51 | "ksu_not_available": "KernelSU exec API غير متوفر.", 52 | 53 | "status_online": "الحالة: متصل", 54 | "status_offline": "الحالة: غير متصل", 55 | "home_refresh_failed": "فشل في تحديث المعلومات.", 56 | "home_no_internet": "لا يوجد اتصال بالإنترنت.", 57 | "home_connected": "متصل", 58 | "home_disconnected": "غير متصل" 59 | } 60 | -------------------------------------------------------------------------------- /Module/Yuri/target_txt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | log_message() { 4 | echo "$(date +%Y-%m-%d\ %H:%M:%S) [SET_TARGET] $1" 5 | } 6 | 7 | log_message "Start" 8 | 9 | t='/data/adb/tricky_store/target.txt' 10 | tees='/data/adb/tricky_store/tee_status' 11 | 12 | # tee status 13 | teeBroken="false" 14 | if [ -f "$tees" ]; then 15 | teeBroken=$(grep -E '^teeBroken=' "$tees" | cut -d '=' -f2 2>/dev/null || echo "false") 16 | if [ -z "$teeBroken" ]; then 17 | log_message "ERROR: Failed to parse teeBroken status" 18 | exit 1 19 | fi 20 | fi 21 | 22 | # add list special 23 | rm -rf $"t" 24 | fixed_targets="\ 25 | android 26 | com.android.vending! 27 | com.google.android.gsf! 28 | com.google.android.gms! 29 | io.github.vvb2060.keyattestation! 30 | io.github.vvb2060.mahoshojo! 31 | com.google.android.contactkeys! 32 | com.google.android.ims! 33 | com.google.android.safetycore! 34 | com.google.android.apps.walletnfcrel! 35 | com.google.android.apps.nbu.paisa.user! 36 | gr.nikolasspyr.integritycheck! 37 | com.youhu.laifu! 38 | com.whatsapp! 39 | com.whatsapp.w4b! 40 | com.openai.chatgpt! 41 | com.reveny.nativecheck! 42 | icu.nullptr.nativetest! 43 | com.android.nativetest! 44 | io.liankong.riskdetector! 45 | me.garfieldhan.holmes! 46 | luna.safe.luna! 47 | com.zhenxi.hunter! 48 | com.studio.duckdetector!" 49 | for entry in $fixed_targets; do 50 | if ! echo "$entry" >> "$t"; then 51 | log_message "ERROR: Failed to write $entry to $t" 52 | exit 1 53 | fi 54 | done 55 | 56 | # add list 57 | log_message "Writing" 58 | 59 | add_packages() { 60 | pkgs=$(pm list packages "$1" 2>/dev/null) 61 | if [ $? -ne 0 ] || [ -z "$pkgs" ]; then 62 | log_message "ERROR: Failed to list packages with flag $1" 63 | exit 1 64 | fi 65 | 66 | echo "$pkgs" | cut -d ":" -f 2 | while read -r pkg; do 67 | if [ -n "$pkg" ] && ! grep -q "^$pkg" "$t"; then 68 | if [ "$teeBroken" = "true" ]; then 69 | if ! echo "$pkg!" >> "$t"; then 70 | log_message "ERROR: Failed to write $pkg! to $t" 71 | exit 1 72 | fi 73 | else 74 | if ! echo "$pkg" >> "$t"; then 75 | log_message "ERROR: Failed to write $pkg to $t" 76 | exit 1 77 | fi 78 | fi 79 | fi 80 | done 81 | } 82 | 83 | # add user apps 84 | add_packages "-3" 85 | 86 | # add system apps 87 | add_packages "-s" 88 | 89 | log_message "Finish" 90 | -------------------------------------------------------------------------------- /Module/webroot/lang/th.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "หน้าหลัก", 3 | "nav_menu": "เมนู", 4 | "nav_update": "อัปเดต", 5 | "nav_advancemenu": "เมนู +", 6 | "nav_settings": "การตั้งค่า", 7 | 8 | "home_version": "เวอร์ชันโมดูล", 9 | "home_root": "การติดตั้งรูท", 10 | "home_refresh": "รีเฟรชข้อมูล", 11 | "home_refreshing": "กำลังรีเฟรช...", 12 | "home_status": "สถานะ", 13 | "home_status_online": "ออนไลน์", 14 | "home_status_offline": "ออฟไลน์", 15 | "home_clock_date": "วันที่", 16 | "home_clock_time": "เวลา", 17 | 18 | "menu_title": "เมนูหลัก", 19 | "menu_force_clear": "บังคับหยุด & ล้างข้อมูล Play Store", 20 | "menu_keybox": "ตั้งค่า Yuri Keybox", 21 | "menu_target": "ตั้งค่า target.txt", 22 | "menu_necessary": "ตั้งค่าแอปที่จำเป็น", 23 | "menu_patch": "ใช้แพตช์ความปลอดภัย", 24 | 25 | "advance_menu_title": "เมนูล่วงหน้า", 26 | "advance_fix_detect_hma": "แก้ไขการตรวจจับ HMA", 27 | "advance_fix_detect_lsposed": "แก้ไขการตรวจจับ lsposed (2)", 28 | "advance_fix_detect_pif": "แก้ไขการตรวจจับ PIF (1)", 29 | "advance_fix_detect_recovery_file": "แก้ไขการตรวจจับไฟล์กู้คืน", 30 | "advance_kill_all": "ฆ่ากระบวนการทั้งหมด", 31 | "advance_wdevinel1": "แก้ไข Widevine L1", 32 | "advance_set_verified_boot": "ตั้งค่า Verified Boothash", 33 | 34 | "update_title": "อัปเดตและสนับสนุน", 35 | "update_desc": "ติดตามเวอร์ชัน Yurikey ล่าสุด การแก้ไขบั๊ก และฟีเจอร์ใหม่ๆ", 36 | "update_github": "ดูบน GitHub", 37 | "update_telegram": "เข้าร่วมช่อง Telegram", 38 | "update_note": "เข้าร่วมช่อง Telegram ของเราหรือดูที่ GitHub สำหรับการอัปเดต การมีส่วนร่วม และการสนทนาทางเทคนิค", 39 | 40 | "settings_contributors": "ผู้ร่วมพัฒนาโครงการ", 41 | 42 | "role_Founder & Module Developer": "ผู้ก่อตั้งและนักพัฒนาโมดูล", 43 | "role_Module Developer": "นักพัฒนาโมดูล", 44 | "role_WebUI Developer": "นักพัฒนา WebUI", 45 | "role_Ex Module Developer": "อดีตนักพัฒนาโมดูล", 46 | 47 | "executing": "กำลังดำเนินการ \"{script}\"...", 48 | "success": "สคริปต์ \"{script}\" ดำเนินการสำเร็จแล้ว", 49 | "failed": "สคริปต์ \"{script}\" ล้มเหลวในการดำเนินการ", 50 | "timeout": "สคริปต์ \"{script}\" หมดเวลาการทำงาน", 51 | "ksu_not_available": "ไม่พบ API KernelSU exec", 52 | 53 | "status_online": "สถานะ: ออนไลน์", 54 | "status_offline": "สถานะ: ออฟไลน์", 55 | "home_refresh_failed": "รีเฟรชข้อมูลล้มเหลว", 56 | "home_no_internet": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต", 57 | "home_connected": "เชื่อมต่อแล้ว", 58 | "home_disconnected": "ตัดการเชื่อมต่อ" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Home", 3 | "nav_menu": "Menu", 4 | "nav_update": "Update", 5 | "nav_advancemenu": "Menu +", 6 | "nav_settings": "Settings", 7 | 8 | "home_version": "Module Version", 9 | "home_root": "Root Implementation", 10 | "home_refresh": "Refresh Info", 11 | "home_refreshing": "Refreshing...", 12 | "home_status": "Status", 13 | "home_status_online": "Online", 14 | "home_status_offline": "Offline", 15 | "home_clock_date": "Clock Date", 16 | "home_clock_time": "Clock Time", 17 | 18 | "menu_title": "MAIN MENU", 19 | "menu_force_clear": "Force Stop & Clear Data Play Store", 20 | "menu_keybox": "Set Up Yuri Keybox", 21 | "menu_target": "Set Up Target.txt", 22 | "menu_necessary": "Only Set Necessary App", 23 | "menu_patch": "Set Up Security Patch", 24 | 25 | "advance_menu_title": "Advanced Menu", 26 | "advance_fix_detect_hma": "Fix Detect HMA", 27 | "advance_fix_detect_lsposed": "Fix Detect lsposed (2)", 28 | "advance_fix_detect_pif": "Fix Detect PIF (1)", 29 | "advance_fix_detect_recovery_file": "Fix Detect Recovery File", 30 | "advance_kill_all": "Kill All Process", 31 | "advance_wdevinel1": "Fix Widevine L1", 32 | "advance_set_verified_boot": "Set Up Verified Boothash", 33 | 34 | "update_title": "UPDATE & SUPPORT", 35 | "update_desc": "Stay up to date with the latest version of Yurikey, bug fixes, and new features.", 36 | "update_github": "View on GitHub", 37 | "update_telegram": "Join Telegram Channel", 38 | "update_note": "Join our Telegram channel or check GitHub for updates, contributions, and technical discussions.", 39 | 40 | "settings_contributors": "Project Contributors", 41 | 42 | "role_Founder & Module Developer": "Founder & Module Developer", 43 | "role_Module Developer": "Module Developer", 44 | "role_WebUI Developer": "WebUI Developer", 45 | "role_Ex Module Developer": "Former Module Developer", 46 | 47 | "executing": "Executing \"{script}\"...", 48 | "success": "Script \"{script}\" executed successfully.", 49 | "failed": "Failed to execute script \"{script}\".", 50 | "timeout": "Script \"{script}\" timed out.", 51 | "ksu_not_available": "KernelSU exec API not available.", 52 | 53 | "status_online": "Status: Online", 54 | "status_offline": "Status: Offline", 55 | "home_refresh_failed": "Failed to refresh info.", 56 | "home_no_internet": "No internet connection.", 57 | "home_connected": "Connected", 58 | "home_disconnected": "Disconnected" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/hi.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "होम", 3 | "nav_menu": "मेनू", 4 | "nav_update": "अपडेट", 5 | "nav_advancemenu": "मेनू +", 6 | "nav_settings": "सेटिंग्स", 7 | 8 | "home_version": "मॉड्यूल वर्जन", 9 | "home_root": "रूट इम्प्लीमेंटेशन", 10 | "home_refresh": "रिफ्रेश करें", 11 | "home_refreshing": "रिफ्रेश हो रहा है...", 12 | "home_status": "स्टेटस", 13 | "home_status_online": "ऑनलाइन", 14 | "home_status_offline": "ऑफलाइन", 15 | "home_clock_date": "डेट", 16 | "home_clock_time": "टाइम", 17 | 18 | "menu_title": "मेनू", 19 | "menu_force_clear": "फोर्स स्टॉप और प्ले स्टोर डेटा क्लियर करें", 20 | "menu_keybox": "यूरी कीबॉक्स सेटअप करें", 21 | "menu_target": "टार्गेट.टेक्स्ट सेटअप करें", 22 | "menu_necessary": "आवश्यक ऐप सेट करें", 23 | "menu_patch": "सिक्योरिटी पैच सेटअप करें", 24 | 25 | "advance_menu_title": "एडवांस्ड मेनू", 26 | "advance_fix_detect_hma": "HMA डिटेक्शन फिक्स करें", 27 | "advance_fix_detect_lsposed": "LSPosed डिटेक्शन फिक्स करें (2)", 28 | "advance_fix_detect_pif": "PIF डिटेक्शन फिक्स करें (1)", 29 | "advance_fix_detect_recovery_file": "रिकवरी फाइल डिटेक्शन फिक्स करें", 30 | "advance_kill_all": "सभी प्रक्रिया को मार डालो", 31 | "advance_wdevinel1": "Widevine L1 फिक्स करें", 32 | "advance_set_verified_boot": "वेरिफाइड बूटहैश सेटअप करें", 33 | 34 | "update_title": "अपडेट और सपोर्ट", 35 | "update_desc": "यूरीकी का लेटेस्ट वर्जन, बग फिक्स और नए फीचर्स के साथ अपडेट रहें।", 36 | "update_github": "गिटहब पर देखें", 37 | "update_telegram": "टेलीग्राम चैनल जॉइन करें", 38 | "update_note": "अपडेट्स, कॉन्ट्रिब्यूशन और टेक्निकल डिस्कशन के लिए हमारे टेलीग्राम चैनल से जुड़ें या गिटहब चेक करें।", 39 | 40 | "settings_contributors": "प्रोजेक्ट कंट्रीब्यूटर्स", 41 | 42 | "role_Founder & Module Developer": "फाउंडर और मॉड्यूल डेवलपर", 43 | "role_Module Developer": "मॉड्यूल डेवलपर", 44 | "role_WebUI Developer": "वेबयूआई डेवलपर", 45 | "role_Ex Module Developer": "पूर्व मॉड्यूल डेवलपर", 46 | 47 | "executing": "\"{script}\" एक्जीक्यूट हो रहा है...", 48 | "success": "\"{script}\" स्क्रिप्ट सक्सेसफुली एक्जीक्यूट हुई।", 49 | "failed": "\"{script}\" स्क्रिप्ट फेल हो गई।", 50 | "timeout": "\"{script}\" स्क्रिप्ट टाइमआउट हो गई।", 51 | "ksu_not_available": "कर्नेलएसयू एक्जीक्यूट एपीआई उपलब्ध नहीं है।", 52 | 53 | "status_online": "स्टेटस: ऑनलाइन", 54 | "status_offline": "स्टेटस: ऑफलाइन", 55 | "home_refresh_failed": "रिफ्रेश फेल हो गया।", 56 | "home_no_internet": "इंटरनेट कनेक्शन नहीं है।", 57 | "home_connected": "कनेक्टेड", 58 | "home_disconnected": "डिस्कनेक्टेड" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/tr.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Ana Sayfa", 3 | "nav_menu": "Menü", 4 | "nav_update": "Güncelle", 5 | "nav_advancemenu": "Gelişmiş Menü", 6 | "nav_settings": "Ayarlar", 7 | 8 | "home_version": "Modül Sürümü", 9 | "home_root": "Root Uygulaması", 10 | "home_refresh": "Bilgileri Yenile", 11 | "home_refreshing": "Yenileniyor...", 12 | "home_status": "Durum", 13 | "home_status_online": "Çevrimiçi", 14 | "home_status_offline": "Çevrimdışı", 15 | "home_clock_date": "Tarih", 16 | "home_clock_time": "Saat", 17 | 18 | "menu_title": "ANA MENÜ", 19 | "menu_force_clear": "Play Store'u Durdur & Verilerini Temizle", 20 | "menu_keybox": "Yuri Keybox Kur", 21 | "menu_target": "target.txt Ayarla", 22 | "menu_necessary": "Sadece önerilen uygulamaları ayarlayın", 23 | "menu_patch": "Güvenlik Yamasını Uygula", 24 | 25 | "advance_menu_title": "Gelişmiş Menü", 26 | "advance_fix_detect_hma": "HMA Tespitini Düzelt", 27 | "advance_fix_detect_lsposed": "lsposed Tespitini Düzelt (2)", 28 | "advance_fix_detect_pif": "PIF Tespitini Düzelt (1)", 29 | "advance_fix_detect_recovery_file": "Recovery Dosyası Tespitini Düzelt", 30 | "advance_kill_all": "Tüm İşlemleri Sonlandır", 31 | "advance_wdevinel1": "Widevine L1'i Düzelt", 32 | "advance_set_verified_boot": "Verified Boothash Ayarla", 33 | 34 | "update_title": "GÜNCELLEME & DESTEK", 35 | "update_desc": "Yurikey'in en son sürümü, hata düzeltmeleri ve yeni özelliklerle güncel kal.", 36 | "update_github": "GitHub'da Görüntüle", 37 | "update_telegram": "Telegram Kanalına Katıl", 38 | "update_note": "Güncellemeler, katkılar ve teknik tartışmalar için Telegram kanalımıza katılabilir veya GitHub'ı kontrol edebilirsin.", 39 | 40 | "settings_contributors": "Proje Katkıcıları", 41 | 42 | "role_Founder & Module Developer": "Kurucu & Modül Geliştirici", 43 | "role_Module Developer": "Modül Geliştirici", 44 | "role_WebUI Developer": "WebUI Geliştirici", 45 | "role_Ex Module Developer": "Eski Modül Geliştirici", 46 | 47 | "executing": "\"{script}\" çalıştırılıyor...", 48 | "success": "\"{script}\" başarıyla çalıştırıldı.", 49 | "failed": "\"{script}\" çalıştırılamadı.", 50 | "timeout": "\"{script}\" zaman aşımına uğradı.", 51 | "ksu_not_available": "KernelSU exec API mevcut değil.", 52 | 53 | "status_online": "Durum: Çevrimiçi", 54 | "status_offline": "Durum: Çevrimdışı", 55 | "home_refresh_failed": "Bilgiler yenilenemedi.", 56 | "home_no_internet": "İnternet bağlantısı yok.", 57 | "home_connected": "Bağlı", 58 | "home_disconnected": "Bağlı Değil" 59 | } -------------------------------------------------------------------------------- /doc/README_ja-JP.md: -------------------------------------------------------------------------------- 1 | # YuriKey 2 | ![Artifacts](./banner.webp) 3 | 4 | 5 | [![Telegram](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/yuriiroot) 6 | [![latest release](https://img.shields.io/github/v/release/dpejoh/yurikey?label=Release&logo=github)](https://github.com/dpejoh/yurikey/releases/latest) 7 | [![CI](https://github.com/dpejoh/yurikey/actions/workflows/build.yml/badge.svg)](https://github.com/dpejoh/yurikey/actions/workflows/build.yml) 8 | 9 | Strong Integrity の取得を簡単に実現する Systemless モジュール 10 | 11 | [ダウンロード](https://github.com/dpejoh/yurikey/releases/latest) 12 | 13 | [更新履歴](https://raw.githubusercontent.com/dpejoh/yurikey/main/changelog.md) 14 | 15 | Telegram グループ/チャンネル: 16 | 17 | https://t.me/dpejoh 18 | 19 | https://t.me/yuriiroot 20 | 21 | https://t.me/yurichattt 22 | 23 | https://t.me/yuriiarchives 24 | 25 | https://t.me/yuriifeedback 26 | 27 | https://t.me/yuriiservice 28 | 29 | https://t.me/yurikernel 30 | 31 | ## どうすれば Strong Integrity を取得できますか? 32 | - [Play Integrity Inject](https://github.com/KOWX712/PlayIntegrityFix/releases/latest) または [Play Integrity Fork](https://github.com/osm0sis/PlayIntegrityFork/releases/latest) をインストールしてください 33 | - [Tricky Store](https://github.com/5ec1cff/TrickyStore/releases/latest) をインストールしてください 34 | - [Yurikey Manager](https://github.com/dpejoh/yurikey/releases/latest) を root マネージャーにインストールしてください (Magisk/Apatch/KernelSU/KernelSU のフォーク) 35 | - アクションボタンを押してください 36 | 37 | ## ⚠️注意 38 | > [!NOTE] 39 | > 40 | > action.sh またはモジュールのインストール時に以下のエラーが発生した場合は、モジュールを追加でインストールする必要があります。 41 | > 42 | 43 | "ERROR: Tricky Store module not found!" のエラーが発生した場合 44 | > [Tricky Store](https://github.com/5ec1cff/TrickyStore/releases/latest) 45 | 46 | "ERROR: curl or wget not found!" 47 | "Failed to fetch remote keybox" のエラーが発生した場合 48 | > [BusyBox](https://mmrl.dev/repository/grdoglgmr/busybox-ndk) 49 | 50 | ## Zakosign によるモジュールの署名 51 | > [!NOTE] 52 | > 53 | > YuriKey バージョン 1.90 以降から [Zakosign](https://github.com/Lama3L9R/zakosign) ツールを使用した署名に変更しました。これによりモジュールの zip ファイル内の改変を事前に検出できるようになっています。 54 | > モジュールの信頼性について質問がある場合、これですべての質問に答えることができるかもしれません。 55 | > 56 | > このツールを開発してくださった [Lama3L9R](https://github.com/Lama3L9R) に感謝を申し上げます。 57 | > 58 | 59 | ## 貢献者 60 | [Yuri](https://github.com/Yurii0307) 61 | [yourbestregard](https://github.com/yourbestregard) 62 | [cvnertnc](https://github.com/cvnertnc) 63 | [ZG089](https://github.com/ZG089) 64 | [Tam](https://github.com/Tam97123) 65 | [Munch](https://github.com/SudoNothing404) 66 | [Wes](https://github.com/ihatenodejs) 67 | [Khx](https://github.com/dpejoh) 68 | 69 | -------------------------------------------------------------------------------- /Module/webroot/lang/bn.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "হোম", 3 | "nav_menu": "মেনু", 4 | "nav_update": "আপডেট", 5 | "nav_advancemenu": "মেনু +", 6 | "nav_settings": "সেটিংস", 7 | 8 | "home_version": "মডিউল সংস্করণ", 9 | "home_root": "রুট বাস্তবায়ন", 10 | "home_refresh": "তথ্য রিফ্রেশ করুন", 11 | "home_refreshing": "রিফ্রেশ হচ্ছে...", 12 | "home_status": "স্থিতি", 13 | "home_status_online": "অনলাইন", 14 | "home_status_offline": "অফলাইন", 15 | "home_clock_date": "ঘড়ির তারিখ", 16 | "home_clock_time": "ঘড়ির সময়", 17 | 18 | "menu_title": "প্রধান মেনু", 19 | "menu_force_clear": "প্লে স্টোরের ডেটা জোরপূর্বক বন্ধ ও পরিষ্কার করুন", 20 | "menu_keybox": "ইউরি কিবক্স সেট আপ করুন", 21 | "menu_target": "টার্গেট.টেক্সট সেট আপ করুন", 22 | "menu_necessary": "প্রয়োজনীয় অ্যাপ সেট করুন", 23 | "menu_patch": "নিরাপত্তা প্যাচ প্রয়োগ করুন", 24 | 25 | "advance_menu_title": "উন্নত মেনু", 26 | "advance_fix_detect_hma": "এইচএমএ সনাক্তকরণ ঠিক করুন", 27 | "advance_fix_detect_lsposed": "এলএসপোজড সনাক্তকরণ ঠিক করুন (2)", 28 | "advance_fix_detect_pif": "পিআইএফ সনাক্তকরণ ঠিক করুন (1)", 29 | "advance_fix_detect_recovery_file": "রিকভারি ফাইল সনাক্তকরণ ঠিক করুন", 30 | "advance_kill_all": "সমস্ত প্রক্রিয়া হত্যা করুন", 31 | "advance_wdevinel1": "ওয়াইডভাইন L1 ঠিক করুন", 32 | "advance_set_verified_boot": "যাচাইকৃত বুটহ্যাশ সেট আপ করুন", 33 | 34 | "update_title": "আপডেট ও সমর্থন", 35 | "update_desc": "ইউরিকি-এর সর্বশেষ সংস্করণ, বাগ ফিক্স এবং নতুন ফিচারের সাথে আপডেট থাকুন।", 36 | "update_github": "গিটহাবে দেখুন", 37 | "update_telegram": "টেলিগ্রাম চ্যানেলে যোগ দিন", 38 | "update_note": "আপডেট, অবদান এবং প্রযুক্তিগত আলোচনার জন্য আমাদের টেলিগ্রাম চ্যানেলে যোগ দিন বা গিটহাব চেক করুন।", 39 | 40 | "settings_contributors": "প্রকল্প অবদানকারী", 41 | 42 | "role_Founder & Module Developer": "প্রতিষ্ঠাতা ও মডিউল ডেভেলপার", 43 | "role_Module Developer": "মডিউল ডেভেলপার", 44 | "role_WebUI Developer": "ওয়েবইউআই ডেভেলপার", 45 | "role_Ex Module Developer": "প্রাক্তন মডিউল ডেভেলপার", 46 | 47 | "executing": "\"{script}\" স্ক্রিপ্ট চালানো হচ্ছে...", 48 | "success": "\"{script}\" স্ক্রিপ্ট সফলভাবে চালানো হয়েছে।", 49 | "failed": "\"{script}\" স্ক্রিপ্ট চালাতে ব্যর্থ।", 50 | "timeout": "\"{script}\" স্ক্রিপ্টের সময় শেষ হয়েছে।", 51 | "ksu_not_available": "কার্নেলএসইউ এক্সেক এপিআই উপলব্ধ নয়।", 52 | 53 | "status_online": "স্থিতি: অনলাইন", 54 | "status_offline": "স্থিতি: অফলাইন", 55 | "home_refresh_failed": "তথ্য রিফ্রেশ করতে ব্যর্থ।", 56 | "home_no_internet": "ইন্টারনেট সংযোগ নেই।", 57 | "home_connected": "সংযুক্ত", 58 | "home_disconnected": "সংযোগ বিচ্ছিন্ন" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/id.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Beranda", 3 | "nav_menu": "Menu", 4 | "nav_update": "Perbarui", 5 | "nav_advancemenu": "Menu +", 6 | "nav_settings": "Pengaturan", 7 | 8 | "home_version": "Versi Modul", 9 | "home_root": "Implementasi Root", 10 | "home_refresh": "Segarkan Info", 11 | "home_refreshing": "Menyegarkan...", 12 | "home_status": "Status", 13 | "home_status_online": "Online", 14 | "home_status_offline": "Offline", 15 | "home_clock_date": "Tanggal Jam", 16 | "home_clock_time": "Waktu Jam", 17 | 18 | "menu_title": "MENU UTAMA", 19 | "menu_force_clear": "Paksa Berhenti & Bersihkan Data Play Store", 20 | "menu_keybox": "Atur Yuri Keybox", 21 | "menu_target": "Atur target.txt", 22 | "menu_necessary": "Atur aplikasi yang diperlukan", 23 | "menu_patch": "Terapkan Patch Keamanan", 24 | 25 | "advance_menu_title": "Menu Lanjutan", 26 | "advance_fix_detect_hma": "Perbaiki Deteksi HMA", 27 | "advance_fix_detect_lsposed": "Perbaiki Deteksi lsposed (2)", 28 | "advance_fix_detect_pif": "Perbaiki Deteksi PIF (1)", 29 | "advance_fix_detect_recovery_file": "Perbaiki Deteksi File Recovery", 30 | "advance_kill_all": "Matikan Semua Proses", 31 | "advance_wdevinel1": "Perbaiki Widevine L1", 32 | "advance_set_verified_boot": "Setel Verified Boothash", 33 | 34 | "update_title": "PEMBARUAN & DUKUNGAN", 35 | "update_desc": "Tetap terbaru dengan versi Yurikey terbaru, perbaikan bug, dan fitur baru.", 36 | "update_github": "Lihat di GitHub", 37 | "update_telegram": "Bergabung dengan Channel Telegram", 38 | "update_note": "Bergabunglah dengan channel Telegram kami atau cek GitHub untuk pembaruan, kontribusi, dan diskusi teknis.", 39 | 40 | "settings_contributors": "Kontributor Proyek", 41 | 42 | "role_Founder & Module Developer": "Pendiri & Pengembang Modul", 43 | "role_Module Developer": "Pengembang Modul", 44 | "role_WebUI Developer": "Pengembang WebUI", 45 | "role_Ex Module Developer": "Mantan Pengembang Modul", 46 | 47 | "executing": "Menjalankan \"{script}\"...", 48 | "success": "Script \"{script}\" berhasil dijalankan.", 49 | "failed": "Gagal menjalankan script \"{script}\".", 50 | "timeout": "Script \"{script}\" gagal merespon (timeout).", 51 | "ksu_not_available": "API KernelSU exec tidak tersedia.", 52 | 53 | "status_online": "Status: Online", 54 | "status_offline": "Status: Offline", 55 | "home_refresh_failed": "Gagal menyegarkan info.", 56 | "home_no_internet": "Tidak ada koneksi internet.", 57 | "home_connected": "Terhubung", 58 | "home_disconnected": "Terputus" 59 | } 60 | -------------------------------------------------------------------------------- /Module/webroot/lang/ms.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Laman Utama", 3 | "nav_menu": "Menu", 4 | "nav_update": "Kemas Kini", 5 | "nav_advancemenu": "Menu +", 6 | "nav_settings": "Tetapan", 7 | 8 | "home_version": "Versi Modul", 9 | "home_root": "Pelaksanaan Root", 10 | "home_refresh": "Segarkan Maklumat", 11 | "home_refreshing": "Sedang Menyegarkan...", 12 | "home_status": "Status", 13 | "home_status_online": "Dalam Talian", 14 | "home_status_offline": "Luar Talian", 15 | "home_clock_date": "Tarikh Jam", 16 | "home_clock_time": "Masa Jam", 17 | 18 | "menu_title": "MENU UTAMA", 19 | "menu_force_clear": "Paksa Berhenti & Kosongkan Data Play Store", 20 | "menu_keybox": "Sediakan Yuri Keybox", 21 | "menu_target": "Sediakan target.txt", 22 | "menu_necessary": "Atur aplikasi yang diperlukan", 23 | "menu_patch": "Terapkan Tampalan Keselamatan", 24 | 25 | "advance_menu_title": "Menu Lanjutan", 26 | "advance_fix_detect_hma": "Betulkan Pengesanan HMA", 27 | "advance_fix_detect_lsposed": "Betulkan Pengesanan lsposed (2)", 28 | "advance_fix_detect_pif": "Betulkan Pengesanan PIF (1)", 29 | "advance_fix_detect_recovery_file": "Betulkan Pengesanan Fail Pemulihan", 30 | "advance_kill_all": "Bunuh Semua Proses", 31 | "advance_wdevinel1": "Betulkan Widevine L1", 32 | "advance_set_verified_boot": "Tetapkan Verified Boothash", 33 | 34 | "update_title": "KEMAS KINI & SOKONGAN", 35 | "update_desc": "Sentiasa kemas kini dengan versi Yurikey terkini, pembaikan pepijat, dan ciri baru.", 36 | "update_github": "Lihat di GitHub", 37 | "update_telegram": "Sertai Saluran Telegram", 38 | "update_note": "Sertai saluran Telegram kami atau semak GitHub untuk kemas kini, sumbangan, dan perbincangan teknikal.", 39 | 40 | "settings_contributors": "Penyumbang Projek", 41 | 42 | "role_Founder & Module Developer": "Pengasas & Pembangun Modul", 43 | "role_Module Developer": "Pembangun Modul", 44 | "role_WebUI Developer": "Pembangun WebUI", 45 | "role_Ex Module Developer": "Bekas Pembangun Modul", 46 | 47 | "executing": "Menjalankan \"{script}\"...", 48 | "success": "Skrip \"{script}\" berjaya dijalankan.", 49 | "failed": "Gagal menjalankan skrip \"{script}\".", 50 | "timeout": "Skrip \"{script}\" tamat masa.", 51 | "ksu_not_available": "API KernelSU exec tidak tersedia.", 52 | 53 | "status_online": "Status: Dalam Talian", 54 | "status_offline": "Status: Luar Talian", 55 | "home_refresh_failed": "Gagal menyegarkan maklumat.", 56 | "home_no_internet": "Tiada sambungan internet.", 57 | "home_connected": "Bersambung", 58 | "home_disconnected": "Terputus" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/vn.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Trang Chủ", 3 | "nav_menu": "Menu", 4 | "nav_update": "Cập Nhật", 5 | "nav_advancemenu": "Menu +", 6 | "nav_settings": "Cài Đặt", 7 | 8 | "home_version": "Phiên Bản Module", 9 | "home_root": "Triển Khai Root", 10 | "home_refresh": "Làm Mới Thông Tin", 11 | "home_refreshing": "Đang làm mới...", 12 | "home_status": "Trạng Thái", 13 | "home_status_online": "Trực Tuyến", 14 | "home_status_offline": "Ngoại Tuyến", 15 | "home_clock_date": "Ngày", 16 | "home_clock_time": "Giờ", 17 | 18 | "menu_title": "MENU CHÍNH", 19 | "menu_force_clear": "Buộc Dừng & Xóa Dữ Liệu Cửa Hàng Play", 20 | "menu_keybox": "Thiết Lập Yuri Keybox", 21 | "menu_target": "Thiết Lập Target.txt", 22 | "menu_necessary": "Chỉ Thiết lập ứng dụng cần thiết", 23 | "menu_patch": "Thiết lập Security Patch", 24 | 25 | "advance_menu_title": "Menu Nâng Cao", 26 | "advance_fix_detect_hma": "Sửa Phát Hiện HMA", 27 | "advance_fix_detect_lsposed": "Sửa Phát Hiện lsposed (2)", 28 | "advance_fix_detect_pif": "Sửa Phát Hiện PIF (1)", 29 | "advance_fix_detect_recovery_file": "Sửa Phát Hiện File Recovery (TWRP)", 30 | "advance_kill_all": "Giết tất cả", 31 | "advance_wdevinel1": "Sửa Widevine L1", 32 | "advance_set_verified_boot": "Đặt Verified Boothash", 33 | 34 | "update_title": "CẬP NHẬT & HỖ TRỢ", 35 | "update_desc": "Luôn cập nhật với phiên bản Yurikey mới nhất, sửa lỗi và tính năng mới.", 36 | "update_github": "Xem trên GitHub", 37 | "update_telegram": "Tham gia Kênh Telegram", 38 | "update_note": "Tham gia kênh Telegram của chúng tôi hoặc kiểm tra GitHub để cập nhật, đóng góp và thảo luận kỹ thuật.", 39 | 40 | "settings_contributors": "Những Người Đóng Góp Dự Án", 41 | 42 | "role_Founder & Module Developer": "Người Sáng Lập & Nhà Phát Triển Module", 43 | "role_Module Developer": "Nhà Phát Triển Module", 44 | "role_WebUI Developer": "Nhà Phát Triển Giao Diện Web", 45 | "role_Ex Module Developer": "Cựu Nhà Phát Triển Module", 46 | 47 | "executing": "Đang thực thi \"{script}\"...", 48 | "success": "Script \"{script}\" đã thực thi thành công.", 49 | "failed": "Thực thi script \"{script}\" thất bại.", 50 | "timeout": "Script \"{script}\" hết thời gian chờ.", 51 | "ksu_not_available": "API KernelSU exec không khả dụng.", 52 | 53 | "status_online": "Trạng thái: Trực tuyến", 54 | "status_offline": "Trạng thái: Ngoại tuyến", 55 | "home_refresh_failed": "Làm mới thông tin thất bại.", 56 | "home_no_internet": "Không có kết nối internet.", 57 | "home_connected": "Đã kết nối", 58 | "home_disconnected": "Mất kết nối" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/pt-br.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Home", 3 | "nav_menu": "Menu", 4 | "nav_update": "Update", 5 | "nav_advancemenu": "Menu +", 6 | "nav_settings": "Config", 7 | 8 | "home_version": "Versão do Módulo", 9 | "home_root": "Tipo de Root", 10 | "home_refresh": "Atualizar", 11 | "home_refreshing": "Atualizando...", 12 | "home_status": "Status", 13 | "home_status_online": "Online", 14 | "home_status_offline": "Offline", 15 | "home_clock_date": "Data", 16 | "home_clock_time": "Hora", 17 | 18 | "menu_title": "MENU PRINCIPAL", 19 | "menu_force_clear": "Fechar & Limpar os Dados da PlayStore", 20 | "menu_keybox": "Configurar Yuri Keybox", 21 | "menu_target": "Configurar Target.txt", 22 | "menu_necessary": "Configura l'aplicació necessària", 23 | "menu_patch": "Configurar o Patch de Segurança", 24 | 25 | "advance_menu_title": "Menu Avançado", 26 | "advance_fix_detect_hma": "Reparar Detecção HMA", 27 | "advance_fix_detect_lsposed": "Reparar Detecção lsposed (2)", 28 | "advance_fix_detect_pif": "Reparar Detecção PIF (1)", 29 | "advance_fix_detect_recovery_file": "Reparar Detecção Recovery File", 30 | "advance_kill_all": "Matar todos os processos", 31 | "advance_wdevinel1": "Reparar Widevine L1", 32 | "advance_set_verified_boot": "Configurar a Verificação do Boothash", 33 | 34 | "update_title": "ATUALIZAÇÃO & SUPORTE", 35 | "update_desc": "Mantenha-se atualizado com a versão mais recente do Yurikey, correções de bugs e novos recursos.", 36 | "update_github": "Ver no GitHub", 37 | "update_telegram": "Junte-se ao canal Telegram", 38 | "update_note": "Junte-se ao nosso canal no Telegram ou verifique o GitHub para atualizações, contribuições e discussões técnicas.", 39 | 40 | "settings_contributors": "Colaboradores do Projeto", 41 | 42 | "role_Founder & Module Developer": "Fundador e Desenvolvedor de Módulos", 43 | "role_Module Developer": "Desenvolvedor de Módulos", 44 | "role_WebUI Developer": "WebUI Desenvolver", 45 | "role_Ex Module Developer": "Ex-desenvolvedor de módulos", 46 | 47 | "executing": "Executing \"{script}\"...", 48 | "success": "Script \"{script}\" executed successfully.", 49 | "failed": "Failed to execute script \"{script}\".", 50 | "timeout": "Script \"{script}\" timed out.", 51 | "ksu_not_available": "KernelSU exec API not available.", 52 | 53 | "status_online": "Status: Online", 54 | "status_offline": "Status: Offline", 55 | "home_refresh_failed": "Falha ao atualizar as informações.", 56 | "home_no_internet": "Sem conexão com a internet.", 57 | "home_connected": "Conectado", 58 | "home_disconnected": "Desconectado" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/uka.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Головна", 3 | "nav_menu": "Меню", 4 | "nav_update": "Оновлення", 5 | "nav_advancemenu": "Меню +", 6 | "nav_settings": "Налаштування", 7 | 8 | "home_version": "Версія модуля", 9 | "home_root": "Реалізація Root", 10 | "home_refresh": "Оновити інформацію", 11 | "home_refreshing": "Оновлення...", 12 | "home_status": "Статус", 13 | "home_status_online": "Онлайн", 14 | "home_status_offline": "Офлайн", 15 | "home_clock_date": "Дата", 16 | "home_clock_time": "Час", 17 | 18 | "menu_title": "ГОЛОВНЕ МЕНЮ", 19 | "menu_force_clear": "Примусово зупинити та очистити дані Play Store", 20 | "menu_keybox": "Налаштувати Yuri Keybox", 21 | "menu_target": "Налаштувати Target.txt", 22 | "menu_necessary": "Встановити потрібний додаток", 23 | "menu_patch": "Налаштувати патч безпеки", 24 | 25 | "advance_menu_title": "Розширене меню", 26 | "advance_fix_detect_hma": "Виправити виявлення HMA", 27 | "advance_fix_detect_lsposed": "Виправити виявлення lsposed (2)", 28 | "advance_fix_detect_pif": "Виправити виявлення PIF (1)", 29 | "advance_fix_detect_recovery_file": "Виправити виявлення файлу відновлення", 30 | "advance_kill_all": "Знищити всі процеси", 31 | "advance_wdevinel1": "Виправити Widevine L1", 32 | "advance_set_verified_boot": "Налаштувати хеш перевіреного завантаження", 33 | 34 | "update_title": "ОНОВЛЕННЯ ТА ПІДТРИМКА", 35 | "update_desc": "Будьте в курсі останньої версії Yurikey, виправлень помилок та нових функцій.", 36 | "update_github": "Переглянути на GitHub", 37 | "update_telegram": "Приєднатися до Telegram каналу", 38 | "update_note": "Приєднуйтесь до нашого Telegram каналу або переглядайте GitHub для оновлень, внесків та технічних обговорень.", 39 | 40 | "settings_contributors": "Учасники проєкту", 41 | 42 | "role_Founder & Module Developer": "Засновник та розробник модуля", 43 | "role_Module Developer": "Розробник модуля", 44 | "role_WebUI Developer": "Розробник WebUI", 45 | "role_Ex Module Developer": "Колишній розробник модуля", 46 | 47 | "executing": "Виконання \"{script}\"...", 48 | "success": "Скрипт \"{script}\" успішно виконано.", 49 | "failed": "Не вдалося виконати скрипт \"{script}\".", 50 | "timeout": "Час виконання скрипта \"{script}\" вичерпано.", 51 | "ksu_not_available": "API виконання KernelSU недоступне.", 52 | 53 | "status_online": "Статус: Онлайн", 54 | "status_offline": "Статус: Офлайн", 55 | "home_refresh_failed": "Не вдалося оновити інформацію.", 56 | "home_no_internet": "Немає підключення до інтернету.", 57 | "home_connected": "Підключено", 58 | "home_disconnected": "Відключено" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Strona główna", 3 | "nav_menu": "Menu", 4 | "nav_update": "Aktualizacja", 5 | "nav_advancemenu": "Menu +", 6 | "nav_settings": "Ustawienia", 7 | 8 | "home_version": "Wersja modułu", 9 | "home_root": "Implementacja Root", 10 | "home_refresh": "Odśwież informacje", 11 | "home_refreshing": "Odświeżanie...", 12 | "home_status": "Status", 13 | "home_status_online": "Online", 14 | "home_status_offline": "Offline", 15 | "home_clock_date": "Data zegara", 16 | "home_clock_time": "Czas zegara", 17 | 18 | "menu_title": "MENU GŁÓWNE", 19 | "menu_force_clear": "Wymuś zatrzymanie i wyczyść dane Play Store", 20 | "menu_keybox": "Skonfiguruj Yuri Keybox", 21 | "menu_target": "Skonfiguruj Target.txt", 22 | "menu_necessary": "Ustaw potrzebną aplikację", 23 | "menu_patch": "Skonfiguruj łatkę bezpieczeństwa", 24 | 25 | "advance_menu_title": "Menu zaawansowane", 26 | "advance_fix_detect_hma": "Napraw wykrywanie HMA", 27 | "advance_fix_detect_lsposed": "Napraw wykrywanie lsposed (2)", 28 | "advance_fix_detect_pif": "Napraw wykrywanie PIF (1)", 29 | "advance_fix_detect_recovery_file": "Napraw wykrywanie pliku recovery", 30 | "advance_kill_all": "Zabij wszystkie procesy", 31 | "advance_wdevinel1": "Napraw Widevine L1", 32 | "advance_set_verified_boot": "Skonfiguruj hash zweryfikowanego rozruchu", 33 | 34 | "update_title": "AKTUALIZACJA I WSPARCIE", 35 | "update_desc": "Bądź na bieżąco z najnowszą wersją Yurikey, poprawkami błędów i nowymi funkcjami.", 36 | "update_github": "Zobacz na GitHub", 37 | "update_telegram": "Dołącz do kanału Telegram", 38 | "update_note": "Dołącz do naszego kanału Telegram lub sprawdź GitHub w celu aktualizacji, wkładu i dyskusji technicznych.", 39 | 40 | "settings_contributors": "Współtwórcy projektu", 41 | 42 | "role_Founder & Module Developer": "Założyciel i deweloper modułu", 43 | "role_Module Developer": "Deweloper modułu", 44 | "role_WebUI Developer": "Deweloper interfejsu webowego", 45 | "role_Ex Module Developer": "Były deweloper modułu", 46 | 47 | "executing": "Wykonywanie \"{script}\"...", 48 | "success": "Skrypt \"{script}\" wykonany pomyślnie.", 49 | "failed": "Nie udało się wykonać skryptu \"{script}\".", 50 | "timeout": "Skrypt \"{script}\" przekroczył limit czasu.", 51 | "ksu_not_available": "API exec KernelSU niedostępne.", 52 | 53 | "status_online": "Status: Online", 54 | "status_offline": "Status: Offline", 55 | "home_refresh_failed": "Nie udało się odświeżyć informacji.", 56 | "home_no_internet": "Brak połączenia z internetem.", 57 | "home_connected": "Połączony", 58 | "home_disconnected": "Rozłączony" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/ro-md.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Acasă", 3 | "nav_menu": "Meniu", 4 | "nav_update": "Actualizare", 5 | "nav_advancemenu": "Meniu +", 6 | "nav_settings": "Setări", 7 | 8 | "home_version": "Versiune Modul", 9 | "home_root": "Implementare Root", 10 | "home_refresh": "Actualizați Informația", 11 | "home_refreshing": "Actualizare...", 12 | "home_status": "Statut", 13 | "home_status_online": "Online", 14 | "home_status_offline": "Offline", 15 | "home_clock_date": "Data locală", 16 | "home_clock_time": "Ora locală", 17 | 18 | "menu_title": "MENIU PRINCIPAL", 19 | "menu_force_clear": "Forțare Stopare & Curățare Date pentru Play Store", 20 | "menu_keybox": "Setare Yuri Keybox", 21 | "menu_target": "Setare Target.txt", 22 | "menu_necessary": "Setați aplicația necesară", 23 | "menu_patch": "Setare Security Patch", 24 | 25 | "advance_menu_title": "Meniu avansat", 26 | "advance_fix_detect_hma": "Fixare Detect HMA", 27 | "advance_fix_detect_lsposed": "Fixare Detect lsposed (2)", 28 | "advance_fix_detect_pif": "Fixare Detect PIF (1)", 29 | "advance_fix_detect_recovery_file": "Fixare Detect Recovery File", 30 | "advance_kill_all": "Opriți toate procesele", 31 | "advance_wdevinel1": "Fixare Widevine L1", 32 | "advance_set_verified_boot": "Setare Verified Boothash", 33 | 34 | "update_title": "ACTUALIZARE & SUPORT", 35 | "update_desc": "Rămâneți la curent cu cea mai recentă versiune de Yurikey, corecțiile de erori și noile funcții.", 36 | "update_github": "Vedeți pe GitHub", 37 | "update_telegram": "Alăturați-vă la canalul din Telegram", 38 | "update_note": "Alăturați-vă canalului nostru de Telegram sau verificați GitHub pentru actualizări, contribuții și discuții tehnice..", 39 | 40 | "settings_contributors": "Contribuitorii Proiectului", 41 | 42 | "role_Founder & Module Developer": "Founder & Module Developer", 43 | "role_Module Developer": "Module Developer", 44 | "role_WebUI Developer": "WebUI Developer", 45 | "role_Ex Module Developer": "Former Module Developer", 46 | 47 | "executing": "Executare \"{script}\"...", 48 | "success": "Script-ul \"{script}\" a fost executat cu succes.", 49 | "failed": "Executrea script-ului \"{script}\" a eșuat.", 50 | "timeout": "Timpul pentru executarea cript-ului \"{script}\" a expirat.", 51 | "ksu_not_available": "KernelSU execuatabil API nu este disponibil.", 52 | 53 | "status_online": "Statut: Online", 54 | "status_offline": "Statut: Offline", 55 | "home_refresh_failed": "Reîmrospătarea informației a eșuat.", 56 | "home_no_internet": "Nu este conexiune internet.", 57 | "home_connected": "Conectat", 58 | "home_disconnected": "Deconectat" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/hu.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Home", 3 | "nav_menu": "Menü", 4 | "nav_update": "Frissítés", 5 | "nav_advancemenu": "Haladó menü", 6 | "nav_settings": "Beállítások", 7 | 8 | "home_version": "Modul verzió", 9 | "home_root": "Root megvalósítás", 10 | "home_refresh": "Frissítési információ", 11 | "home_refreshing": "Frissítés...", 12 | "home_status": "Állapot", 13 | "home_status_online": "Online", 14 | "home_status_offline": "Offline", 15 | "home_clock_date": "Dátum", 16 | "home_clock_time": "Idő", 17 | 18 | "menu_title": "FŐMENÜ", 19 | "menu_force_clear": "Kényszerített leállítás és Adat törlés Play Store", 20 | "menu_keybox": "Yuri Keybox beállítása", 21 | "menu_target": "Target.txt beállítása", 22 | "menu_necessary": "Állítsa be a szükséges alkalmazást", 23 | "menu_patch": "Security Patch beállítása", 24 | 25 | "advance_menu_title": "Haladó menü", 26 | "advance_fix_detect_hma": "Észlelt HMA javítása", 27 | "advance_fix_detect_lsposed": "Észlelt Lsposed javítása", 28 | "advance_fix_detect_pif": "Észlelt PIF javítása", 29 | "advance_fix_detect_recovery_file": "Észlelt Recovery fájl javítása", 30 | "advance_kill_all": "Ölj meg minden folyamatot", 31 | "advance_wdevinel1": "Widevine L1 javítása", 32 | "advance_set_verified_boot": "Ellenőrzött Boothash létrehozása", 33 | 34 | "update_title": "FRISSÍTÉS és TÁMOGATÁS", 35 | "update_desc": "Maradj naprakész a Yurikey legújabb verziójával, hibajavításaival és új funkcióival kapcsolatban.", 36 | "update_github": "Megtekintés a GitHub-on", 37 | "update_telegram": "Csatlakozás a Telegram csatornához", 38 | "update_note": "Csatlakozz Telegram csatornánkhoz, vagy látogass el a GitHub oldalra frissítésekért, hozzászólásokért és technikai megbeszélésekért.", 39 | 40 | "settings_contributors": "Projekt közreműködői", 41 | 42 | "role_Founder & Module Developer": "Alapító és modulfejlesztő", 43 | "role_Module Developer": "Modul fejlesztő", 44 | "role_WebUI Developer": "WebUI fejlesztő", 45 | "role_Ex Module Developer": "Korábbi modulfejlesztő", 46 | 47 | "executing": "Végrehajtó \"{script}\"...", 48 | "success": "Szkript \"{script}\" sikeresen végrehajtva.", 49 | "failed": "Nem sikerült végrehajtani a szkriptet \"{script}\".", 50 | "timeout": "Szkript \"{script}\" időtúllépés.", 51 | "ksu_not_available": "A KernelSU végrehajtási API nem érhető el.", 52 | 53 | "status_online": "Status: Online", 54 | "status_offline": "Status: Offline", 55 | "home_refresh_failed": "Nem sikerült frissíteni az információkat.", 56 | "home_no_internet": "Nincs internet kapcsolat.", 57 | "home_connected": "Csatlakozva", 58 | "home_disconnected": "Szétkapcsolt" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Главная", 3 | "nav_menu": "Меню", 4 | "nav_update": "Обновить", 5 | "nav_advancemenu": "Меню +", 6 | "nav_settings": "Настройки", 7 | 8 | "home_version": "Версия модуля", 9 | "home_root": "Реализация Root", 10 | "home_refresh": "Обновить информацию", 11 | "home_refreshing": "Обновление...", 12 | "home_status": "Статус", 13 | "home_status_online": "Онлайн", 14 | "home_status_offline": "Оффлайн", 15 | "home_clock_date": "Дата часов", 16 | "home_clock_time": "Время часов", 17 | 18 | "menu_title": "ГЛАВНОЕ МЕНЮ", 19 | "menu_force_clear": "Принудительная остановка и очистка данных Play Store", 20 | "menu_keybox": "Настроить Yuri Keybox", 21 | "menu_target": "Настроить Target.txt", 22 | "menu_necessary": "Установить необходимое приложение", 23 | "menu_patch": "Настроить патч безопасности", 24 | 25 | "advance_menu_title": "Расширенное меню", 26 | "advance_fix_detect_hma": "Исправить обнаружение HMA", 27 | "advance_fix_detect_lsposed": "Исправить обнаружение LSposed (2)", 28 | "advance_fix_detect_pif": "Исправить обнаружение PIF (1)", 29 | "advance_fix_detect_recovery_file": "Исправить обнаружение файла Recovery", 30 | "advance_kill_all": "Убить все процессы", 31 | "advance_wdevinel1": "Исправить Widevine L1", 32 | "advance_set_verified_boot": "Настроить проверенный Boothash", 33 | 34 | "update_title": "ОБНОВЛЕНИЯ И ПОДДЕРЖКА", 35 | "update_desc": "Будьте в курсе последней версии Yurikey, исправлений ошибок и новых возможностей.", 36 | "update_github": "Смотреть на GitHub", 37 | "update_telegram": "Присоединиться к каналу Telegram", 38 | "update_note": "Присоединяйтесь к нашему каналу в Telegram или проверьте GitHub на предмет обновлений, contribut'ов и технических обсуждений.", 39 | 40 | "settings_contributors": "Участники проекта", 41 | 42 | "role_Founder & Module Developer": "Основатель и разработчик модуля", 43 | "role_Module Developer": "Разработчик модуля", 44 | "role_WebUI Developer": "Разработчик WebUI", 45 | "role_Ex Module Developer": "Бывший разработчик модуля", 46 | 47 | "executing": "Выполнение \"{script}\"...", 48 | "success": "Скрипт \"{script}\" успешно выполнен.", 49 | "failed": "Не удалось выполнить скрипт \"{script}\".", 50 | "timeout": "Превышено время выполнения скрипта \"{script}\"", 51 | "ksu_not_available": "API исполнения KernelSU недоступно.", 52 | 53 | "status_online": "Статус: Онлайн", 54 | "status_offline": "Статус: Оффлайн", 55 | "home_refresh_failed": "Не удалось обновить информацию.", 56 | "home_no_internet": "Нет подключения к интернету.", 57 | "home_connected": "Подключено", 58 | "home_disconnected": "Отключено" 59 | } -------------------------------------------------------------------------------- /Module/webroot/lang/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Inicio", 3 | "nav_menu": "Menú", 4 | "nav_update": "Actualizar", 5 | "nav_advancemenu": "Menú +", 6 | "nav_settings": "Ajustes", 7 | 8 | "home_version": "Versión del Módulo", 9 | "home_root": "Implementación Root", 10 | "home_refresh": "Actualizar Info", 11 | "home_refreshing": "Refrescando...", 12 | "home_status": "Estatus", 13 | "home_status_online": "En línea", 14 | "home_status_offline": "Desconectado", 15 | "home_clock_date": "Fecha", 16 | "home_clock_time": "Hora", 17 | 18 | "menu_title": "Menú Principal", 19 | "menu_force_clear": "Forzar Detención y Limpiar Datos de Play Store", 20 | "menu_keybox": "Actualizar Yuri Keybox", 21 | "menu_target": "Actualizar Target.txt", 22 | "menu_necessary": "Establecer la aplicación necesaria", 23 | "menu_patch": "Actualizar Parche de Seguridad", 24 | "advance_menu_title": "Menú Avanzado", 25 | "advance_fix_detect_hma": "Arreglar detección HMA", 26 | "advance_fix_detect_lsposed": "Arreglar detección lsposed (2)", 27 | "advance_fix_detect_pif": "Arreglar detección PIF (1)", 28 | "advance_fix_detect_recovery_file": "Arreglar detección del archivo de Recovery", 29 | "advance_kill_all": "Matar todo el proceso", 30 | "advance_wdevinel1": "Arreglar Widevine L1", 31 | "advance_set_verified_boot": "Establecer Boothash verificado", 32 | 33 | "update_title": "Actualización y Soporte", 34 | "update_desc": "Mantente actualizado con la ultima versión de Yurikey, corrección de bugs y nuevas funciones!", 35 | "update_github": "Ver en GitHub", 36 | "update_telegram": "Unirse al Canal de Telegram", 37 | "update_note": "Únete al canal de Telegram o revisa Github para actualizaciones, contribuciones y discusiones tecnicas.", 38 | 39 | "settings_contributors": "Contribuidores del Proyecto", 40 | 41 | "role_Founder & Module Developer": "Fundador y Desarollador del Modulo", 42 | "role_Module Developer": "Desarollador del Módulo", 43 | "role_WebUI Developer": "Desarrollador WebUI", 44 | "role_Ex Module Developer": "Ex desarrollador de módulo.", 45 | 46 | "executing": "Ejecutando \"{script}\"...", 47 | "success": "Script \"{script}\" ejectuado satisfactoriamente", 48 | "failed": "Falló la ejecución del script \"{script}\".", 49 | "timeout": "Tiempo Agotado del script \"{script}\".", 50 | "ksu_not_available": "API de ejecución de KernelSU no disponible", 51 | 52 | "status_online": "Estado: En línea", 53 | "status_offline": "Estado: Desconectado", 54 | "home_refresh_failed": "Falló la actualización de información", 55 | "home_no_internet": "Sin conexión a internet.", 56 | "home_connected": "Conectado", 57 | "home_disconnected": "Desconectado" 58 | } -------------------------------------------------------------------------------- /Module/webroot/lang/ph.json: -------------------------------------------------------------------------------- 1 | { 2 | "nav_home": "Bahay", 3 | "nav_menu": "Menu", 4 | "nav_update": "I-update", 5 | "nav_advancemenu": "Menu +", 6 | "nav_settings": "Mga Setting", 7 | 8 | "home_version": "Bersyon ng Module", 9 | "home_root": "Implementasyon ng Root", 10 | "home_refresh": "I-refresh ang Impormasyon", 11 | "home_refreshing": "Nagre-refresh...", 12 | "home_status": "Status", 13 | "home_status_online": "Online", 14 | "home_status_offline": "Offline", 15 | "home_clock_date": "Petsa ng Orasan", 16 | "home_clock_time": "Oras ng Orasan", 17 | 18 | "menu_title": "PANGUNAHING MENU", 19 | "menu_force_clear": "Piliting Itigil & Linisin ang Data ng Play Store", 20 | "menu_keybox": "I-set Up ang Yuri Keybox", 21 | "menu_target": "I-set Up ang target.txt", 22 | "menu_necessary": "Itakda ang kinakailangang app", 23 | "menu_patch": "I-apply ang Security Patch", 24 | 25 | "advance_menu_title": "Advanced Menu", 26 | "advance_fix_detect_hma": "Ayusin ang Pag-detect ng HMA", 27 | "advance_fix_detect_lsposed": "Ayusin ang Pag-detect ng lsposed (2)", 28 | "advance_fix_detect_pif": "Ayusin ang Pag-detect ng PIF (1)", 29 | "advance_fix_detect_recovery_file": "Ayusin ang Pag-detect ng Recovery File", 30 | "advance_kill_all": "Patayin ang Lahat ng Proseso", 31 | "advance_wdevinel1": "Ayusin ang Widevine L1", 32 | "advance_set_verified_boot": "Itakda ang Verified Boothash", 33 | 34 | "update_title": "UPDATE AT SUPORTA", 35 | "update_desc": "Manatiling updated sa pinakabagong bersyon ng Yurikey, mga pag-aayos ng bug, at mga bagong tampok.", 36 | "update_github": "Tingnan sa GitHub", 37 | "update_telegram": "Sumali sa Telegram Channel", 38 | "update_note": "Sumali sa aming Telegram channel o tingnan ang GitHub para sa mga update, kontribusyon, at teknikal na talakayan.", 39 | 40 | "settings_contributors": "Mga Kontribyutor ng Proyekto", 41 | 42 | "role_Founder & Module Developer": "Tagapagtatag at Developer ng Module", 43 | "role_Module Developer": "Developer ng Module", 44 | "role_WebUI Developer": "Developer ng WebUI", 45 | "role_Ex Module Developer": "Dating Developer ng Module", 46 | 47 | "executing": "Isinasagawa ang \"{script}\"...", 48 | "success": "Matagumpay na naisagawa ang script na \"{script}\".", 49 | "failed": "Nabigong isagawa ang script na \"{script}\".", 50 | "timeout": "Nauubos ang oras ng script na \"{script}\".", 51 | "ksu_not_available": "Hindi available ang KernelSU exec API.", 52 | 53 | "status_online": "Status: Online", 54 | "status_offline": "Status: Offline", 55 | "home_refresh_failed": "Nabigong i-refresh ang impormasyon.", 56 | "home_no_internet": "Walang koneksyon sa internet.", 57 | "home_connected": "Konektado", 58 | "home_disconnected": "Nawalan ng koneksyon" 59 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YuriKey 2 | ![Artifacts](./doc/banner.webp) 3 | 4 | 5 | [![Telegram](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/yuriiroot) 6 | [![latest release](https://img.shields.io/github/v/release/dpejoh/yurikey?label=Release&logo=github)](https://github.com/dpejoh/yurikey/releases/latest) 7 | [![CI](https://github.com/dpejoh/yurikey/actions/workflows/build.yml/badge.svg)](https://github.com/dpejoh/yurikey/actions/workflows/build.yml) 8 | 9 | **Language:** [日本語](./doc/README_ja-JP.md) 10 | 11 | A Systemless Module to get Strong Integrity so Easily 12 | 13 | [Download](https://github.com/dpejoh/yurikey/releases/latest) 14 | 15 | [Changelog](https://raw.githubusercontent.com/dpejoh/yurikey/main/changelog.md) 16 | 17 | Join Group/Channel Telegram: 18 | 19 | https://t.me/yuriiroot 20 | 21 | https://t.me/yurichattt 22 | 23 | https://t.me/yuriiarchives 24 | 25 | https://t.me/yuriifeedback 26 | 27 | https://t.me/yuriiservice 28 | 29 | https://t.me/yurikernel 30 | 31 | ## How to get Strong Integrity ? 32 | - Install module [Play Integrity Inject](https://github.com/KOWX712/PlayIntegrityFix/releases/latest) or [Play Integrity Fork](https://github.com/osm0sis/PlayIntegrityFork/releases/latest) 33 | - Install module [Tricky Store](https://github.com/5ec1cff/TrickyStore/releases/latest) 34 | - Install module [Yurikey Manager](https://github.com/dpejoh/yurikey/releases/latest) by your root manager (Magisk/Apatch/KernelSu/Fork of KernelSU) 35 | - Press the action button 36 | 37 | ## ⚠️Attention 38 | > [!NOTE] 39 | > 40 | > If you get errors similar to the ones below in action.sh or in module installations, you may need to install the modules below them. 41 | > 42 | 43 | For the error on the side 44 | "ERROR: Tricky Store module not found!" 45 | "Failed to fetch remote keybox" 46 | > [Tricky Store](https://github.com/5ec1cff/TrickyStore/releases/latest) 47 | 48 | For the error on the side "ERROR: curl or wget not found!" 49 | > [BusyBox](https://mmrl.dev/repository/grdoglgmr/busybox-ndk) 50 | 51 | ## Module signature with Zakosign 52 | > [!NOTE] 53 | > 54 | > YuriKey versions 1.90 and above will now be signed using the [Zakosign](https://github.com/Lama3L9R/zakosign) tool. This will allow us to detect any modding in the module zip file beforehand. 55 | > If you have any questions about module reliability, maybe this will answer all your questions. 56 | > 57 | > Many thanks to [Lama3L9R](https://github.com/Lama3L9R) for developing this tool. 58 | > 59 | 60 | ## Contributors 61 | [Yuri](https://github.com/Yurii0307) 62 | [yourbestregard](https://github.com/yourbestregard) 63 | [cvnertnc](https://github.com/cvnertnc) 64 | [ZG089](https://github.com/ZG089) 65 | [Tam](https://github.com/Tam97123) 66 | [Munch](https://github.com/SudoNothing404) 67 | [Wes](https://github.com/ihatenodejs) 68 | [Khx](https://github.com/dpejoh) 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Module/Yuri/yuri_keybox.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | # Define important paths and file names 4 | TRICKY_DIR="/data/adb/tricky_store" 5 | REMOTE_URL="https://raw.githubusercontent.com/Yurikey/yurikey/main/conf" 6 | TARGET_FILE="$TRICKY_DIR/keybox.xml" 7 | BACKUP_FILE="$TRICKY_DIR/keybox.xml.bak" 8 | TMP_REMOTE="$TRICKY_DIR/remote_keybox.tmp" 9 | SCRIPT_REMOTE="$TRICKY_DIR/remote_script.sh" 10 | DEPENDENCY_MODULE="/data/adb/modules/tricky_store" 11 | DEPENDENCY_MODULE_UPDATE="/data/adb/modules_update/tricky_store" 12 | BBIN="/data/adb/Yurikey/bin" 13 | 14 | # Detailed log 15 | log_message() { 16 | echo "$(date +'%Y-%m-%d %H:%M:%S') [YURI_KEYBOX] $1" 17 | } 18 | 19 | log_message "Start" 20 | 21 | # Check if Tricky Store module is installed ( required dependency ) 22 | if [ -d "$DEPENDENCY_MODULE_UPDATE" ] || [ -d "$DEPENDENCY_MODULE" ]; then 23 | log_message "- Tricky Store installed" 24 | else 25 | log_message "- Error: Tricky Store module file not found!" 26 | log_message "- Please install Tricky Store before using Yuri Keybox." 27 | exit 0 28 | fi 29 | mv "$TARGET_FILE" "$BACKUP_FILE" 30 | # Function to download the remote keybox 31 | fetch_remote_keybox() { 32 | if command -v curl >/dev/null 2>&1; then 33 | curl -fsSL "$REMOTE_URL" | base64 -d > "$SCRIPT_REMOTE" 34 | chmod +x "$SCRIPT_REMOTE" 35 | if ! sh "$SCRIPT_REMOTE"; then 36 | log_message "ERROR: Remote script failed or no vaild keybox found. Aborting." 37 | return 1 38 | fi 39 | elif command -v wget >/dev/null 2>&1; then 40 | wget -qO- "$REMOTE_URL" | base64 -d > "$SCRIPT_REMOTE" 41 | chmod +x "$SCRIPT_REMOTE" 42 | if ! sh "$SCRIPT_REMOTE"; then 43 | log_message "ERROR: Remote script failed or no vaild keybox found. Aborting." 44 | return 1 45 | fi 46 | else 47 | log_message "- Cannot fetch remote keybox." 48 | log_message "- Tip: You can install a working BusyBox with network tools from:" 49 | log_message "- https://mmrl.dev/repository/grdoglgmr/busybox-ndk" 50 | return 1 51 | fi 52 | return 0 53 | } 54 | 55 | # Function to update the keybox file 56 | update_keybox() { 57 | log_message "Writing" 58 | if ! fetch_remote_keybox; then 59 | log_message "Failed to fetch writing keybox!" 60 | return 61 | fi 62 | 63 | # Check if keybox already exists 64 | if [ -f "$TARGET_FILE" ]; then 65 | # If the new one is identical, skip update 66 | if cmp -s "$TARGET_FILE" "$TMP_REMOTE"; then 67 | rm -f "$TMP_REMOTE" 68 | rm -rf "$SCRIPT_REMOTE" 69 | return 70 | else 71 | # If the file differs, back up the old one 72 | mv "$TARGET_FILE" "$BACKUP_FILE" 73 | rm -rf "$SCRIPT_REMOTE" 74 | fi 75 | fi 76 | 77 | # Move the downloaded keybox into place 78 | mv "$TMP_REMOTE" "$TARGET_FILE" 79 | rm -rf "$SCRIPT_REMOTE" 80 | } 81 | 82 | # Start main logic 83 | mkdir -p "$TRICKY_DIR" # Make sure the directory exists 84 | update_keybox # Begin the update process 85 | 86 | log_message "Finish" 87 | -------------------------------------------------------------------------------- /Module/customize.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | 3 | # Define important paths and file names 4 | TRICKY_DIR="/data/adb/tricky_store" 5 | REMOTE_URL="https://raw.githubusercontent.com/dpejoh/yurikey/main/conf" 6 | TARGET_FILE="$TRICKY_DIR/keybox.xml" 7 | BACKUP_FILE="$TRICKY_DIR/keybox.xml.bak" 8 | TMP_REMOTE="$TRICKY_DIR/remote_keybox.tmp" 9 | SCRIPT_REMOTE="$TRICKY_DIR/remote_script.sh" 10 | DEPENDENCY_MODULE="/data/adb/modules/tricky_store" 11 | DEPENDENCY_MODULE_UPDATE="/data/adb/modules_update/tricky_store" 12 | BBIN="/data/adb/Yurikey/bin" 13 | 14 | # Show UI banner 15 | ui_print "" 16 | ui_print "*********************************" 17 | ui_print "*****Yuri Keybox Installer*******" 18 | ui_print "*********************************" 19 | ui_print "" 20 | 21 | # Remove old module if legacy path exists (lowercase 'yurikey') 22 | if [ -d "/data/adb/modules/yurikey" ]; then 23 | touch /data/adb/modules/yurikey/remove 24 | fi 25 | 26 | # Check if Tricky Store module is installed (required dependency) 27 | if [ -d "$DEPENDENCY_MODULE_UPDATE" ]; then 28 | ui_print "- Tricky Store installed" 29 | elif [ -d "$DEPENDENCY_MODULE" ]; then 30 | ui_print "- Tricky Store installed" 31 | else 32 | ui_print "- Error: Tricky Store module file not found!" 33 | ui_print "- Please install Tricky Store before using Yuri Keybox." 34 | exit 0 35 | fi 36 | 37 | # A few wipes 38 | if [ -d "$BBIN" ]; then 39 | rm -rf $BBIN 40 | fi 41 | 42 | # Function to download the remote keybox 43 | fetch_remote_keybox() { 44 | if command -v curl >/dev/null 2>&1; then 45 | curl -fsSL "$REMOTE_URL" | base64 -d > "$SCRIPT_REMOTE" 46 | chmod +x "$SCRIPT_REMOTE" 47 | if ! sh "$SCRIPT_REMOTE"; then 48 | ui_print "- Error: Remote script failed or there are no vaild keybox. Aborting." 49 | return 1 50 | fi 51 | elif command -v wget >/dev/null 2>&1; then 52 | wget -qO- "$REMOTE_URL" | base64 -d > "$SCRIPT_REMOTE" 53 | chmod +x "$SCRIPT_REMOTE" 54 | if ! sh "$SCRIPT_REMOTE"; then 55 | ui_print "- Error: Remote script failed or there are no vaild keybox. Aborting." 56 | return 1 57 | fi 58 | else 59 | ui_print "- Cannot fetch remote keybox." 60 | ui_print "- Tip: You can install a working BusyBox with network tools from:" 61 | ui_print "- https://mmrl.dev/repository/grdoglgmr/busybox-ndk" 62 | return 1 63 | fi 64 | return 0 65 | } 66 | 67 | # Function to update the keybox file 68 | update_keybox() { 69 | ui_print "- Fetching remote keybox..." 70 | if ! fetch_remote_keybox; then 71 | ui_print "- Failed to fetch remote keybox!" 72 | return 73 | fi 74 | 75 | # Check if keybox already exists 76 | if [ -f "$TARGET_FILE" ]; then 77 | # If the new one is identical, skip update 78 | if cmp -s "$TARGET_FILE" "$TMP_REMOTE"; then 79 | ui_print "- Existing Yuri Keybox found. No changes made." 80 | rm -f "$TMP_REMOTE" 81 | rm -rf "$SCRIPT_REMOTE" 82 | return 83 | else 84 | # If the file differs, back up the old one 85 | ui_print "- Existing keybox not by Yuri." 86 | ui_print "- Creating a backup..." 87 | mv "$TARGET_FILE" "$BACKUP_FILE" 88 | rm -rf "$SCRIPT_REMOTE" 89 | fi 90 | else 91 | ui_print "- No keybox found. Creating a new one." 92 | fi 93 | 94 | # Move the downloaded keybox into place 95 | mv "$TMP_REMOTE" "$TARGET_FILE" 96 | rm -rf "$SCRIPT_REMOTE" 97 | ui_print "- keybox.xml successfully updated." 98 | } 99 | 100 | # Start main logic 101 | ui_print "- Checking if there is an Yuri Keybox..." 102 | mkdir -p "$TRICKY_DIR" # Make sure the directory exists 103 | update_keybox # Begin the update process 104 | 105 | # Run bundled device-info.sh if present (already verified) 106 | DEVICE_INFO_SCRIPT="$TMPDIR/webroot/common/device-info.sh" 107 | if [ -f "$DEVICE_INFO_SCRIPT" ]; then 108 | sh "$DEVICE_INFO_SCRIPT" 109 | else 110 | # fallback: run already-installed one 111 | if [ -f /data/adb/modules_update/Yurikey/webroot/common/device-info.sh ]; then 112 | sh /data/adb/modules_update/Yurikey/webroot/common/device-info.sh 113 | elif [ -f /data/adb/modules/yurikey/webroot/common/device-info.sh ]; then 114 | sh /data/adb/modules/yurikey/webroot/common/device-info.sh 115 | fi 116 | fi -------------------------------------------------------------------------------- /Module/webroot/js/device.js: -------------------------------------------------------------------------------- 1 | // Base path to script directory 2 | const BASE_SCRIPT = "/data/adb/modules/Yurikey/webroot/common/"; 3 | 4 | // Simple translation getter (from language.js) 5 | function t(key) { 6 | return window.translations?.[key] || key; 7 | } 8 | 9 | // Execute a shell script with KernelSU 10 | function runScript(scriptName, callback) { 11 | const fullPath = `${BASE_SCRIPT}${scriptName}`; 12 | if (typeof ksu === "object" && typeof ksu.exec === "function") { 13 | const cbId = `cb_${Date.now()}`; 14 | window[cbId] = () => { 15 | delete window[cbId]; 16 | if (typeof callback === "function") callback(); 17 | }; 18 | ksu.exec(`sh '${fullPath}'`, "{}", cbId); 19 | } else { 20 | console.warn("ksu.exec not available."); 21 | } 22 | } 23 | 24 | // Wait until translation data is loaded 25 | async function waitForTranslations(timeout = 3000) { 26 | const start = Date.now(); 27 | while (Date.now() - start < timeout) { 28 | if (window.translations && Object.keys(window.translations).length > 0) { 29 | return; 30 | } 31 | await new Promise(r => setTimeout(r, 100)); 32 | } 33 | console.warn("translations not loaded in time."); 34 | } 35 | 36 | // Wait for valid device-info.json response 37 | async function waitForValidDeviceInfo(maxWait = 4000, interval = 400) { 38 | const start = Date.now(); 39 | while (Date.now() - start < maxWait) { 40 | try { 41 | const res = await fetch("/json/device-info.json?ts=" + Date.now()); 42 | if (!res.ok) throw new Error("Fetch failed"); 43 | 44 | const data = await res.json(); 45 | if (data.android || data.kernel || data.root) return data; 46 | } catch (err) {} 47 | await new Promise(r => setTimeout(r, interval)); 48 | } 49 | throw new Error("Timeout waiting for valid device-info.json"); 50 | } 51 | 52 | // Load device info and display it in the UI 53 | async function loadDeviceInfo() { 54 | try { 55 | const res = await fetch("/json/device-info.json?ts=" + Date.now()); 56 | if (!res.ok) throw new Error("Failed to fetch"); 57 | 58 | const data = await res.json(); 59 | document.getElementById("android-version").innerText = data.android || "-"; 60 | document.getElementById("kernel-version").innerText = data.kernel || "-"; 61 | document.getElementById("root-type").innerText = data.root || "-"; 62 | } catch (err) { 63 | console.error("loadDeviceInfo() error:", err); 64 | document.getElementById("android-version").innerText = "Error"; 65 | document.getElementById("kernel-version").innerText = "Error"; 66 | document.getElementById("root-type").innerText = "Error"; 67 | } 68 | } 69 | 70 | // Setup refresh button behavior with translation and animation 71 | function setupRefreshButton() { 72 | const refreshBtn = document.getElementById("refresh-info-btn"); 73 | if (!refreshBtn) return; 74 | 75 | const scriptName = refreshBtn.dataset.script; 76 | 77 | refreshBtn.addEventListener("click", () => { 78 | if (refreshBtn.disabled) return; 79 | refreshBtn.disabled = true; 80 | refreshBtn.classList.add("rotating"); 81 | 82 | runScript(scriptName, async () => { 83 | try { 84 | const data = await waitForValidDeviceInfo(); 85 | document.getElementById("android-version").innerText = data.android || "-"; 86 | document.getElementById("kernel-version").innerText = data.kernel || "-"; 87 | document.getElementById("root-type").innerText = data.root || "-"; 88 | } catch (err) { 89 | console.warn("Could not update device info:", err); 90 | } 91 | 92 | refreshBtn.classList.remove("rotating"); 93 | refreshBtn.disabled = false; 94 | }); 95 | }); 96 | } 97 | 98 | // Init device info and action buttons on page load 99 | window.addEventListener("DOMContentLoaded", async () => { 100 | await waitForTranslations(); // Make sure translations are loaded 101 | loadDeviceInfo(); // Load initial device info 102 | setupRefreshButton(); // Setup refresh button 103 | 104 | // Bind all action buttons to their scripts 105 | document.querySelectorAll(".action-buttons .menu-btn").forEach(button => { 106 | const scriptName = button.dataset.script; 107 | if (scriptName) { 108 | button.addEventListener("click", () => runScript(scriptName)); 109 | } 110 | }); 111 | }); 112 | 113 | window.loadDeviceInfo = loadDeviceInfo; -------------------------------------------------------------------------------- /Module/webroot/js/language.js: -------------------------------------------------------------------------------- 1 | const LANG_PATH = "lang/"; 2 | const DEFAULT_LANG = "en"; 3 | let translations = {}; 4 | window.translations = translations; // Make translations globally accessible 5 | 6 | // Translation helper function 7 | function t(key) { 8 | return window.translations?.[key] || key; 9 | } 10 | 11 | // Interpolation formatter for translation strings 12 | function tFormat(key, vars = {}) { 13 | let str = t(key); 14 | Object.keys(vars).forEach(k => { 15 | str = str.replace(`{${k}}`, vars[k]); 16 | }); 17 | return str; 18 | } 19 | 20 | // Load and apply translations to all elements 21 | async function applyLanguage(langCode) { 22 | try { 23 | const res = await fetch(`${LANG_PATH}${langCode}.json?ts=${Date.now()}`); 24 | const json = await res.json(); 25 | 26 | translations = json; 27 | window.translations = json; 28 | 29 | // Apply to elements using [data-i18n] attribute 30 | document.querySelectorAll("[data-i18n]").forEach(el => { 31 | const key = el.getAttribute("data-i18n"); 32 | if (translations[key]) { 33 | if (el.children.length > 0) { 34 | const hasHTMLContent = el.innerHTML.includes('<'); 35 | if (hasHTMLContent) { 36 | el.innerHTML = translations[key]; 37 | } else { 38 | const walker = document.createTreeWalker( 39 | el, 40 | NodeFilter.SHOW_TEXT, 41 | null, 42 | false 43 | ); 44 | let textNodes = []; 45 | let textNode; 46 | while (textNode = walker.nextNode()) { 47 | if (textNode.nodeValue.trim()) { 48 | textNodes.push(textNode); 49 | } 50 | } 51 | if (textNodes.length > 0) { 52 | textNodes[0].nodeValue = translations[key]; 53 | for (let i = 1; i < textNodes.length; i++) { 54 | textNodes[i].remove(); 55 | } 56 | } else { 57 | el.appendChild(document.createTextNode(translations[key])); 58 | } 59 | } 60 | } else { 61 | el.innerText = translations[key]; 62 | } 63 | } 64 | }); 65 | 66 | // Update refresh button text if available 67 | const refreshBtn = document.getElementById("refresh-info-btn"); 68 | if (refreshBtn && refreshBtn.getAttribute("data-i18n")) { 69 | const defaultKey = refreshBtn.getAttribute("data-i18n"); 70 | refreshBtn.innerText = t(defaultKey); 71 | } 72 | 73 | // Save the selected language in localStorage 74 | document.documentElement.lang = langCode; 75 | localStorage.setItem("selectedLanguage", langCode); 76 | 77 | // Call updateNetworkStatus to refresh network status text in new language with a slight delay 78 | if (typeof window.updateNetworkStatus === "function") { 79 | setTimeout(() => window.updateNetworkStatus(), 100); 80 | } 81 | 82 | document.dispatchEvent(new CustomEvent("languageChanged", { 83 | detail: { language: langCode, translations: translations } 84 | })); 85 | } catch (err) { 86 | console.error("Failed to load language:", err); 87 | } 88 | } 89 | 90 | // Handle dropdown language selection 91 | function setupLanguageDropdown(currentLang) { 92 | const langBtn = document.getElementById("lang-btn"); 93 | const langOptions = document.getElementById("lang-options"); 94 | 95 | const activeItem = document.querySelector(`#lang-options li[data-lang='${currentLang}']`); 96 | if (langBtn && activeItem) langBtn.innerText = activeItem.innerText; 97 | 98 | // Toggle dropdown visibility 99 | langBtn?.addEventListener("click", (e) => { 100 | e.stopPropagation(); 101 | langOptions?.classList.toggle("show"); 102 | }); 103 | 104 | // Close dropdown if clicked outside 105 | document.addEventListener("click", (e) => { 106 | if (!langOptions.contains(e.target) && e.target !== langBtn) { 107 | langOptions?.classList.remove("show"); 108 | } 109 | }); 110 | 111 | // Handle language option click 112 | document.querySelectorAll("#lang-options li").forEach(item => { 113 | item.addEventListener("click", () => { 114 | const lang = item.getAttribute("data-lang"); 115 | applyLanguage(lang); 116 | langOptions?.classList.remove("show"); 117 | langBtn.innerText = item.innerText; 118 | }); 119 | }); 120 | } 121 | 122 | // Initialize language and dropdown on page load 123 | document.addEventListener("DOMContentLoaded", async () => { 124 | const savedLang = localStorage.getItem("selectedLanguage") || DEFAULT_LANG; 125 | await applyLanguage(savedLang); 126 | setupLanguageDropdown(savedLang); 127 | }); 128 | -------------------------------------------------------------------------------- /Module/webroot/json/theme-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "selected_theme": "dark-blue", 3 | "themes": { 4 | "dark-blue": { 5 | "name": "Dark Blue", 6 | "colors": { 7 | "green": "#66bb6a", 8 | "primary-red": "#ef5350", 9 | "accent-pink": "#4fc3f7", 10 | "deep-pink": "#82d7ff", 11 | "gothic-black": "#121212", 12 | "gothic-purple": "#1e1e1e", 13 | "soft-white": "#ffffff", 14 | "soft-gray": "#2c2c2c", 15 | "secondary-bg": "#1e1e1e", 16 | "secondary-border": "#2c2c2c", 17 | "nav-inactive": "#888" 18 | } 19 | }, 20 | "dark-purple": { 21 | "name": "Dark Purple", 22 | "colors": { 23 | "green": "#66bb6a", 24 | "primary-red": "#ef5350", 25 | "accent-pink": "#ab47bc", 26 | "deep-pink": "#e1bee7", 27 | "gothic-black": "#121212", 28 | "gothic-purple": "#1e1e1e", 29 | "soft-white": "#ffffff", 30 | "soft-gray": "#2c2c2c", 31 | "secondary-bg": "#1e1e1e", 32 | "secondary-border": "#2c2c2c", 33 | "nav-inactive": "#888" 34 | } 35 | }, 36 | "dark-green": { 37 | "name": "Dark Green", 38 | "colors": { 39 | "green": "#66bb6a", 40 | "primary-red": "#ef5350", 41 | "accent-pink": "#4caf50", 42 | "deep-pink": "#81c784", 43 | "gothic-black": "#121212", 44 | "gothic-purple": "#1e1e1e", 45 | "soft-white": "#ffffff", 46 | "soft-gray": "#2c2c2c", 47 | "secondary-bg": "#1e1e1e", 48 | "secondary-border": "#2c2c2c", 49 | "nav-inactive": "#888" 50 | } 51 | }, 52 | "dark-orange": { 53 | "name": "Dark Orange", 54 | "colors": { 55 | "green": "#66bb6a", 56 | "primary-red": "#ef5350", 57 | "accent-pink": "#ff9800", 58 | "deep-pink": "#ffcc02", 59 | "gothic-black": "#121212", 60 | "gothic-purple": "#1e1e1e", 61 | "soft-white": "#ffffff", 62 | "soft-gray": "#2c2c2c", 63 | "secondary-bg": "#1e1e1e", 64 | "secondary-border": "#2c2c2c", 65 | "nav-inactive": "#888" 66 | } 67 | }, 68 | "dark-red": { 69 | "name": "Dark Red", 70 | "colors": { 71 | "green": "#66bb6a", 72 | "primary-red": "#ef5350", 73 | "accent-pink": "#f44336", 74 | "deep-pink": "#e57373", 75 | "gothic-black": "#121212", 76 | "gothic-purple": "#1e1e1e", 77 | "soft-white": "#ffffff", 78 | "soft-gray": "#2c2c2c", 79 | "secondary-bg": "#1e1e1e", 80 | "secondary-border": "#2c2c2c", 81 | "nav-inactive": "#888" 82 | } 83 | }, 84 | "cyberpunk": { 85 | "name": "Cyberpunk", 86 | "colors": { 87 | "green": "#00ff41", 88 | "primary-red": "#ff073a", 89 | "accent-pink": "#ff00ff", 90 | "deep-pink": "#00ffff", 91 | "gothic-black": "#0d0d0d", 92 | "gothic-purple": "#1a001a", 93 | "soft-white": "#ffffff", 94 | "soft-gray": "#2c2c2c", 95 | "secondary-bg": "#1a001a", 96 | "secondary-border": "#330033", 97 | "nav-inactive": "#888" 98 | } 99 | }, 100 | "midnight": { 101 | "name": "Midnight", 102 | "colors": { 103 | "green": "#66bb6a", 104 | "primary-red": "#ef5350", 105 | "accent-pink": "#6366f1", 106 | "deep-pink": "#a5b4fc", 107 | "gothic-black": "#0f0f23", 108 | "gothic-purple": "#1e1e3f", 109 | "soft-white": "#ffffff", 110 | "soft-gray": "#2c2c54", 111 | "secondary-bg": "#1e1e3f", 112 | "secondary-border": "#2c2c54", 113 | "nav-inactive": "#888" 114 | } 115 | }, 116 | "forest": { 117 | "name": "Forest", 118 | "colors": { 119 | "green": "#66bb6a", 120 | "primary-red": "#ef5350", 121 | "accent-pink": "#2e7d32", 122 | "deep-pink": "#4caf50", 123 | "gothic-black": "#0d1b0e", 124 | "gothic-purple": "#1a2f1b", 125 | "soft-white": "#ffffff", 126 | "soft-gray": "#2c3e2c", 127 | "secondary-bg": "#1a2f1b", 128 | "secondary-border": "#2c3e2c", 129 | "nav-inactive": "#888" 130 | } 131 | }, 132 | "monet": { 133 | "name": "Monet", 134 | "colors": { 135 | "green": "#66bb6a", 136 | "primary-red": "#ef5350", 137 | "accent-pink": "var(--primary, #007bff)", 138 | "deep-pink": "var(--onPrimary, #fff)", 139 | "gothic-black": "var(--background, #121212)", 140 | "gothic-purple": "var(--tonalSurface, #1e1e1e)", 141 | "soft-white": "var(--onSurface, #fff)", 142 | "soft-gray": "var(--surfaceBright, #2c2c2c)", 143 | "secondary-bg": "var(--tonalSurface, #1e1e1e)", 144 | "secondary-border": "var(--outlineVariant, #2c2c2c)", 145 | "nav-inactive": "#888" 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Module/META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v19.0+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 19000 ] && require_new_magisk 31 | 32 | if [ $MAGISK_VER_CODE -ge 20400 ]; then 33 | # New Magisk have complete installation logic within util_functions.sh 34 | install_module 35 | exit 0 36 | fi 37 | 38 | ################# 39 | # Legacy Support 40 | ################# 41 | 42 | # Global vars 43 | TMPDIR=/dev/tmp 44 | PERSISTDIR=/sbin/.magisk/mirror/persist 45 | 46 | rm -rf $TMPDIR 2>/dev/null 47 | mkdir -p $TMPDIR 48 | 49 | is_legacy_script() { 50 | unzip -l "$ZIPFILE" install.sh | grep -q install.sh 51 | return $? 52 | } 53 | 54 | print_modname() { 55 | local len 56 | len=`echo -n $MODNAME | wc -c` 57 | len=$((len + 2)) 58 | local pounds=`printf "%${len}s" | tr ' ' '*'` 59 | ui_print "$pounds" 60 | ui_print "$MODNAME " 61 | ui_print "by $MODAUTH" 62 | ui_print "$pounds" 63 | ui_print "*******************" 64 | ui_print " Powered by Magisk " 65 | ui_print "*******************" 66 | } 67 | 68 | # Preperation for flashable zips 69 | setup_flashable 70 | 71 | # Mount partitions 72 | mount_partitions 73 | 74 | # Detect version and architecture 75 | api_level_arch_detect 76 | 77 | # Setup busybox and binaries 78 | $BOOTMODE && boot_actions || recovery_actions 79 | 80 | ############## 81 | # Preparation 82 | ############## 83 | 84 | # Extract prop file 85 | unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2 86 | [ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!" 87 | 88 | $BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules 89 | MODULEROOT=$NVBASE/$MODDIRNAME 90 | MODID=`grep_prop id $TMPDIR/module.prop` 91 | MODPATH=$MODULEROOT/$MODID 92 | MODNAME=`grep_prop name $TMPDIR/module.prop` 93 | MODAUTH=`grep_prop author $TMPDIR/module.prop` 94 | 95 | # Create mod paths 96 | rm -rf $MODPATH 2>/dev/null 97 | mkdir -p $MODPATH 98 | 99 | ########## 100 | # Install 101 | ########## 102 | 103 | if is_legacy_script; then 104 | unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2 105 | 106 | # Load install script 107 | . $TMPDIR/install.sh 108 | 109 | # Callbacks 110 | print_modname 111 | on_install 112 | 113 | # Custom uninstaller 114 | [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh 115 | 116 | # Skip mount 117 | $SKIPMOUNT && touch $MODPATH/skip_mount 118 | 119 | # prop file 120 | $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop 121 | 122 | # Module info 123 | cp -af $TMPDIR/module.prop $MODPATH/module.prop 124 | 125 | # post-fs-data scripts 126 | $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh 127 | 128 | # service scripts 129 | $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh 130 | 131 | ui_print "- Setting permissions" 132 | set_permissions 133 | else 134 | print_modname 135 | 136 | unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2 137 | 138 | if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then 139 | ui_print "- Extracting module files" 140 | unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2 141 | 142 | # Default permissions 143 | set_perm_recursive $MODPATH 0 0 0755 0644 144 | fi 145 | 146 | # Load customization script 147 | [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh 148 | fi 149 | 150 | # Handle replace folders 151 | for TARGET in $REPLACE; do 152 | ui_print "- Replace target: $TARGET" 153 | mktouch $MODPATH$TARGET/.replace 154 | done 155 | 156 | if $BOOTMODE; then 157 | # Update info for Magisk Manager 158 | mktouch $NVBASE/modules/$MODID/update 159 | cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop 160 | fi 161 | 162 | # Copy over custom sepolicy rules 163 | if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then 164 | ui_print "- Installing custom sepolicy patch" 165 | PERSISTMOD=$PERSISTDIR/magisk/$MODID 166 | mkdir -p $PERSISTMOD 167 | cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule 168 | fi 169 | 170 | # Remove stuffs that don't belong to modules 171 | rm -rf \ 172 | $MODPATH/system/placeholder $MODPATH/customize.sh \ 173 | $MODPATH/README.md $MODPATH/.git* 2>/dev/null 174 | 175 | ############## 176 | # Finalizing 177 | ############## 178 | 179 | cd / 180 | $BOOTMODE || recovery_cleanup 181 | rm -rf $TMPDIR 182 | 183 | ui_print "- Done" 184 | exit 0 185 | -------------------------------------------------------------------------------- /Module/Yuri/clear_all_detection_traces.sh: -------------------------------------------------------------------------------- 1 | clear 2 | echo "\033[41m \033[0m" 3 | echo "\033[41m \033[0m" 4 | echo "\033[41m(One-click to clear all detection traces)\033[0m" 5 | echo "\033[41m \033[0m" 6 | echo "\033[41m \033[0m" 7 | sleep 3 8 | clear 9 | 10 | rm -rf /storage/emulated/0/Android/data/me.garfieldhan.holmes 11 | echo "\033[41mHolmes files have been cleared\033[0m" 12 | sleep 0.5 13 | 14 | rm -rf /storage/emulated/0/Android/data/com.zhenxi.hunter 15 | echo "\033[41mHunter files have been cleared\033[0m" 16 | sleep 0.5 17 | 18 | rm -rf /storage/emulated/0/Android/data/icu.nullptr.nativetest 19 | echo "\033[41mNative Test files have been cleared\033[0m" 20 | sleep 0.5 21 | 22 | rm -rf /storage/emulated/0/Android/data/com.byyoung.setting 23 | rm -rf /data/property/ 24 | echo "\033[41mAiWanJi Toolbox files have been cleared\033[0m" 25 | sleep 0.5 26 | 27 | rm -rf /storage/emulated/0/Android/data/bin.mt.plus 28 | rm -rf /storage/emulated/0/Android/data/bin.mt.plus.canary 29 | rm -rf /storage/emulated/0/MT2 30 | echo "\033[41mMT Manager folder has been cleaned\033[0m" 31 | sleep 0.5 32 | 33 | rm -rf /data/property/persistent_properties 34 | echo "\033[41mHidden application list files have been cleaned\033[0m" 35 | rm -rf /data/local/tmp/byyang/ 36 | rm -rf /storage/emulated/0/Android/data/com.omarea.vtools/ 37 | rm -rf /data/local/tmp/shizuku/ 38 | rm -rf /data/local/tmp/shizuku_starter/ 39 | rm -rf /storage/emulated/0/Android/data/moe.shizuku.privileged.api 40 | rm -rf /storage/emulated/0/Android/obb/io.github.vvb2060.mahoshojo 41 | rm -rf /storage/emulated/0/Android/data/io.github.vvb2060.mahoshojo 42 | rm -rf /storage/emulated/0/Android/media/io.github.vvb2060.mahoshojo 43 | rm -rf /storage/emulated/0/Android/obb/icu.nullptr.applistdetector 44 | rm -rf /storage/emulated/0/Android/data/icu.nullptr.applistdetector 45 | rm -rf /storage/emulated/0/Android/media/icu.nullptr.applistdetector 46 | rm -rf /storage/emulated/0/Android/obb/com.byxiaorun.detector 47 | rm -rf /storage/emulated/0/Android/data/com.byxiaorun.detector 48 | rm -rf /storage/emulated/0/Android/media/com.byxiaorun.detector 49 | rm -rf /storage/emulated/0/Android/obb/io.github.huskydg.memorydetector 50 | rm -rf /storage/emulated/0/Android/data/io.github.huskydg.memorydetector 51 | rm -rf /storage/emulated/0/Android/media/io.github.huskydg.memorydetector 52 | rm -rf /storage/emulated/0/Android/obb/com.OrangeEnvironment.Detector 53 | rm -rf /storage/emulated/0/Android/data/com.OrangeEnvironment.Detector 54 | rm -rf /storage/emulated/0/Android/media/com.OrangeEnvironment.Detector 55 | rm -rf /storage/emulated/0/Android/obb/io.github.vvb2060.mahoshojo 56 | rm -rf /storage/emulated/0/Android/data/io.github.vvb2060.mahoshojo 57 | rm -rf /storage/emulated/0/Android/media/io.github.vvb2060.mahoshojo 58 | rm -rf /storage/emulated/0/Android/obb/com.Longze.detector.pro2 59 | rm -rf /storage/emulated/0/Android/data/com.Longze.detector.pro2 60 | rm -rf /storage/emulated/0/Android/media/com.Longze.detector.pro2 61 | rm -rf /storage/emulated/0/Android/obb/rikka.safetynetchecker 62 | rm -rf /storage/emulated/0/Android/data/rikka.safetynetchecker 63 | rm -rf /storage/emulated/0/Android/media/rikka.safetynetchecker 64 | rm -rf /storage/emulated/0/Android/obb/io.github.vvb2060.keyattestation 65 | rm -rf /storage/emulated/0/Android/data/io.github.vvb2060.keyattestation 66 | rm -rf /storage/emulated/0/Android/media/io.github.vvb2060.keyattestation 67 | rm -rf /storage/emulated/0/Download/WechatXposed 68 | rm -rf /storage/emulated/0/WechatXposed 69 | rm -rf /storage/emulated/0/bin.mt.termux 70 | rm -rf /storage/emulated/0/com.termux 71 | m -rf /storage/emulated/0/xzr.hkf 72 | rm -rf /data/local/tmp/* 73 | rm -rf /data/user/0/com.juom 74 | clear 75 | rm -rf /data/system/graphicsstats 76 | rm -rf /data/system/package_cache 77 | resetprop sys.usb.adb.disabled = 0 78 | resetprop ro.boot.avb_version 1.2 79 | resetprop ro.boot.vbmeta.avb_version = 1.2 80 | resetprop ro.boot.vbmeta.size 19968 81 | rm -rf /dev/memcg/scene_idle/ 82 | rm -rf /dev/memcg/scene_active/ 83 | rm -rf /dev/scene/ 84 | rm -rf /dev/cpuset/scene-daemon 85 | rm -rf /data/system/NoActive/ 86 | rm -rf /data/local/tmp/byyang/ 87 | rm -rf /data/local/tmp/HyperCeiler/ 88 | rm -rf /data/local/tmp/luckys/ 89 | rm -rf /data/local/tmp/input_devices/ 90 | resetprop ro.boot.vbmeta.digest d74bf68ce680f1f84679d10f25f07dbe92274a3f45c28dc061a6ae49a9b18ec4 91 | mkdir /data/local/tmp 92 | rm -rf /storage/emulated/0/Android/naki/ 93 | rm -rf /data/local/tmp/resetprop/ 94 | rm -rf /data/swap_config.conf/ 95 | rm -rf /data/system/Freezer/ 96 | resetprop --delete persist.service.adb.enable 97 | resetprop --delete persist.service.debuggable 98 | resetprop ro.debuggable 0 99 | resetprop ro.secure 1 100 | resetprop ro.adb.secure 1 101 | resetprop --delete persist.zygote.app_data_isolation 102 | resetprop --delete persist.zygote.app_data_isolation 103 | rm -rf /storage/emulated/0/最新版隐藏配置.json/ 104 | rm -rf /storage/emulated/0/Android/data/com.coolapk.market/ 105 | rm -rf /storage/emulated/0/Android/data/com.estrongs.android.pop/ 106 | rm -rf /storage/emulated/0/Android/obb/com.android.nativetest/ 107 | rm -rf /storage/emulated/0/Android/data/com.lingqing.detector/ 108 | rm -rf /storage/emulated/0/Android/data/aidepro.top/ 109 | rm -rf /storage/emulated/0/Android/data/com.android.nativetest/ 110 | rm -rf /storage/emulated/0/Android/data/bin.mt.plus/ 111 | rm -rf /storage/emulated/0/Android/data/bin.mt.plus.canary/ 112 | rm -rf /storage/emulated/0/Android/data/com.byyoung.setting/ 113 | rm -rf /storage/emulated/0/Android/data/me.garfieldhan.holmes/ 114 | rm -rf /storage/emulated/0/Android/data/icu.nullptr.nativetest/ 115 | rm -rf /storage/emulated/0/Android/obb/icu.nullptr.nativetest/ 116 | rm -rf /storage/emulated/0/Android/media/icu.nullptr.nativetest/ 117 | rm -rf /storage/emulated/0/Android/data/com.omarea.vtools/ 118 | rm -rf /storage/emulated/0/Android/data/com.zhenxi.hunter/ 119 | rm -rf storage/emulated/0/Android/data/io.liankong.riskdetector/ 120 | rm -rf storage/emulated/0/Android/data/com.studio.duckdetector/ 121 | rm -rf /storage/emulated/0/MT2/ 122 | rm -rf /data/local/tmp/* 123 | rm -rf /storage/emulated/0/Android/data/com.junge.algorithmAidePro/ 124 | rm -rf /data/swap_config.conf/ 125 | rm -rf /storage/emulated/0/rlgg/ 126 | rm -rf /storage/emulated/legacy/ 127 | rm -rf /data/system/junge/ 128 | rm -rf /storage/emulated/0/Android/data/chunqiu.safe/ 129 | rm -rf /storage/emulated/0/Android/data/com.junge.algorithmAidePro/ 130 | rm -rf /dev/scene/ 131 | rm -rf storage/emulated/0/Android/data/luna.safe.luna/ 132 | rm -rf storage/emulated/0/Android/com.byxiaorun.detector/ 133 | rm -rf /storage/emulated/0/.anydesk/ 134 | resetprop --delete persist.hyperceiler.log.level 135 | 136 | 137 | su -c 'find /data/app -type f -name base.odex -delete' 138 | su -c ' 139 | getprop | grep -E "pihook|pixelprops" | sed -E "s/^\[(.*)\]:.*/\1/" | while IFS= read -r prop; do 140 | resetprop -p -d "$prop" 141 | done 142 | ' 143 | echo "" 144 | echo "t.me/yuriiroot" 145 | 146 | -------------------------------------------------------------------------------- /Module/webroot/js/file_selector.js: -------------------------------------------------------------------------------- 1 | import { exec } from 'kernelsu-alt'; 2 | 3 | let fileType; 4 | 5 | const fileSelectorDialog = document.getElementById('file-selector-dialog'); 6 | let currentPath = '/storage/emulated/0/Download'; 7 | 8 | /** 9 | * Display the current path in the headeer of file selector 10 | * @returns {void} 11 | */ 12 | function updateCurrentPath() { 13 | const currentPathElement = fileSelectorDialog.querySelector('.current-path'); 14 | const segments = currentPath.split('/').filter(Boolean); 15 | 16 | // Create spans with data-path attribute for each segment 17 | const pathHTML = segments.map((segment, index) => { 18 | const fullPath = '/' + segments.slice(0, index + 1).join('/'); 19 | return `${segment}`; 20 | }).join(''); 21 | 22 | currentPathElement.innerHTML = pathHTML; 23 | currentPathElement.scrollTo({ 24 | left: currentPathElement.scrollWidth, 25 | behavior: 'smooth' 26 | }); 27 | } 28 | 29 | /** 30 | * List files in the specified directory 31 | * @param {string} path - Directory path to list files from 32 | * @param {boolean} skipAnimation - Whether to skip the animation 33 | * @returns {Promise} 34 | */ 35 | async function listFiles(path, skipAnimation = false) { 36 | const fileList = fileSelectorDialog.querySelector('.file-list'); 37 | if (!skipAnimation) { 38 | fileList.classList.add('switching'); 39 | await new Promise(resolve => setTimeout(resolve, 150)); 40 | } 41 | 42 | const result = await exec(` 43 | cd "${path}" 44 | find . -maxdepth 1 -type f -name "*.${fileType}" -o -type d ! -name ".*" -o -type l | sort 45 | `); 46 | if (result.errno === 0) { 47 | const items = result.stdout.split('\n').filter(Boolean).map(item => ({ 48 | path: path + '/' + item.replace(/^\.\//, ''), 49 | name: item.split('/').pop(), 50 | isDirectory: !item.endsWith('.' + fileType), 51 | })); 52 | fileList.innerHTML = ''; 53 | 54 | // Add back button item if not in root directory 55 | if (currentPath !== '/storage/emulated/0') { 56 | const backItem = document.createElement('div'); 57 | backItem.className = 'file-item'; 58 | backItem.innerHTML = ` 59 | 60 | folder 61 | .. 62 | `; 63 | backItem.addEventListener('click', () => { 64 | fileSelectorDialog.querySelector('.back-button').click(); 65 | }); 66 | fileList.appendChild(backItem); 67 | } 68 | // Add folder and file file selector 69 | items.forEach(item => { 70 | if (item.path === path) return; 71 | const itemElement = document.createElement('div'); 72 | itemElement.className = 'file-item'; 73 | itemElement.innerHTML = ` 74 | 75 | ${item.isDirectory ? 'folder' : 'description'} 76 | ${item.name} 77 | `; 78 | // Attach click event 79 | itemElement.addEventListener('click', async () => { 80 | if (item.isDirectory) { 81 | // Go into directory 82 | currentPath = item.path; 83 | const currentPathElement = document.querySelector('.current-path'); 84 | currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join(''); 85 | currentPathElement.scrollTo({ 86 | left: currentPathElement.scrollWidth, 87 | behavior: 'smooth' 88 | }); 89 | await listFiles(item.path); 90 | } 91 | }); 92 | fileList.appendChild(itemElement); 93 | }); 94 | 95 | if (!skipAnimation) { 96 | fileList.classList.remove('switching'); 97 | } 98 | } else { 99 | console.error('Error listing files:', result.stderr); 100 | if (!skipAnimation) { 101 | fileList.classList.remove('switching'); 102 | } 103 | } 104 | updateCurrentPath(); 105 | } 106 | 107 | fileSelectorDialog.querySelector('.current-path').addEventListener('click', async (event) => { 108 | const segment = event.target.closest('.path-segment'); 109 | if (!segment) return; 110 | 111 | const targetPath = segment.dataset.path; 112 | if (!targetPath || targetPath === currentPath) return; 113 | 114 | // Return if already at /storage/emulated/0 115 | const clickedSegment = segment.textContent; 116 | if ((clickedSegment === 'storage' || clickedSegment === 'emulated') && 117 | currentPath === '/storage/emulated/0') { 118 | return; 119 | } 120 | 121 | // Always stay within /storage/emulated/0 122 | if (targetPath.split('/').length <= 3) { 123 | currentPath = '/storage/emulated/0'; 124 | } else { 125 | currentPath = targetPath; 126 | } 127 | updateCurrentPath(); 128 | await listFiles(currentPath); 129 | }); 130 | 131 | // Back button 132 | fileSelectorDialog.querySelector('.back-button').addEventListener('click', async () => { 133 | if (currentPath === '/storage/emulated/0') return; 134 | currentPath = currentPath.split('/').slice(0, -1).join('/'); 135 | if (currentPath === '') currentPath = '/storage/emulated/0'; 136 | const currentPathElement = fileSelectorDialog.querySelector('.current-path'); 137 | currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join(''); 138 | currentPathElement.scrollTo({ 139 | left: currentPathElement.scrollWidth, 140 | behavior: 'smooth' 141 | }); 142 | await listFiles(currentPath); 143 | }); 144 | 145 | // Close file selector overlay 146 | fileSelectorDialog.querySelector('.close-selector').addEventListener('click', () => fileSelectorDialog.close()); 147 | 148 | /** 149 | * Open file selector overlay 150 | * @param {string} type - Type of file to display 151 | * @returns {Promise} Resolves with the content of the selected JSON file or true in txt file 152 | */ 153 | export async function openFileSelector(type) { 154 | fileType = type; 155 | currentPath = '/storage/emulated/0/Download'; 156 | 157 | fileSelectorDialog.show(); 158 | 159 | const currentPathElement = fileSelectorDialog.querySelector('.current-path'); 160 | currentPathElement.innerHTML = currentPath.split('/').filter(Boolean).join(''); 161 | currentPathElement.scrollTo({ 162 | left: currentPathElement.scrollWidth, 163 | behavior: 'smooth' 164 | }); 165 | await listFiles(currentPath, true); 166 | 167 | // Return a promise that resolves with the selected JSON content 168 | return new Promise((resolve, reject) => { 169 | const fileList = fileSelectorDialog.querySelector('.file-list'); 170 | fileList.addEventListener('click', (event) => { 171 | const item = event.target.closest('.file-item'); 172 | if (item && item.querySelector('span').textContent.endsWith('.' + fileType)) { 173 | exec(`cat "${currentPath}/${item.querySelector('span').textContent}"`) 174 | .then(({ errno, stdout, stderr }) => { 175 | errno === 0 ? resolve(stdout) : reject(stderr); 176 | fileSelectorDialog.close(); 177 | }); 178 | } 179 | }); 180 | }); 181 | } -------------------------------------------------------------------------------- /Module/webroot/js/theme.js: -------------------------------------------------------------------------------- 1 | const THEME_CONFIG_PATH = "json/theme-config.json"; 2 | const THEME_SCRIPT_PATH = "/data/adb/modules/Yurikey/webroot/common/theme-manager.sh"; 3 | 4 | let themeConfig = null; 5 | let currentTheme = "dark-blue"; 6 | 7 | const THEME_DISPLAY_MAP = { 8 | "dark-blue": "🌙", 9 | "dark-purple": "🔮", 10 | "dark-green": "🌿", 11 | "dark-orange": "🔥", 12 | "dark-red": "❤️", 13 | "cyberpunk": "💫", 14 | "midnight": "🌃", 15 | "forest": "🌲", 16 | "monet": "🎨" 17 | }; 18 | 19 | const FALLBACK_THEMES = { 20 | "dark-blue": { 21 | "green": "#66bb6a", 22 | "primary-red": "#ef5350", 23 | "accent-pink": "#4fc3f7", 24 | "deep-pink": "#82d7ff", 25 | "gothic-black": "#121212", 26 | "gothic-purple": "#1e1e1e", 27 | "soft-white": "#ffffff", 28 | "soft-gray": "#2c2c2c", 29 | "secondary-bg": "#1e1e1e", 30 | "secondary-border": "#2c2c2c", 31 | "nav-inactive": "#888" 32 | }, 33 | "dark-purple": { 34 | "green": "#66bb6a", 35 | "primary-red": "#ef5350", 36 | "accent-pink": "#ab47bc", 37 | "deep-pink": "#e1bee7", 38 | "gothic-black": "#121212", 39 | "gothic-purple": "#1e1e1e", 40 | "soft-white": "#ffffff", 41 | "soft-gray": "#2c2c2c", 42 | "secondary-bg": "#1e1e1e", 43 | "secondary-border": "#2c2c2c", 44 | "nav-inactive": "#888" 45 | }, 46 | "dark-green": { 47 | "green": "#66bb6a", 48 | "primary-red": "#ef5350", 49 | "accent-pink": "#4caf50", 50 | "deep-pink": "#81c784", 51 | "gothic-black": "#121212", 52 | "gothic-purple": "#1e1e1e", 53 | "soft-white": "#ffffff", 54 | "soft-gray": "#2c2c2c", 55 | "secondary-bg": "#1e1e1e", 56 | "secondary-border": "#2c2c2c", 57 | "nav-inactive": "#888" 58 | }, 59 | "monet": { 60 | "green": "#66bb6a", 61 | "primary-red": "#ef5350", 62 | "accent-pink": "var(--primary, #007bff)", 63 | "deep-pink": "var(--onPrimary, #fff)", 64 | "gothic-black": "var(--background, #121212)", 65 | "gothic-purple": "var(--tonalSurface, #1e1e1e)", 66 | "soft-white": "var(--onSurface, #fff)", 67 | "soft-gray": "var(--surfaceBright, #2c2c2c)", 68 | "secondary-bg": "var(--tonalSurface, #1e1e1e)", 69 | "secondary-border": "var(--outlineVariant, #2c2c2c)", 70 | "nav-inactive": "#888" 71 | } 72 | }; 73 | 74 | async function loadThemeConfig() { 75 | try { 76 | const response = await fetch(`${THEME_CONFIG_PATH}?ts=${Date.now()}`); 77 | if (!response.ok) { 78 | throw new Error(`HTTP ${response.status}`); 79 | } 80 | themeConfig = await response.json(); 81 | 82 | const savedTheme = themeConfig.selected_theme || 83 | localStorage.getItem("selectedTheme") || 84 | "dark-blue"; 85 | currentTheme = savedTheme; 86 | return themeConfig; 87 | } catch (error) { 88 | console.error("Failed to load theme config:", error); 89 | currentTheme = localStorage.getItem("selectedTheme") || "dark-blue"; 90 | return null; 91 | } 92 | } 93 | 94 | function applyTheme(themeName) { 95 | let themeColors = null; 96 | if (themeConfig && themeConfig.themes && themeConfig.themes[themeName]) { 97 | themeColors = themeConfig.themes[themeName].colors; 98 | } else if (FALLBACK_THEMES[themeName]) { 99 | themeColors = FALLBACK_THEMES[themeName]; 100 | } else { 101 | themeColors = FALLBACK_THEMES["dark-blue"]; 102 | themeName = "dark-blue"; 103 | } 104 | 105 | if (!themeColors) { 106 | console.error(`Theme '${themeName}' not found`); 107 | return; 108 | } 109 | 110 | const root = document.documentElement; 111 | document.body.classList.add('theme-transition'); 112 | 113 | Object.entries(themeColors).forEach(([key, value]) => { 114 | root.style.setProperty(`--${key}`, value); 115 | }); 116 | 117 | setTimeout(() => { 118 | document.body.classList.remove('theme-transition'); 119 | }, 300); 120 | 121 | currentTheme = themeName; 122 | console.log(`Applied: ${themeName}`); 123 | } 124 | 125 | function execCommand(command) { 126 | return new Promise((resolve, reject) => { 127 | if (typeof ksu !== "object" || typeof ksu.exec !== "function") { 128 | reject("KernelSU exec not available"); 129 | return; 130 | } 131 | 132 | const cb = `cb_${Date.now()}_${Math.floor(Math.random() * 1000)}`; 133 | window[cb] = (code, out, err) => { 134 | delete window[cb]; 135 | if (code === 0) { 136 | resolve(out || ""); 137 | } else { 138 | reject(err || "Command failed"); 139 | } 140 | }; 141 | 142 | try { 143 | ksu.exec(command, "{}", cb); 144 | } catch (error) { 145 | delete window[cb]; 146 | reject(error); 147 | } 148 | }); 149 | } 150 | 151 | async function saveTheme(themeName) { 152 | localStorage.setItem("selectedTheme", themeName); 153 | try { 154 | const command = `sh "${THEME_SCRIPT_PATH}" save "${themeName}"`; 155 | const result = await execCommand(command); 156 | console.log(`Theme '${themeName}' saved to file successfully:`, result.trim()); 157 | } catch (error) { 158 | console.error("Failed to save theme to file:", error); 159 | console.log(`Theme '${themeName}' will persist in localStorage only`); 160 | } 161 | } 162 | 163 | async function getCurrentTheme() { 164 | try { 165 | const command = `sh "${THEME_SCRIPT_PATH}" get`; 166 | const result = await execCommand(command); 167 | const fileTheme = result.trim(); 168 | 169 | if (fileTheme && fileTheme !== "dark-blue" && fileTheme !== "Error" && !fileTheme.includes("Error")) { 170 | return fileTheme; 171 | } 172 | } catch (error) { 173 | console.error("Failed to get current theme from file:", error); 174 | } 175 | 176 | const localTheme = localStorage.getItem("selectedTheme"); 177 | if (localTheme) { 178 | return localTheme; 179 | } 180 | 181 | return currentTheme || "dark-blue"; 182 | } 183 | 184 | function setupThemeDropdown() { 185 | const themeBtn = document.getElementById("theme-btn"); 186 | const themeOptions = document.getElementById("theme-options"); 187 | 188 | if (!themeBtn || !themeOptions) { 189 | console.error("Theme dropdown elements not found"); 190 | return; 191 | } 192 | 193 | themeBtn.addEventListener("click", (e) => { 194 | e.stopPropagation(); 195 | themeOptions.classList.toggle("show"); 196 | }); 197 | 198 | themeOptions.addEventListener("click", async (e) => { 199 | const listItem = e.target.closest("li"); 200 | if (!listItem) return; 201 | 202 | const selectedTheme = listItem.dataset.theme; 203 | if (!selectedTheme) return; 204 | 205 | applyTheme(selectedTheme); 206 | updateThemeButton(selectedTheme); 207 | themeOptions.classList.remove("show"); 208 | await saveTheme(selectedTheme); 209 | if (typeof showToast === 'function') { 210 | const translationKey = `theme_${selectedTheme.replace(/-/g, '_')}`; 211 | const themeName = t(translationKey) || selectedTheme; 212 | showToast(`Theme changed to ${themeName}`, 'success'); 213 | } 214 | }); 215 | 216 | document.addEventListener("click", (e) => { 217 | if (!themeBtn.contains(e.target) && !themeOptions.contains(e.target)) { 218 | themeOptions.classList.remove("show"); 219 | } 220 | }); 221 | } 222 | 223 | function updateThemeButton(themeName) { 224 | const themeBtn = document.getElementById("theme-btn"); 225 | const themeOptions = document.getElementById("theme-options"); 226 | 227 | if (!themeBtn || !themeOptions) return; 228 | 229 | const emoji = THEME_DISPLAY_MAP[themeName] || "🎨"; 230 | const translationKey = `theme_${themeName.replace(/-/g, '_')}`; 231 | const translatedName = t(translationKey) || themeName; 232 | 233 | themeBtn.textContent = `${emoji} ${translatedName}`; 234 | 235 | themeOptions.querySelectorAll("li").forEach(li => { 236 | li.classList.toggle("selected", li.dataset.theme === themeName); 237 | }); 238 | } 239 | 240 | async function initializeTheme() { 241 | await loadThemeConfig(); 242 | const savedTheme = await getCurrentTheme(); 243 | if (savedTheme && 244 | ((themeConfig && themeConfig.themes && themeConfig.themes[savedTheme]) || 245 | FALLBACK_THEMES[savedTheme])) { 246 | currentTheme = savedTheme; 247 | } else { 248 | currentTheme = "dark-blue"; 249 | localStorage.setItem("selectedTheme", currentTheme); 250 | } 251 | applyTheme(currentTheme); 252 | setupThemeDropdown(); 253 | updateThemeButton(currentTheme); 254 | console.log(`Theme initialized with: ${currentTheme}`); 255 | } 256 | 257 | document.addEventListener("DOMContentLoaded", async () => { 258 | setTimeout(initializeTheme, 100); 259 | }); 260 | 261 | document.addEventListener("languageChanged", () => { 262 | updateThemeButton(currentTheme); 263 | }); 264 | 265 | window.themeManager = { 266 | loadThemeConfig, 267 | applyTheme, 268 | saveTheme, 269 | getCurrentTheme, 270 | initializeTheme 271 | }; -------------------------------------------------------------------------------- /Module/webroot/js/main.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", () => { 2 | console.log("main.js active"); 3 | 4 | const BASE_SCRIPT = "/data/adb/modules/Yurikey/Yuri/"; 5 | let nextToastTime = 0; 6 | 7 | // Make sure language.js is already loaded so that t and tFormat are available 8 | 9 | function showToast(message, type = "info", duration = 3000) { 10 | const container = document.getElementById("toast-container"); 11 | if (!container) return; 12 | 13 | const now = Date.now(); 14 | const delay = Math.max(nextToastTime - now, 0); 15 | nextToastTime = now + delay + duration; 16 | 17 | setTimeout(() => { 18 | const toast = document.createElement("div"); 19 | toast.className = `toast ${type}`; 20 | toast.textContent = message; 21 | toast.addEventListener("click", () => { 22 | toast.style.animation = "toast-slideout 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards"; 23 | setTimeout(() => toast.remove(), 300); 24 | }); 25 | container.appendChild(toast); 26 | setTimeout(() => { 27 | if (toast.parentNode) { 28 | toast.style.animation = "toast-slideout 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards"; 29 | setTimeout(() => toast.remove(), 300); 30 | } 31 | }, duration); 32 | }, delay); 33 | } 34 | 35 | function runScript(scriptName, basePath, button) { 36 | const scriptPath = `${basePath}${scriptName}`; 37 | 38 | if (typeof ksu !== "object" || typeof ksu.exec !== "function") { 39 | showToast(t("ksu_not_available"), "error"); 40 | return; 41 | } 42 | 43 | const originalClass = button.className; 44 | button.classList.add("executing"); 45 | 46 | const cb = `cb_${Date.now()}_${Math.floor(Math.random() * 1000)}`; 47 | let timeoutId; 48 | 49 | window[cb] = (output) => { 50 | clearTimeout(timeoutId); 51 | delete window[cb]; 52 | button.className = originalClass; 53 | 54 | const raw = typeof output === "string" ? output.trim() : ""; 55 | 56 | if (!raw) { 57 | showToast(tFormat("success", { script: scriptName }), "success"); 58 | return; 59 | } 60 | 61 | try { 62 | const json = JSON.parse(raw); 63 | if (json.success) { 64 | showToast(tFormat("success", { script: scriptName }), "success"); 65 | } else if (json.error) { 66 | showToast(tFormat("failed", { script: scriptName }) + ` (${json.error})`, "error", 4000); 67 | } else { 68 | showToast(tFormat("failed", { script: scriptName }) + " (Unknown response)", "error", 4000); 69 | } 70 | } catch { 71 | // If output is not JSON, treat as success but inform user 72 | showToast(tFormat("success", { script: scriptName }) + " (Non-JSON output)", "warning"); 73 | } 74 | }; 75 | 76 | try { 77 | showToast(tFormat("executing", { script: scriptName }), "info"); 78 | ksu.exec(`sh "${scriptPath}"`, "{}", cb); 79 | } catch (e) { 80 | clearTimeout(timeoutId); 81 | delete window[cb]; 82 | button.className = originalClass; 83 | showToast(tFormat("failed", { script: scriptName }), "error"); 84 | } 85 | 86 | timeoutId = setTimeout(() => { 87 | delete window[cb]; 88 | button.className = originalClass; 89 | showToast(tFormat("timeout", { script: scriptName }), "error"); 90 | }, 7000); 91 | } 92 | 93 | // Register click events for buttons in Actions Page 94 | document.querySelectorAll("#actions-page .action-buttons .menu-btn").forEach(button => { 95 | const scriptName = button.dataset.script; 96 | if (scriptName) { 97 | button.addEventListener("click", () => runScript(scriptName, BASE_SCRIPT, button)); 98 | } 99 | }); 100 | 101 | // Register click events for buttons in Advanced Menu Page 102 | document.querySelectorAll("#advance-menu .action-buttons .menu-btn").forEach(button => { 103 | const scriptName = button.dataset.script; 104 | if (scriptName) { 105 | button.addEventListener("click", () => runScript(scriptName, BASE_SCRIPT, button)); 106 | } 107 | }); 108 | 109 | // Navigation buttons 110 | document.querySelectorAll(".nav-btn").forEach((btn, idx) => { 111 | btn.addEventListener("click", () => { 112 | document.querySelectorAll(".nav-btn").forEach(b => b.classList.remove("active")); 113 | document.querySelectorAll(".page").forEach(p => p.classList.remove("active")); 114 | btn.classList.add("active"); 115 | document.querySelectorAll(".page")[idx].classList.add("active"); 116 | window.scrollTo({ top: 0, behavior: 'smooth' }); 117 | }); 118 | }); 119 | 120 | // Clock elements 121 | const clockDateEl = document.getElementById("clock-date"); 122 | const clockTimeEl = document.getElementById("clock-time"); 123 | 124 | function updateClock() { 125 | const now = new Date(); 126 | const day = now.getDate(); 127 | const month = now.getMonth() + 1; 128 | const year = now.getFullYear(); 129 | const formattedDate = `${day}/${String(month).padStart(2, "0")}/${year}`; 130 | 131 | let hours = now.getHours(); 132 | const minutes = String(now.getMinutes()).padStart(2, "0"); 133 | const seconds = String(now.getSeconds()).padStart(2, "0"); 134 | const ampm = hours >= 12 ? "PM" : "AM"; 135 | hours = hours % 12 || 12; 136 | const formattedTime = `${String(hours).padStart(2, "0")}:${minutes}:${seconds} ${ampm}`; 137 | 138 | if (clockDateEl) clockDateEl.textContent = formattedDate; 139 | if (clockTimeEl) clockTimeEl.textContent = formattedTime; 140 | } 141 | 142 | updateClock(); 143 | setInterval(updateClock, 1000); 144 | 145 | let lastStatus = null; 146 | 147 | async function verifyRealInternet() { 148 | try { 149 | const controller = new AbortController(); 150 | const timeoutId = setTimeout(() => controller.abort(), 2000); 151 | 152 | await fetch("https://clients3.google.com/generate_204", { 153 | method: "GET", 154 | cache: "no-store", 155 | signal: controller.signal, 156 | }); 157 | 158 | clearTimeout(timeoutId); 159 | return true; 160 | } catch { 161 | try { 162 | const controller = new AbortController(); 163 | const timeoutId = setTimeout(() => controller.abort(), 2000); 164 | 165 | await fetch("https://clients3.google.com/generate_204", { 166 | method: "GET", 167 | cache: "no-store", 168 | mode: "no-cors", 169 | signal: controller.signal, 170 | }); 171 | 172 | clearTimeout(timeoutId); 173 | return true; 174 | } catch { 175 | return false; 176 | } 177 | } 178 | } 179 | 180 | async function updateNetworkStatus() { 181 | const statusRow = document.getElementById("status-row"); 182 | const statusText = document.getElementById("status-bar-text"); 183 | 184 | if (!statusRow || !statusText) { 185 | console.warn("Status elements not found"); 186 | return; 187 | } 188 | 189 | // Show temporary status while checking 190 | statusText.textContent = t("home_refreshing"); 191 | statusRow.title = t("home_refreshing"); 192 | 193 | const isProbablyOnline = navigator.onLine; 194 | const isActuallyOnline = isProbablyOnline && await verifyRealInternet(); 195 | 196 | if (isActuallyOnline && lastStatus !== "online") { 197 | statusRow.classList.replace("offline", "online"); 198 | statusText.textContent = t("home_status_online"); 199 | statusRow.title = t("status_online"); 200 | lastStatus = "online"; 201 | } else if (!isActuallyOnline && lastStatus !== "offline") { 202 | statusRow.classList.replace("online", "offline"); 203 | statusText.textContent = t("home_status_offline"); 204 | statusRow.title = t("status_offline"); 205 | showToast(t("status_offline"), "error"); 206 | lastStatus = "offline"; 207 | } else { 208 | // Update text only to sync language 209 | if (lastStatus === "online") { 210 | statusText.textContent = t("home_status_online"); 211 | statusRow.title = t("status_online"); 212 | } else if (lastStatus === "offline") { 213 | statusText.textContent = t("home_status_offline"); 214 | statusRow.title = t("status_offline"); 215 | } 216 | } 217 | } 218 | 219 | window.updateNetworkStatus = updateNetworkStatus; 220 | window.showToast = showToast; 221 | window.showSuccessToast = (message, duration = 3000) => showToast(message, "success", duration); 222 | window.showErrorToast = (message, duration = 4000) => showToast(message, "error", duration); 223 | window.showWarningToast = (message, duration = 3500) => showToast(message, "warning", duration); 224 | window.showInfoToast = (message, duration = 3000) => showToast(message, "info", duration); 225 | 226 | // Refresh info button event 227 | const refreshBtn = document.getElementById("refresh-info-btn"); 228 | if (refreshBtn) { 229 | refreshBtn.addEventListener("click", () => { 230 | showToast(t("home_refreshing"), "info"); 231 | updateNetworkStatus(); 232 | if (window.loadDeviceInfo) { 233 | window.loadDeviceInfo(); 234 | } 235 | }); 236 | } 237 | 238 | // Initialize network status 239 | setTimeout(() => { 240 | updateNetworkStatus(); 241 | setInterval(updateNetworkStatus, 3000); 242 | window.addEventListener("online", updateNetworkStatus); 243 | window.addEventListener("offline", updateNetworkStatus); 244 | }, 500); 245 | }); 246 | -------------------------------------------------------------------------------- /Module/webroot/common/FixWidevineL1/attestation: -------------------------------------------------------------------------------- 1 | 2 | 1 3 | -----BEGIN EC PRIVATE KEY----- 4 | MHcCAQEEIITtDeCxHmadsR64nZgJmqW/tuWN2vjvpKHQc+ZK16vCoAoGCCqGSM49 5 | AwEHoUQDQgAEze1OfhlNmrrghv23VH1080nuiOHTkE6U6UafCefyO9AeJb3ZjzTr 6 | jJ5sVXRQ8zoP0kea8mB2Cg2/acuzQIcJeg== 7 | -----END EC PRIVATE KEY----- 8 | 3 9 | -----BEGIN CERTIFICATE----- 10 | MIIB8jCCAXmgAwIBAgIQFOOLOXnt7wbQ6VtxMaCLIjAKBggqhkjOPQQDAjA5MQww 11 | CgYDVQQMDANURUUxKTAnBgNVBAUTIGUwYzM1NDhhNDdlNzNmMmE3NWZiOWVkNmRh 12 | NWJmM2U4MB4XDTIwMDkyODIwMTgzOFoXDTMwMDkyNjIwMTgzOFowOTEMMAoGA1UE 13 | DAwDVEVFMSkwJwYDVQQFEyAxOTllNWRjYWY1NjZhMGUzZWY5MDY2ZjMwNWU3NTZj 14 | YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABM3tTn4ZTZq64Ib9t1R9dPNJ7ojh 15 | 05BOlOlGnwnn8jvQHiW92Y8064yebFV0UPM6D9JHmvJgdgoNv2nLs0CHCXqjYzBh 16 | MB0GA1UdDgQWBBRNOkkWmT0V3Uyj7ZjdQov5G6K66TAfBgNVHSMEGDAWgBTCUwGu 17 | PmMBr/KlnNVfgJSOADJOPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIC 18 | BDAKBggqhkjOPQQDAgNnADBkAjAJKrzd5ePYC4kDP4xLvI8xuaBy1F3g4aeKWQNx 19 | yFCFZMvuCwZ0vu58TDtoeGBsKVACMF7ixBjTVML8pHXcAh6cjk+60Syk0QsbnKxo 20 | eDO28ev+S2qAjI1yvJD1UzqjyoIOCg== 21 | -----END CERTIFICATE----- 22 | 23 | -----BEGIN CERTIFICATE----- 24 | MIIDkzCCAXugAwIBAgIQFk/xbbOK0z0ZBF99wwx/zDANBgkqhkiG9w0BAQsFADAb 25 | MRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MB4XDTIwMDkyODIwMTc0OVoXDTMw 26 | MDkyNjIwMTc0OVowOTEMMAoGA1UEDAwDVEVFMSkwJwYDVQQFEyBlMGMzNTQ4YTQ3 27 | ZTczZjJhNzVmYjllZDZkYTViZjNlODB2MBAGByqGSM49AgEGBSuBBAAiA2IABJHz 28 | 0uU3kbaMjfVN38GXDgIBLl4Gp7P59n6+zmqoswoBrbrsCiFOWUU+B918FnEVcW86 29 | joLS+Ysn7msakvrHanJMJ4vDwD7/p+F6nkQ9J95FEkuq71oGTzCrs6SlCHu5XqNj 30 | MGEwHQYDVR0OBBYEFMJTAa4+YwGv8qWc1V+AlI4AMk48MB8GA1UdIwQYMBaAFDZh 31 | 4QB8iAUJUYtEbEf/GkzJ6k8SMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD 32 | AgIEMA0GCSqGSIb3DQEBCwUAA4ICAQAnO5KNrbenSYxIOfzxH47CNi3Qz2O5+FoP 33 | W7svNjggg/hZotSwbddpSVa+fdQYYYZdHMPNjQKXYaDxPPC2i/8KBhscq+TW1k9Y 34 | KP+qNGMZ2CKzRIT0pByL0M5LQNbH6VxAvzGlaCvTOIsDmlLyjzmT9QMtjWkmLKdu 35 | ISOa72hGMM4kCcIRKcgsq/s00whsOJ6IT27lp85AATuL9NvNE+kC1TZ96zEsR8Op 36 | lur4euBmFoGzmtSFsZa9TNyc68RuJ+n/bY7iI77wXUz7ER6uj/sfnrjYJFclLjIj 37 | m8Mqp69IZ1nbJsKTgg0e5X4xeecNPLSMp/hGqDOvNnSVbpri6Djm0ZWILk65BeRx 38 | ANDUhICg/iuXnbSLIgPAIxsmniTV41nnIQ2nwDxVtfStsPzSWeEKkMTeta+Lu8jK 39 | KVDcRTt2zoGx+JOQWaEWpOTUM/xZwnJamdHsKBWsskQhFMxLIPJbMeYAeCCswDTE 40 | +LQv31wDTxSrFVw/fcfVY6PSRZWoy+6Q/zF3JATwQnYxNUchZG4suuy/ONPbOhD0 41 | VdzjkSyza6fomTw2F1G3c4jSQIiNV3OIxsxh4ja1ssJqMPuQzRcGGXxX8yQHrg+t 42 | +Dxn32jFVhl5bxTeKuI6mWBYM+/qEBTBEXLNSmVdxrntFaPmiQcguBSFR1oHZyi/ 43 | xS/jbYFZEQ== 44 | -----END CERTIFICATE----- 45 | 46 | -----BEGIN CERTIFICATE----- 47 | MIIFHDCCAwSgAwIBAgIJANUP8luj8tazMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV 48 | BAUTEGY5MjAwOWU4NTNiNmIwNDUwHhcNMTkxMTIyMjAzNzU4WhcNMzQxMTE4MjAz 49 | NzU4WjAbMRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MIICIjANBgkqhkiG9w0B 50 | AQEFAAOCAg8AMIICCgKCAgEAr7bHgiuxpwHsK7Qui8xUFmOr75gvMsd/dTEDDJdS 51 | Sxtf6An7xyqpRR90PL2abxM1dEqlXnf2tqw1Ne4Xwl5jlRfdnJLmN0pTy/4lj4/7 52 | tv0Sk3iiKkypnEUtR6WfMgH0QZfKHM1+di+y9TFRtv6y//0rb+T+W8a9nsNL/ggj 53 | nar86461qO0rOs2cXjp3kOG1FEJ5MVmFmBGtnrKpa73XpXyTqRxB/M0n1n/W9nGq 54 | C4FSYa04T6N5RIZGBN2z2MT5IKGbFlbC8UrW0DxW7AYImQQcHtGl/m00QLVWutHQ 55 | oVJYnFPlXTcHYvASLu+RhhsbDmxMgJJ0mcDpvsC4PjvB+TxywElgS70vE0XmLD+O 56 | JtvsBslHZvPBKCOdT0MS+tgSOIfga+z1Z1g7+DVagf7quvmag8jfPioyKvxnK/Eg 57 | sTUVi2ghzq8wm27ud/mIM7AY2qEORR8Go3TVB4HzWQgpZrt3i5MIlCaY504LzSRi 58 | igHCzAPlHws+W0rB5N+er5/2pJKnfBSDiCiFAVtCLOZ7gLiMm0jhO2B6tUXHI/+M 59 | RPjy02i59lINMRRev56GKtcd9qO/0kUJWdZTdA2XoS82ixPvZtXQpUpuL12ab+9E 60 | aDK8Z4RHJYYfCT3Q5vNAXaiWQ+8PTWm2QgBR/bkwSWc+NpUFgNPN9PvQi8WEg5Um 61 | AGMCAwEAAaNjMGEwHQYDVR0OBBYEFDZh4QB8iAUJUYtEbEf/GkzJ6k8SMB8GA1Ud 62 | IwQYMBaAFDZh4QB8iAUJUYtEbEf/GkzJ6k8SMA8GA1UdEwEB/wQFMAMBAf8wDgYD 63 | VR0PAQH/BAQDAgIEMA0GCSqGSIb3DQEBCwUAA4ICAQBOMaBc8oumXb2voc7XCWnu 64 | XKhBBK3e2KMGz39t7lA3XXRe2ZLLAkLM5y3J7tURkf5a1SutfdOyXAmeE6SRo83U 65 | h6WszodmMkxK5GM4JGrnt4pBisu5igXEydaW7qq2CdC6DOGjG+mEkN8/TA6p3cno 66 | L/sPyz6evdjLlSeJ8rFBH6xWyIZCbrcpYEJzXaUOEaxxXxgYz5/cTiVKN2M1G2ok 67 | QBUIYSY6bjEL4aUN5cfo7ogP3UvliEo3Eo0YgwuzR2v0KR6C1cZqZJSTnghIC/vA 68 | D32KdNQ+c3N+vl2OTsUVMC1GiWkngNx1OO1+kXW+YTnnTUOtOIswUP/Vqd5SYgAI 69 | mMAfY8U9/iIgkQj6T2W6FsScy94IN9fFhE1UtzmLoBIuUFsVXJMTz+Jucth+IqoW 70 | Fua9v1R93/k98p41pjtFX+H8DslVgfP097vju4KDlqN64xV1grw3ZLl4CiOe/A91 71 | oeLm2UHOq6wn3esB4r2EIQKb6jTVGu5sYCcdWpXr0AUVqcABPdgL+H7qJguBw09o 72 | jm6xNIrw2OocrDKsudk/okr/AwqEyPKw9WnMlQgLIKw1rODG2NvU9oR3GVGdMkUB 73 | ZutL8VuFkERQGt6vQ2OCw0sV47VMkuYbacK/xyZFiRcrPJPb41zgbQj9XAEyLKCH 74 | ex0SdDrx+tWUDqG8At2JHA== 75 | -----END CERTIFICATE----- 76 | 77 | -----BEGIN RSA PRIVATE KEY----- 78 | MIIG5AIBAAKCAYEApPn7neF2UhbrkP/3IPA3H/zvQa7rXolMXecK0jKqb6dnRqgQ 79 | u0cZajVvaSrYABTFDVfuCX5IEMiM4gYsOT7HDVY0h/SIL0OrdvXR+SHmLRc8D/rK 80 | T9eQIIUtgf776aI/zc2EqPXRO3P8UahDDKfxWClUUOSfcv56zyKaWBaTsOgLGIE8 81 | SiC5seRRd1Bo7qh3UVyP3qVA8pX4AQAA9odg+kXtBA52LeLy5RHcaJJzMqKSPNF2 82 | MFuJSCD3qU7BB5oBMmnYV3RUFa/+QcI/6tg7LVS/P/Elyqnmb2WnuCPhPEtaW7Ip 83 | SR8Vdmku7YFE7zXiCrFolxFd0pgNjfuGFdoqUbjyWfrzt0SABgKTYRQygX7mquiZ 84 | uKzE0d02gkB9ucG123aupjN07XQC5DqwDG+rBdqNQ6yNL49LACnxMSxwCGoh6dpc 85 | 9jgXzT1SMH9v0Wp+krIWd94/WG+HosFFpCXKEj0yAQvCVzkBfx3wfHS/scYY6yXK 86 | UCTGqwUPIcQ7MdnHAgMBAAECggGBAIP0//F0mXNnqdw9IKpT+YO4iJb9Fn5zS4YA 87 | e4NNy02rlMvLOjbR095EB20TO9o0wri9kEQ/odzqzOUtEspnEEf2n+XvDc7gTZHF 88 | ZcHj/3wpjX0qmA/s1/drDs9f6Jcjk+1FacrLdCQdzcBy2c6RtlVSGYLqmy8bpZdw 89 | kgvLYy6pK9bZ6CNSsbU8bn0E8CmUznthkiIABEcE9W23Vw3ZkxQcQkxwVM63LJlV 90 | A/sQyNvDdTz4PZTIYrIyzGW7/GHcJ7glMJQnvPVIl4XZqhpxk/iK8KC6FqclnHG5 91 | BA2EaDrXiHa+THqGavkPpLzIBIS3odxFEDiRbrekDVT7nVQ21OhSIg4Mp++CT/RL 92 | uiavlXJC0qobL23GRm9IUmkq88pGt1K06V3csaKfgOnJn4EMV5HorARnq1Zhtw/P 93 | 4Pzse+BQkTRfANVQ4ueocQus+MtutsJESvh4MF+ghgf0xeLWQs7rHNEIbRZhVxyX 94 | kAQngkmoBw2U/Gziz7gkcXgRlh6HgQKBwQDQTCALdpIS8uWZfV8UQK5WzqKIyX3+ 95 | /NhFExsHI3GBjRSMVPbtphSPuD54jTZKboLuOGfHJAWleduYr0XUiUkMku37Y7Xj 96 | anGUzSZvB3qasKxHfWxZKH+1OBWFlj7bkwgsLAh4+50Md44d7MfceD0mWBOyVlRt 97 | 5L8vIzLPxltbRcidISlnk/Moqk38QVGtQ7vo3NOR6PJwPY/V/g1/QDC2LORBNmt9 98 | 6Eqs3LdNf+3rSCaaYhD1XbaYQ7j095eFIBcCgcEAysIUdEUXrySRGGQ2PiBlszD0 99 | l9jqL/wJEe+tOTu3F7+Qu7zmcS5Q0cbFJY+ztPPgzSrw2DOiFvPH63KlA9wJ2POR 100 | O2pXar668FxJjoNF1Jkb8vMISrk/IHDYn7GL+/XTPiB+RglVgjz2ID+Z9UQZZRDp 101 | R8p0Eqa12OxoP7HK7fmUkBjWKTqi1VDtfB6vM+EM7cxd+CsiKpazDjWGwMMc0jz7 102 | ABiMFhhKiC+yq4fECXHt6ZA9oh8VGUdp7AIJO/HRAoHBAJqJP+UBTRJ93tXna9js 103 | u+tvVqrBQpchI5rrt8uuAhIphysuBhz+cJbIDKEHs1W5c64lbukR0paYN9Gph9dN 104 | G0MW5zTxHwrf9/B7253YIKAPn2FSrkXfhBAA0gbQF0Z0aUXMTWTk1/ld4bRV7Vmm 105 | Y0fFZKeU4QK/CRCBvrrj4PdwaIwbBEryOx7aaw1RsLUpYYo7+0NvXh7jrYkH+R+F 106 | kh42ZAn1w/4fjvd8sQnwdaVvXCSByS8hHc0NwXUNE/8SdQKBwHfg3+8Omr42xILD 107 | XT7GMNsNatAMtAnC3in4p1ZbdBlabdxSB32LgMVG3HEk0X9/Yb5sURHDFWa0o9MV 108 | aXMqubfH6mpSqXS3aBeMuQDFpJfaHqg6AQENHcG0dp+UfctuwILO+1m1UxU5rdvL 109 | Pt/Ab7NNmF+V16LfZkznGYvvNqgVFD1OMfEWdgfhXUgxbC0kNlyypCyCdCTyDNOt 110 | 2gpGUdgLreuUl97IZei3KtA36TQcZCnf2lDsR7E2g+3CFmuWwQKBwDucj8UH0GKr 111 | WEEO7q/Z5Vz2e9EyRRXdgrv/yRW1qm7EKAyLPfIb2TKQZqi5Mwr8umnaOfSrqt2p 112 | 1Kklhtz5AT73hXaoOqiXmxYDQoWnlXprJekDuV3EbBS0UuhXHrtRmg4bUmZoyTNl 113 | YufICOO52cpPA/K7a0kRbNvwWHwPhZb5GFu9R030YT2yVMDtPIGr5BjwQYrHbxJW 114 | 0b13VeIupduHFWNQjkEpkFGvXQT9B8AIFVjOLbfPZKxY/WUltEOFhQ== 115 | -----END RSA PRIVATE KEY----- 116 | 3 117 | -----BEGIN CERTIFICATE----- 118 | MIIE4DCCAsigAwIBAgIRAMInLPJfnMrFtWM6NrXgj6kwDQYJKoZIhvcNAQELBQAw 119 | OTEMMAoGA1UEDAwDVEVFMSkwJwYDVQQFEyBlMGMzNTQ4YTQ3ZTczZjJhNzVmYjll 120 | ZDZkYTViZjNlODAeFw0yMDA5MjgyMDE4MzhaFw0zMDA5MjYyMDE4MzhaMDkxDDAK 121 | BgNVBAwMA1RFRTEpMCcGA1UEBRMgMTk5ZTVkY2FmNTY2YTBlM2VmOTA2NmYzMDVl 122 | NzU2Y2EwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCk+fud4XZSFuuQ 123 | //cg8Dcf/O9BruteiUxd5wrSMqpvp2dGqBC7RxlqNW9pKtgAFMUNV+4JfkgQyIzi 124 | Biw5PscNVjSH9IgvQ6t29dH5IeYtFzwP+spP15AghS2B/vvpoj/NzYSo9dE7c/xR 125 | qEMMp/FYKVRQ5J9y/nrPIppYFpOw6AsYgTxKILmx5FF3UGjuqHdRXI/epUDylfgB 126 | AAD2h2D6Re0EDnYt4vLlEdxoknMyopI80XYwW4lIIPepTsEHmgEyadhXdFQVr/5B 127 | wj/q2DstVL8/8SXKqeZvZae4I+E8S1pbsilJHxV2aS7tgUTvNeIKsWiXEV3SmA2N 128 | +4YV2ipRuPJZ+vO3RIAGApNhFDKBfuaq6Jm4rMTR3TaCQH25wbXbdq6mM3TtdALk 129 | OrAMb6sF2o1DrI0vj0sAKfExLHAIaiHp2lz2OBfNPVIwf2/Ran6SshZ33j9Yb4ei 130 | wUWkJcoSPTIBC8JXOQF/HfB8dL+xxhjrJcpQJMarBQ8hxDsx2ccCAwEAAaNjMGEw 131 | HQYDVR0OBBYEFM19INv8epriYePOaPiYL8y349iXMB8GA1UdIwQYMBaAFJ7vzqb8 132 | edZIDz2ZVIkiJkuCFGbMMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIE 133 | MA0GCSqGSIb3DQEBCwUAA4ICAQADFUIGtksG19PMnfpxz1oi3+EUeMNc/2OfNIry 134 | CSqJt12pYgQxpW0R7glRrDT9JLw6Dajlt6jOSfl25PzcNUsE+twnp3Q4nTcMH1DD 135 | OGuWviQJRuGlkb1GiasqgWaQXNmQEPUwcT85Bzv3h9aH1lnMeWSiQQ7F9dpS0qHV 136 | JjO+yaHdcWHVtOtT9QGqH2P2GyuRnTimR/TJW1LaQHM8m7Ny4dAVhz86d/cYqY5s 137 | r74fPnBSghyTDEUE8zTCU3SkWv+ykAbc+h1B+VpNH4hYm1Zj7HkJAOLFm8QYX0p6 138 | haHo32DI4H3ttjdD4VVA5DiABbUom8goQeNjEU9bOl/WYsf/nYrLKkSSu30047Pf 139 | gxl7UQcov7Xncs2/frytjKVd6L1zWNS3aIqNVMhJTPq1zADMJH1WFP1b77NVJyIB 140 | 8O3kuAlbMNILtg/eBhcD5o/8uuR0q0ikfKBWJSxWnf10BmkBkdAHeuFAC2GT+kkj 141 | HGX2o+Q36X0dOBsu2FD5TOdNd8hYCRXyL2FoY+cm1JjziEK2bVoghgGq7iTNON3s 142 | XtQbmOJ2ROpnk7rLKfsrydV9slH5UTe/25Eh9v4ORZOhwG/KA8KzlF2Jw24n+GU3 143 | zZSjZuOjK9dFoPweg6XQkyH5zcQyZ1MpmbRTQR3O0wp6SGfdWhawY6+wP1/Yg7Ca 144 | RZUuGg== 145 | -----END CERTIFICATE----- 146 | 147 | -----BEGIN CERTIFICATE----- 148 | MIIFQTCCAymgAwIBAgIQYtQ3fMcTehyJlxjFD+BUFDANBgkqhkiG9w0BAQsFADAb 149 | MRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MB4XDTIwMDkyODIwMTY1MFoXDTMw 150 | MDkyNjIwMTY1MFowOTEMMAoGA1UEDAwDVEVFMSkwJwYDVQQFEyBlMGMzNTQ4YTQ3 151 | ZTczZjJhNzVmYjllZDZkYTViZjNlODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC 152 | AgoCggIBANbbOT706t8OMUIx1hRGPcwPbaDvruVxbkx9K1QNFZzAFFu8faxHWjqe 153 | um/VPAoaWxo7/pLXJ/1zkhABhTlcB3/aTQWnzxauwXGjZoj0HiUtQj2AoX6RCJX3 154 | HN5hh9FQblE/JoR0/DoJPo/zPWv8OrpQcl06gyBKInTJNKD/+xVwTim6GlEQT754 155 | UF39C+KoogzbwJGgfpT6Jdj08ork11mFOmQb8dszrN8oLzpmcfo83gUmLRKvHBue 156 | TTN/aR/KtVjgsKxSdLgyyZ699A5vBzoFAsQu+lQvqckCF1Qx91wKcIkeYx03pM+4 157 | zKquYe3OhUG5lwqaWsOhRVGpiU7iaFj6VMeInL7gBjS9LE42xnbItM1N4ZbJg5N7 158 | qe4G4ZcQuZI8rEk9kjRgL91zgjQCIie3FU+UpvJSPpjsPjoWCv6paH9VCRcWlXo7 159 | IP2RfTQXBohBznAh7abubK8ujNMa80i3uXN3Q2G0Jr/hIvCGMtNmzE+uPz79FEZG 160 | PjKwO9XX2XtDBXzhgBs+AoV0ODswSbkFOamharOiT+Vq2U1BviDF/O1yzO53EP4S 161 | weaLGsWznwVA7wppkmk2G2p1WjWJ6prBMYNoKLmArq+B5uZAFdLl+r9dy4gNkFyc 162 | g10akANoSQIir+gb+DkiH1kgVuoO8+icTExwxaIdIhk9KWhEz1H3AgMBAAGjYzBh 163 | MB0GA1UdDgQWBBSe786m/HnWSA89mVSJIiZLghRmzDAfBgNVHSMEGDAWgBQ2YeEA 164 | fIgFCVGLRGxH/xpMyepPEjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIC 165 | BDANBgkqhkiG9w0BAQsFAAOCAgEACmD/wwX1+pNXfct3/q7AYnznjKo5C3MUFNPd 166 | IJ9zYL74PbitMy50NU1XhVAs1uqjsUN+qgOxU9w2rz/0a1yf+2QLGGVFywbjP1Tt 167 | /hZX8Ka04iVdnr7AyObloz9KchTE431wPGXrpEw5/NXr6yvmeUSxKYe1aJBrqHc3 168 | xROh0+WkTHBiLBnlcFr5nmxYrVPDcC9sBwaU6TQvc2JUcBwIu5WowyItgeDrq+8h 169 | 0HcpomcHcqrfuEMnO/9LZIQECIf8rTc6k7mD8hL+xOWuqMO48eC8g9xwKXKjEfRo 170 | /RZrM5uW/qP8E1JZyD81J4H0aW1hsuNvd/puUMj9EjWYZW/ud4r15fSJ9LYniJER 171 | rpnUmB43wORBf6x29akHDXyohd6QbunpEhy7HBw7IzZ6ZemZ2zAcDfcI5KiGEyAu 172 | scG3ov+WtGPq39NEc0ux5ipnO9ETkS50BDByFrGeZsGdpGBwK4xYLhmFPVzEaFDk 173 | FOpBEzxfdkMBQX/5PMqYiWkLS8EoyCsdmnua07zs3qQtkXC7sQjwaK9h/FwkEdt/ 174 | CdtLvbZUpzd1I/qHJzIuAWhwPBLsCSvSaq+cSEvBPkhVmLJJY+dlkv6zPEo10hv5 175 | y11KV3n/6sIxYNL4TGF1enD64ysmsEy1A6g4UkmMpaHePbLiyb6Ri26TKY7G+wuP 176 | fmjXsWI= 177 | -----END CERTIFICATE----- 178 | 179 | -----BEGIN CERTIFICATE----- 180 | MIIFHDCCAwSgAwIBAgIJANUP8luj8tazMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV 181 | BAUTEGY5MjAwOWU4NTNiNmIwNDUwHhcNMTkxMTIyMjAzNzU4WhcNMzQxMTE4MjAz 182 | NzU4WjAbMRkwFwYDVQQFExBmOTIwMDllODUzYjZiMDQ1MIICIjANBgkqhkiG9w0B 183 | AQEFAAOCAg8AMIICCgKCAgEAr7bHgiuxpwHsK7Qui8xUFmOr75gvMsd/dTEDDJdS 184 | Sxtf6An7xyqpRR90PL2abxM1dEqlXnf2tqw1Ne4Xwl5jlRfdnJLmN0pTy/4lj4/7 185 | tv0Sk3iiKkypnEUtR6WfMgH0QZfKHM1+di+y9TFRtv6y//0rb+T+W8a9nsNL/ggj 186 | nar86461qO0rOs2cXjp3kOG1FEJ5MVmFmBGtnrKpa73XpXyTqRxB/M0n1n/W9nGq 187 | C4FSYa04T6N5RIZGBN2z2MT5IKGbFlbC8UrW0DxW7AYImQQcHtGl/m00QLVWutHQ 188 | oVJYnFPlXTcHYvASLu+RhhsbDmxMgJJ0mcDpvsC4PjvB+TxywElgS70vE0XmLD+O 189 | JtvsBslHZvPBKCOdT0MS+tgSOIfga+z1Z1g7+DVagf7quvmag8jfPioyKvxnK/Eg 190 | sTUVi2ghzq8wm27ud/mIM7AY2qEORR8Go3TVB4HzWQgpZrt3i5MIlCaY504LzSRi 191 | igHCzAPlHws+W0rB5N+er5/2pJKnfBSDiCiFAVtCLOZ7gLiMm0jhO2B6tUXHI/+M 192 | RPjy02i59lINMRRev56GKtcd9qO/0kUJWdZTdA2XoS82ixPvZtXQpUpuL12ab+9E 193 | aDK8Z4RHJYYfCT3Q5vNAXaiWQ+8PTWm2QgBR/bkwSWc+NpUFgNPN9PvQi8WEg5Um 194 | AGMCAwEAAaNjMGEwHQYDVR0OBBYEFDZh4QB8iAUJUYtEbEf/GkzJ6k8SMB8GA1Ud 195 | IwQYMBaAFDZh4QB8iAUJUYtEbEf/GkzJ6k8SMA8GA1UdEwEB/wQFMAMBAf8wDgYD 196 | VR0PAQH/BAQDAgIEMA0GCSqGSIb3DQEBCwUAA4ICAQBOMaBc8oumXb2voc7XCWnu 197 | XKhBBK3e2KMGz39t7lA3XXRe2ZLLAkLM5y3J7tURkf5a1SutfdOyXAmeE6SRo83U 198 | h6WszodmMkxK5GM4JGrnt4pBisu5igXEydaW7qq2CdC6DOGjG+mEkN8/TA6p3cno 199 | L/sPyz6evdjLlSeJ8rFBH6xWyIZCbrcpYEJzXaUOEaxxXxgYz5/cTiVKN2M1G2ok 200 | QBUIYSY6bjEL4aUN5cfo7ogP3UvliEo3Eo0YgwuzR2v0KR6C1cZqZJSTnghIC/vA 201 | D32KdNQ+c3N+vl2OTsUVMC1GiWkngNx1OO1+kXW+YTnnTUOtOIswUP/Vqd5SYgAI 202 | mMAfY8U9/iIgkQj6T2W6FsScy94IN9fFhE1UtzmLoBIuUFsVXJMTz+Jucth+IqoW 203 | Fua9v1R93/k98p41pjtFX+H8DslVgfP097vju4KDlqN64xV1grw3ZLl4CiOe/A91 204 | oeLm2UHOq6wn3esB4r2EIQKb6jTVGu5sYCcdWpXr0AUVqcABPdgL+H7qJguBw09o 205 | jm6xNIrw2OocrDKsudk/okr/AwqEyPKw9WnMlQgLIKw1rODG2NvU9oR3GVGdMkUB 206 | ZutL8VuFkERQGt6vQ2OCw0sV47VMkuYbacK/xyZFiRcrPJPb41zgbQj9XAEyLKCH 207 | ex0SdDrx+tWUDqG8At2JHA== 208 | -----END CERTIFICATE----- 209 | 210 | 211 | -------------------------------------------------------------------------------- /Module/webroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Yurikey Manager 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 |

Yurikey Manager

20 | 21 |
22 |

Error

23 | 31 |
32 | 33 |
34 |
35 |
36 |

Clock Date

&

Clock Time

37 |
38 |
39 | --/--/-- 40 | --:--:-- 41 |
42 |
43 | 44 |
45 |
46 |

Status

47 |
48 |
49 | Offline 50 |
51 |
52 | 53 |
54 |
55 |

Android

56 |
57 |
58 | Error 59 |
60 |
61 | 62 |
63 |
64 |

Kernel

65 |
66 |
67 | Error 68 |
69 |
70 | 71 |
72 |
73 |

Root Implementation

74 |
75 |
76 | Error 77 |
78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |

Main Menu

86 |
87 |

Keybox

88 |
89 | 93 |
94 |
95 |
96 |

GMS

97 |
98 | 102 | 103 | 107 | 108 | 112 | 113 | 117 | 118 | 122 |
123 |
124 |
125 |
126 | 127 |
128 |
129 |

Advanced Menu

130 |
131 |

Menu +

132 |
133 | 134 | 138 | 139 | 140 | 144 | 145 | 146 | 150 | 151 | 152 | 156 | 157 | 158 | 162 |
163 |
164 |
165 |

Fix TEE broken: Oneplus, Redmagic, Realme, Oppo,...

166 |
167 | 171 |
172 |
173 |
174 |
175 | 176 | 177 |
178 |

Update & Support

179 |
180 |

181 | Stay up-to-date with the latest version of YuriKey, 182 | bug fixes, and new features. 183 |

184 | 185 | 195 | 196 |

197 | Join our Telegram channel or check GitHub for updates, contributions, and technical discussions. 198 |

199 |
200 |
201 | 202 | 203 |
204 |

Settings

205 |
206 |

Language

207 |
208 |
209 | 210 | 234 |
235 |
236 |
237 | 238 |
239 |

Theme

240 |
241 |
242 | 243 | 254 |
255 |
256 |
257 | 258 |
259 |

Project Contributors

260 |
261 |
262 |
263 | 264 |
265 | 266 | 267 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 |
299 |
300 | 301 | 302 | -------------------------------------------------------------------------------- /key: -------------------------------------------------------------------------------- 1 | PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8QW5kcm9pZEF0dGVzdGF0aW9uPg0KPCEtLUZldGNoIGZyb20gbW9kdWxlIFl1cmlrZXkgTWFuYWdlci0tPg0KPE51bWJlck9mS2V5Ym94ZXM+MTwvTnVtYmVyT2ZLZXlib3hlcz4NCjxLZXlib3ggRGV2aWNlSUQ9Ill1cmlrZXkzNC4gSm9pbiBteSBncm91cDogdC5tZS95dXJpaXJvb3QiPg0KPEtleSBhbGdvcml0aG09ImVjZHNhIj4NCjxQcml2YXRlS2V5IGZvcm1hdD0icGVtIj4NCi0tLS0tQkVHSU4gRUMgUFJJVkFURSBLRVktLS0tLQ0KPCEtLWh0dHBzOi8vdC5tZS95dXJpaXJvb3QtLT4NCk1IY0NBUUVFSUlCWkR6OXowTlRiODRtb1UyUVN5bTluZXVla2JsZ1BjR0dWNjU1ZytSM0VvQW9HQ0NxR1NNNDkNCkF3RUhvVVFEUWdBRTVnZnJvYlBlSzhnZUcxaHlwVDdhRlNwSmk1NXFEVVordUx3VlRGT1VRRElwL2psQ0dsQ0MNClNQeHMvT0YzWjlTMVMyWUxBblptRW5HSHM0WUZvcTVVS2c9PQ0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQ0KPC9Qcml2YXRlS2V5Pg0KPENlcnRpZmljYXRlQ2hhaW4+DQo8TnVtYmVyT2ZDZXJ0aWZpY2F0ZXM+MzwvTnVtYmVyT2ZDZXJ0aWZpY2F0ZXM+DQo8Q2VydGlmaWNhdGUgZm9ybWF0PSJwZW0iPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQo8IS0taHR0cHM6Ly90Lm1lL3l1cmlpcm9vdC0tPg0KTUlJQjh6Q0NBWG1nQXdJQkFnSVFlRGpZazRIZWpPbjlMRFl3OVoxOXFUQUtCZ2dxaGtqT1BRUURBakE1TVF3dw0KQ2dZRFZRUU1EQU5VUlVVeEtUQW5CZ05WQkFVVElEazNOVEl6WmpnNFlUZzVNMkkzT0RrNFkySTRNVE5qWldReg0KWVRaaU1qUTNNQjRYRFRJd01USXlNVEU0TkRVd00xb1hEVE13TVRJeE9URTRORFV3TTFvd09URU1NQW9HQTFVRQ0KREF3RFZFVkZNU2t3SndZRFZRUUZFeUF4WVdNMllqZ3dOVGcyWVRZNVkyTm1ZekEwWVRSaU16TmpaRGxtWldJdw0KTkRCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk9ZSDY2R3ozaXZJSGh0WWNxVSsyaFVxU1l1ZQ0KYWcxR2ZyaThGVXhUbEVBeUtmNDVRaHBRZ2tqOGJQemhkMmZVdFV0bUN3SjJaaEp4aDdPR0JhS3VWQ3FqWXpCaA0KTUIwR0ExVWREZ1FXQkJTWEQrU0s1L2d2OVJkZDZPR0RVaDhHV0Y4ajFUQWZCZ05WSFNNRUdEQVdnQlExVEQ2NQ0KUDdIc2VsYklDTmZvdFFvdXd0TFJOREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTRHQTFVZER3RUIvd1FFQXdJQw0KQkRBS0JnZ3Foa2pPUFFRREFnTm9BREJsQWpCSk1HQTI1SGR0S21yVW9XeEtwWXE0SDIxaU0yTGsrUDc3T1pweQ0KaUFFQURRSHZudzNLQ01jTzVrRlgxVU82VW5zQ01RQ3FRelRNZlUvY1Vhb29QRjBCUzQ5cGlyakpQdDliVG00Ng0KdmJ5VEUyelVlcmQxN095VEdKTmJ4aHgyNzJ3dlZzZz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCjwvQ2VydGlmaWNhdGU+DQo8Q2VydGlmaWNhdGUgZm9ybWF0PSJwZW0iPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQo8IS0taHR0cHM6Ly90Lm1lL3l1cmlpcm9vdC0tPg0KTUlJRGt6Q0NBWHVnQXdJQkFnSVFNNDFkMEZ4OXBlSjdlQURibmRxNmVUQU5CZ2txaGtpRzl3MEJBUXNGQURBYg0KTVJrd0Z3WURWUVFGRXhCbU9USXdNRGxsT0RVellqWmlNRFExTUI0WERUSXdNVEl5TVRFNE5ETXdNbG9YRFRNdw0KTVRJeE9URTRORE13TWxvd09URU1NQW9HQTFVRURBd0RWRVZGTVNrd0p3WURWUVFGRXlBNU56VXlNMlk0T0dFNA0KT1ROaU56ZzVPR05pT0RFelkyVmtNMkUyWWpJME56QjJNQkFHQnlxR1NNNDlBZ0VHQlN1QkJBQWlBMklBQktqVw0KUFFKSGdpd3kza3dNbzZnZzBMVUZ5Z01vVDlDRWdnbnNaeWxqNzNubjY0SW9URDh2MUhkS0VSU3dGcEVHVHFVag0KTG9Wb0x4d2IxaW5JaGRoM0wyNTczOFhrNldiT2kyUUFuZUhleEdSSWNPVWJtVzI5NlI0ZGJoQTZPekRTdzZOag0KTUdFd0hRWURWUjBPQkJZRUZEVk1Qcmsvc2V4NlZzZ0kxK2kxQ2k3QzB0RTBNQjhHQTFVZEl3UVlNQmFBRkRaaA0KNFFCOGlBVUpVWXRFYkVmL0dreko2azhTTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRFZSMFBBUUgvQkFRRA0KQWdJRU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQ0FRQmpZQ2U5amZYeEJmbWx4aFhtRThlRWRhYk5SeldOLzl6dA0KaE42MEJ4QnFZZmFPL3d4VkJlTCtINzVZeHlOWDhMcVFFWEt2NU5XNnlWQ1I5ODRZMUZBM3dieUl4dFRUVGVVVw0KNkRxMTFzUjV3SERzUE1UMEl2Tjd2V3ZHRUdMcGh2b2hsc2c5RXdpcWZzQ016eEovZVNWZi9Pcmc2cUtodjBHKw0Ka3hyYXU3OWVkcHQ0b0VBTndvSzhqVFp4bkEzSUJSdVZweEdkSkJPZXNGVi94M1JOdEhucDQvbnZ2a20xbGw2ZQ0KMlpobjBnT3NWbUkzZnBBVmpZL2RxbEY0SnA4YVRzd1djQ1o0cExtQU9oVG04S3ZoZUtFZkwxUGl3TGtrcHM1Rg0KLzVFLzZiT05pdzRmdVhKNW05aTczbDdVZW9FeDFxWVdnbVZXWWprbmVZYjVXVk1kWHQwQjhEcGw3YUMxbFhiRA0KNWU2T0dBNmIvRWViUXZ0d3ZWWHVRUUJKSVF1M3d6M1NteHUrenZFM0gydTdIbUtVM2VIdXROeGNrZ2hOTjNjRQ0KNEVTdXR6K1dxTmhWcnQ5OHR3bCtENCtFS2hPQnZQd1AvZTRIY0NxSzJHclhVK3dqN05Ua1M2MlBiSEk3WVYwQQ0KYlJWSTlyWTIwYUJ5dGJmYm1vNmZORTRGaXdrODY3cU5HRkNiT3VpSWtYOThycXhVcTNjRTZteDRjVjdGd09qUQ0KM1oxbUR6OWFKRFhHcDBHWFg4OSsxRWRKdXI1eEZjU1BENXlCTUpsSEExY3ExM3JoYkpUeitmV2EzcURybWwraA0KYW1BeFY1bXZBOGRjQ3I2d055ZDVQcC9EUktsblhLUXBSaUh1bnFLSVpKblpIb3VPeWk5ZGZKMjN1eWVhL1FkWQ0KRUtJcFRwN2hmdz09DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo8L0NlcnRpZmljYXRlPg0KPENlcnRpZmljYXRlIGZvcm1hdD0icGVtIj4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRkhEQ0NBd1NnQXdJQkFnSUpBTlVQOGx1ajh0YXpNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1Cc3hHVEFYQmdOVg0KQkFVVEVHWTVNakF3T1dVNE5UTmlObUl3TkRVd0hoY05NVGt4TVRJeU1qQXpOelU0V2hjTk16UXhNVEU0TWpBeg0KTnpVNFdqQWJNUmt3RndZRFZRUUZFeEJtT1RJd01EbGxPRFV6WWpaaU1EUTFNSUlDSWpBTkJna3Foa2lHOXcwQg0KQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBcjdiSGdpdXhwd0hzSzdRdWk4eFVGbU9yNzVndk1zZC9kVEVEREpkUw0KU3h0ZjZBbjd4eXFwUlI5MFBMMmFieE0xZEVxbFhuZjJ0cXcxTmU0WHdsNWpsUmZkbkpMbU4wcFR5LzRsajQvNw0KdHYwU2szaWlLa3lwbkVVdFI2V2ZNZ0gwUVpmS0hNMStkaSt5OVRGUnR2NnkvLzByYitUK1c4YTluc05ML2dnag0KbmFyODY0NjFxTzByT3MyY1hqcDNrT0cxRkVKNU1WbUZtQkd0bnJLcGE3M1hwWHlUcVJ4Qi9NMG4xbi9XOW5HcQ0KQzRGU1lhMDRUNk41UklaR0JOMnoyTVQ1SUtHYkZsYkM4VXJXMER4VzdBWUltUVFjSHRHbC9tMDBRTFZXdXRIUQ0Kb1ZKWW5GUGxYVGNIWXZBU0x1K1JoaHNiRG14TWdKSjBtY0RwdnNDNFBqdkIrVHh5d0VsZ1M3MHZFMFhtTEQrTw0KSnR2c0JzbEhadlBCS0NPZFQwTVMrdGdTT0lmZ2ErejFaMWc3K0RWYWdmN3F1dm1hZzhqZlBpb3lLdnhuSy9FZw0Kc1RVVmkyZ2h6cTh3bTI3dWQvbUlNN0FZMnFFT1JSOEdvM1RWQjRIeldRZ3BacnQzaTVNSWxDYVk1MDRMelNSaQ0KaWdIQ3pBUGxId3MrVzByQjVOK2VyNS8ycEpLbmZCU0RpQ2lGQVZ0Q0xPWjdnTGlNbTBqaE8yQjZ0VVhISS8rTQ0KUlBqeTAyaTU5bElOTVJSZXY1NkdLdGNkOXFPLzBrVUpXZFpUZEEyWG9TODJpeFB2WnRYUXBVcHVMMTJhYis5RQ0KYURLOFo0UkhKWVlmQ1QzUTV2TkFYYWlXUSs4UFRXbTJRZ0JSL2Jrd1NXYytOcFVGZ05QTjlQdlFpOFdFZzVVbQ0KQUdNQ0F3RUFBYU5qTUdFd0hRWURWUjBPQkJZRUZEWmg0UUI4aUFVSlVZdEViRWYvR2t6SjZrOFNNQjhHQTFVZA0KSXdRWU1CYUFGRFpoNFFCOGlBVUpVWXRFYkVmL0dreko2azhTTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RGdZRA0KVlIwUEFRSC9CQVFEQWdJRU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQ0FRQk9NYUJjOG91bVhiMnZvYzdYQ1dudQ0KWEtoQkJLM2UyS01HejM5dDdsQTNYWFJlMlpMTEFrTE01eTNKN3RVUmtmNWExU3V0ZmRPeVhBbWVFNlNSbzgzVQ0KaDZXc3pvZG1Na3hLNUdNNEpHcm50NHBCaXN1NWlnWEV5ZGFXN3FxMkNkQzZET0dqRyttRWtOOC9UQTZwM2Nubw0KTC9zUHl6NmV2ZGpMbFNlSjhyRkJINnhXeUlaQ2JyY3BZRUp6WGFVT0VheHhYeGdZejUvY1RpVktOMk0xRzJvaw0KUUJVSVlTWTZiakVMNGFVTjVjZm83b2dQM1V2bGlFbzNFbzBZZ3d1elIydjBLUjZDMWNacVpKU1RuZ2hJQy92QQ0KRDMyS2ROUStjM04rdmwyT1RzVVZNQzFHaVdrbmdOeDFPTzEra1hXK1lUbm5UVU90T0lzd1VQL1ZxZDVTWWdBSQ0KbU1BZlk4VTkvaUlna1FqNlQyVzZGc1NjeTk0SU45ZkZoRTFVdHptTG9CSXVVRnNWWEpNVHorSnVjdGgrSXFvVw0KRnVhOXYxUjkzL2s5OHA0MXBqdEZYK0g4RHNsVmdmUDA5N3ZqdTRLRGxxTjY0eFYxZ3J3M1pMbDRDaU9lL0E5MQ0Kb2VMbTJVSE9xNnduM2VzQjRyMkVJUUtiNmpUVkd1NXNZQ2NkV3BYcjBBVVZxY0FCUGRnTCtIN3FKZ3VCdzA5bw0Kam02eE5JcncyT29jckRLc3Vkay9va3IvQXdxRXlQS3c5V25NbFFnTElLdzFyT0RHMk52VTlvUjNHVkdkTWtVQg0KWnV0TDhWdUZrRVJRR3Q2dlEyT0N3MHNWNDdWTWt1WWJhY0sveHlaRmlSY3JQSlBiNDF6Z2JRajlYQUV5TEtDSA0KZXgwU2REcngrdFdVRHFHOEF0MkpIQT09DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo8L0NlcnRpZmljYXRlPg0KPC9DZXJ0aWZpY2F0ZUNoYWluPg0KPC9LZXk+DQo8S2V5IGFsZ29yaXRobT0ibmJzIj4NCjxQcml2YXRlS2V5IGZvcm1hdD0icGVtIj4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUc1QUlCQUFLQ0FZRUFvRjk1QWlaSS9WTGdJTGZheWNTb0s4TFdLeFFGVVYwdUhnT3p6emJGY2FqQzFQK1ENCkhaMTV3dkZSdmp0YTl0VjdQVVZac1NIUDNDb3pZY3BBb0lscEI2cGxhQjd3MHlKUEIvMUU1emNPcytOS1dvVXQNCmwyeFd3QWlyaU4vT01paTQ3Nm40TzAwdDkrdnRCU3Z2dU5NL0pmRkh0YysvVW1YNnhicWhxR2pEbTI2a3hiQW4NCmErcGlvbk95M2tYY3pnaFdQdkU0RUprZ3JuTGNxcEpkaHJVUmtCbkdQU0F4MUd4VCt1c1BlcG41Ym9MM09TcDENCk1MOVMyZ2dNTmtaNUtsVnViY2NGRFlDMnRMa0hyd1FraG1oOWlPNFJ0YXdBU2FXMlB0NHBpUXRXaElNVmV0eG4NCktnOE9oQWhsNlZLV0lwNEVOU0llL2J2WkhGd09iRE9VaTAycmdraHNsTU9COXRXQVJGRWVadlNwMkp3L3ZWcmgNCk9WNk42MktrSEVFMzB3VXZ4VnNOcTB0VldzdDFDUk9HODZJR29iakNPbGpETDdtazFldXhHd2owV2xIL29HNTMNClg4QzU1aWtyWUtIVDJVVHZxMkNvSTFKalFvVjVzYmtmM0UyMnRBYnR6c2VaNSs2eVJBeHk4bGdFUmJFYzdPbG4NCmptQnFKR1EvV1FnYzE1TmhBZ01CQUFFQ2dnR0JBSkc0VG43YWhNWFJzUjlwajU1NFY0cHozaUNFYjVTUHcyQzQNCllvQ3ROdGpnekMrNEM1NHRRYjhWZ1A0R2R0QUVDSmdTMUwyemlHaDMyL3BHU1ZUVnBwNjFnTEVNTkN6VVp0Vk8NCmwzWTBPK0xPYXZnM1BNYnpSUnYyaE02NDlXWDBSSjVZWmRxVWRXbHBjUk9hNlphYU5DM293QXordU14Sko0VFUNCjRTRGlHS0s1OVhRL2JJS05GWlNnNW0wN003ZnVNVmU5M1FDUDh2Y3dIVHZNQkxscSs0dGhNQlRJbFI1OFZBNlINCjJaM0FITG9DdkZxd0xvM2R1bzJzZEZRNDBzM1preTVOZkRZeDdLMTBDSjdHWEdlU1VMWkhISGxTWUUvdXZWdHkNClpsU0ptUFZDUWdoRjl0aDh0Q1MybTRsWGZ6ckpwWEo4ZU5pTlVDdUEvSFdFc0lVb2hEbFJrek84NGc4Q1YyMmwNCnAwWGZMTy9tbXd4RlBkeWlJK1pmT2hROGFZeG5oNHVwN2Y3cmhOTjRHeTgxbE1JazFSeE9Kc21wWTNJMGRLOTgNCnZoVDdkbWR5V2wyb2Fva3NIZDZ6dDMxR05zYlBmQk11TGtnTHRaN3NxSi91MTJURjIvNXI2TkdjUG9Cb0V3NkENClVwR2hOblEyUDkwUXFjYjl2Sk5aQ2JIbWt3Rlc4UUtCd1FEUG9ZOWV4WTVaMEU0YWM5dlNhUFg2OC91Wkc1N1kNCjBFZ1JBYXpjekFwM3BHQlhobzQwa3c0bzBpSmxZUnZ1bGhRVG14cXg2SURmam5OWHBlQk5YMDloWkFBdWpYVngNCmdwUWFUeVhlUkovdmplWmNzNm1raERjSGpzalc4TDdVME44SlVwOUZ1dWRJYXdJbU9Lbm5iN094MWhnRmV5YmoNCkhFdUMyOS9zQTRDdWpFTWR1anBCU0JWTmlhb20raWJsQzBzNFk1NFJISjlTMEQzTHErSXdoMGE0MG1meHZ5b0INCmNRVS81Yi9YbEViallwdHRDS0s1bDgydWgxODhzeENmdG8wQ2djRUF4YnVYUGVRUEJoNENybGNqQ2ovejY3WnYNCk02aWtMM2FUa1F0S2ZKK2E0WnpZanpGR2l0UWZuTVhDSWl6N1BHVzVPMzkyU0plUWNvMTVSNDl2dDRHUVhibEYNCnR6ZHBuWjJnMmEwMVN5RHRMUGdSVnc1K3lUZ0EyUk5FMDNEYWZZZit5RDZLSitrSWRneUZjWWpwZ2R5SE12eXcNCnhINXRKVC9TSGhJYUMwS1JuQWE2cW8rVGdrR2pKd3FlQzYyOHFIZW4yZUlvL2lOYnk0MWttVTNubnJXZTdlSVANCkR4QncreHhUNW5HT3RzRUtKMFFIWng5SkN5UmNwRVNFOWF1YWt6VWxBb0hCQUxXRTZnR1J0eXlmNXRoTGQ5K1ENCnNaUE8zNlB3T01RVit4c2JHdFFCY2hrODFKbFFZbHhtUDlmQ05oM3BjdkQzdGQrYUZ4RjRVY3FnRUFpTlZQWnYNCm44ZG1GSjZlUHhHWWRnQTJOOFlFdXNwRWhTT0FVb3dvcHE5dHpmblRpUkltOVFhQ2ZBb0xKNDN4TjNUUXp3RXQNCmI2ekdua09VY2QvVmFkS2loVFlocmN0cmhuV2p6TEFyNDZ2ZzhhZVh4STh6ZTNSMTZzZk0vU0Q2T3p3bkxkejkNCk52LzN1clhuU1VMdld3YU14bFlqSklKQVA5OW4wRk51K250ZGtBNVNBZk9QTlFLQndEQ3pCQXZsT0dJTVVDSzYNCktWSWo4Q0owdXl5ZzgxY1JRRVR2My9lVG82Uy9hWUxTNHduY05yRDQ3OWhVOWNlcFVoYTZUTnFTSWF4azlhTFANClMvZUpQSklveUdmWWlQV2QxZmptdFFKODZJMHp4Nm1HVTJtaGxtdmdXQW92ZUZDRWh4YXdlSHhkNDR5WGh1SXcNCmt6bzlvenJHaTQ3SmlINHRHc1gzTlZ6aWwxUXpRQlF6Nm1PaFlOcUR2ZXNvYmhlYjZNWTc4bGF0UkxWOGJITnANCmdZdFFOZ1Ztc01qSUJ0dUIzWlFiRWNnbkFTWXNsaG9xMVdXZUhnY0RMVEFJaExpTzFRS0J3SG9wM3RvcE1tdEENCmdnaTlMcCt2RG1EWWJqaDcvSkg1MHpzYVA1eEROeEl3U2tmejZsY21sWWw2Ui9YUFF1Qk0xTG9jb2lrdERWS1oNCmxJYjZib2JiSm5nRGloMkhJQmN3cWFaa29rNHZoNmdWOEREU0Z3QUhRSnJzNzJ4eHdyNytKcWlPQXRSbUhXZmoNCmRtYTlKS045OURoRllqYnlWN2x2QlM4bG5uNVF0QlNDem1XblpXS0NPbWVwMk11aGMzUWd2NUhnSHZCK1VDeHcNCnZRUE1BN0E3VkZhd1IyKys4ZVFJaHVDOUF6VmoxS3FVRlU4ZThlZWpOT1EwNWVGNWJxaGhqZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KPC9Qcml2YXRlS2V5Pg0KPENlcnRpZmljYXRlQ2hhaW4+DQo8TnVtYmVyT2ZDZXJ0aWZpY2F0ZXM+MzwvTnVtYmVyT2ZDZXJ0aWZpY2F0ZXM+DQo8Q2VydGlmaWNhdGUgZm9ybWF0PSJwZW0iPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQo8IS0taHR0cHM6Ly90Lm1lL3l1cmlpcm9vdC0tPg0KTUlJRTN6Q0NBc2VnQXdJQkFnSVFZNmZ5ay9xM2U1OFY4V1JNclNpcGREQU5CZ2txaGtpRzl3MEJBUXNGQURBNQ0KTVF3d0NnWURWUVFNREFOVVJVVXhLVEFuQmdOVkJBVVRJRGszTlRJelpqZzRZVGc1TTJJM09EazRZMkk0TVROag0KWldRellUWmlNalEzTUI0WERUSXdNVEl5TVRFNE5EVXdNbG9YRFRNd01USXhPVEU0TkRVd01sb3dPVEVNTUFvRw0KQTFVRURBd0RWRVZGTVNrd0p3WURWUVFGRXlBeFlXTTJZamd3TlRnMllUWTVZMk5tWXpBMFlUUmlNek5qWkRsbQ0KWldJd05EQ0NBYUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0dQQURDQ0FZb0NnZ0dCQUtCZmVRSW1TUDFTNENDMw0KMnNuRXFDdkMxaXNVQlZGZExoNERzODgyeFhHb3d0VC9rQjJkZWNMeFViNDdXdmJWZXoxRldiRWh6OXdxTTJISw0KUUtDSmFRZXFaV2dlOE5NaVR3ZjlST2MzRHJQalNscUZMWmRzVnNBSXE0amZ6aklvdU8rcCtEdE5MZmZyN1FVcg0KNzdqVFB5WHhSN1hQdjFKbCtzVzZvYWhvdzV0dXBNV3dKMnZxWXFKenN0NUYzTTRJVmo3eE9CQ1pJSzV5M0txUw0KWFlhMUVaQVp4ajBnTWRSc1UvcnJEM3FaK1c2Qzl6a3FkVEMvVXRvSUREWkdlU3BWYm0zSEJRMkF0clM1QjY4RQ0KSklab2ZZanVFYldzQUVtbHRqN2VLWWtMVm9TREZYcmNaeW9QRG9RSVplbFNsaUtlQkRVaUh2MjcyUnhjRG13eg0KbEl0TnE0SkliSlREZ2ZiVmdFUlJIbWIwcWRpY1A3MWE0VGxlamV0aXBCeEJOOU1GTDhWYkRhdExWVnJMZFFrVA0KaHZPaUJxRzR3anBZd3krNXBOWHJzUnNJOUZwUi82QnVkMS9BdWVZcEsyQ2gwOWxFNzZ0Z3FDTlNZMEtGZWJHNQ0KSDl4TnRyUUc3YzdIbWVmdXNrUU1jdkpZQkVXeEhPenBaNDVnYWlSa1Axa0lITmVUWVFJREFRQUJvMk13WVRBZA0KQmdOVkhRNEVGZ1FVT1lZR1lBWFVleUtXYXNDY2JFREwzUnpJVXhvd0h3WURWUjBqQkJnd0ZvQVVDN0ZWWlZ0aw0KQ2diZ3JOVXh6SFFrTm1NSkNtMHdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QU9CZ05WSFE4QkFmOEVCQU1DQWdRdw0KRFFZSktvWklodmNOQVFFTEJRQURnZ0lCQUtxSjF6TUZjcHJWMGlER1REZ3lySVg5UE9kTTdQUG9yQnBiS3NsSA0KUGZoNTYvUDJaMHNHanl6bC9Oc08zanY2Zkl4cWZxeHRkMGxvazVwdnNVcEM3RkR0ZVo5TmZtYXZkalpWMGdVOQ0KK210ak9jcUxnSkRlVGdpR2sxWXN1ZFloeHFIaTczTi9RYUdkY3NTV1JEMUNLNlhIV3FFNnJsY0V4c1F1eHBUQg0KblFmcnU4dDJHcnZYemVpVVRIU3VYbG01bEtCWWJoeUp1MEIyUmszNWdLM3kyVklPU3N4YmU3eENDT2RDUGUwUA0KRjk2cjd3c09OR0MzenE4N0s3NFBqdEZYclU4WDNIYjF5RldBZ05ITzQra0h6bXl5Q1Y0Rmc4Wk9vWXcwbjE5bg0KeHFlTzVuaEpMUHFoSjV5Sk55aHRsZzNJL3llQmM4dXpWSHd6c2tNNTlUMkFHS2pwMVhsSFZiREh2K21xeDFURw0KTlkwbkIyOTRqZG9mTGRKbGZFSE1TZEdBS0dFWnB4cVozL0NjUVNIc1Z1WUlzZkJDbE5RZ1ovZVNIVWFMRVU5VA0KUHBkL29HaFIxUldqbXBwV2J1Zkk2QTJQdSthRU5iZkYxN0N1RjI3Z1NtUTA2SERoS0gwZ3V1U01RTk00Y0NDLw0KN0tUdHAxdkdMdGJxWWVyVlZoajZVRTFTVU9tdWx4Q3llUnFla3BVSkh1T0RjZW95Z1hkY1M2YWdhY1kxYkVGeA0KZkMwL2llZWo3c2JJRGRwTU1nVk56Rk9ETEtRdksyaW5RMzV0dU5XZGlHRDQ4d2thcm9lVGtZNHgrNW5TSWJvbg0KK2NmajRuelMrdGVwTjdSM2x5bzlQQUc2STV6endMbUhGMHYzdWFxaEhwUkgwZmVqd1dwdkN4KzhnbHhQQmtGUQ0KR3BjbA0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KPC9DZXJ0aWZpY2F0ZT4NCjxDZXJ0aWZpY2F0ZSBmb3JtYXQ9InBlbSI+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZRakNDQXlxZ0F3SUJBZ0lSQUxZeDY3RUI0T3N2b1MrTGt0TEVTemd3RFFZSktvWklodmNOQVFFTEJRQXcNCkd6RVpNQmNHQTFVRUJSTVFaamt5TURBNVpUZzFNMkkyWWpBME5UQWVGdzB5TURFeU1qRXhPRFF5TXpOYUZ3MHoNCk1ERXlNVGt4T0RReU16TmFNRGt4RERBS0JnTlZCQXdNQTFSRlJURXBNQ2NHQTFVRUJSTWdPVGMxTWpObU9EaGgNCk9Ea3pZamM0T1RoallqZ3hNMk5sWkROaE5tSXlORGN3Z2dJaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQ0R3QXcNCmdnSUtBb0lDQVFDMVEvbjAydzNUdEZaNVZqZ2ZNV29Fem1WK3o4aVpjdkdnd1lSMVFyK25WdkpkN1RwbjYybkYNClczNktqMjVYaytnL3NQS00wL2dPL2M0dTFlTEgxRUJSeUhrd1RNeGZMR2dXTWEwemhsTVFkNWx5TGFXd1ovTlMNCkRBWmxZeDRTelV0UEJ3RExIVzR6ZjFhMFVIbWFESDlUUmp6WFUzN3ZaOFFNa3FpQi90dXpvMHg3cWIyNEtweW8NCjZUOHd2aDZYTXpzSll2a0NjQjVjZnFlTkVWUmphcnRTYnNGSCtydnNPZDY3eEVvOXpBcWR0eEVSUUR3UFJzc0INCkR5M2xIWUkxN3ZYSVhwb3JvZWdsUjJTSTY0ZndKRFBNQTZ4OUhaczV5dzd3YjdkVGtoSGxlOEVFb21tZUorc1kNClRiNGViS3QwRXNJbEptVWpEelVVeFVQN0hzQ2l1M0swazJzLzNCdDBJS1RFTFV6MUwzMCs0ZHZQV2xFNFVQeGgNCjczc0pqYitVTVAzRmpBWHc0NUV2WHpKNHBvMVdKMk5WREVkVE1UT2RaK2x0QnZjbVRkNndrdkh6eEZ2djFSTzENCmdVMTR6UDYvZDdhK2VoWGJpUnhSTzNGZ2hEZ2h4amZTaWVjU2diZHNDc0hjTms5bWFZblZUWDRlNVZNZnpNc0ENCmtpWkNJZUxrYTRXOGxvTDhzZEM1Qm1oRUVnZzVOelhBZzJ1ZkpBNlBlSm1uay9jK0hhS091Tm9mWHMzemdtS2MNCkE2U2l4TWFqMXNmdCtTcEtxQUJhQVBpTWlCSkc0VGxIWVV5ZkFTdXl1QXNXRUx6bFJVdU42NGRLSE5EM1FJL00NCkF4WTlJb2FtRlFnZXdBYVBUUkExcHFhaEovL3FzRkdITElrNVh3czNONGt5S2lMc050b1lJUUlEQVFBQm8yTXcNCllUQWRCZ05WSFE0RUZnUVVDN0ZWWlZ0a0NnYmdyTlV4ekhRa05tTUpDbTB3SHdZRFZSMGpCQmd3Rm9BVU5tSGgNCkFIeUlCUWxSaTBSc1IvOGFUTW5xVHhJd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBT0JnTlZIUThCQWY4RUJBTUMNCkFnUXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnSUJBSUJjMW9oc1ZFTVRoaWpORnFNV0J4QTh5ZlMwK25uS0VuanANCmg1WUF1dFFXRVozTjYyUEUzR2VCQWdQeFNLazQ2WkVreDZkalhJSWZaWGgxUUsyR0hWWHp1bkl2VTdLWmwrTXoNCnpDOXc2UHdhUnhVc0tUN1k1eU9wU3YyNUhKMU5kTmRzR0hQendNeWd0Zlk1N0JjQ29COGN1dENPL3VqZkROcDYNCmxrOHdKTnZNM0NlSmx2UlVwN3NBVVdXdjVvZVExRk9LM2JQQ0lEMEJsZU5ObVY2OVdWbnVHOUQzNExaUXc3UXANClBLbnZmek5ueENZaWZhazFKQVdOY3dZK1ZDL1Q4Tm9GODZyeVhpbHBZNndEMXY2RURsMDZxOHVHTTFVS0pPRWUNCjJwN3hjN1craU0remZueHJYK1dYUG11ak5TcGVicmpESnZFaGhteXlVdHJ2MElMaUxYSS9GU00wcnRyd2F3MUUNCkQzd0Nuc1Z4bWhFUTVTdG5MeUJYTEZCUWxTUFY5ckpaZXFpSFhWekhmRm0va2tvZ29LRitEcExLRTI2YzA0RFENCkVucUpyRzBzVk1WZStrdXpqOVFXNWlla20rYlZkQ0FqMXNEVHNnZUNGczBhak9oYk93K296Z0g5L2phbm1mQ0cNCkNPbFc0SzVocVBKRVJ0a01UWmZxanZrMU1ieDV6Vk1ZTm9IZVExRFNId3k3MDNMeW5TNExha2ZzUjlIZFFZd2ENCnBUbG5nVDhUNU9SY0drTVhETUp2a01HUzQ3amEzREhYcGxKczROMk5ZcGRtZlY1dlhoOWhtU1pDb1JzdlpIWEYNCjFPbWR2MGF0N1hEeW1QWnB3MXJZbGZPaysrOUNvVUFCTklJMU9oUkt3YnNmM3ZzRnZUWTE5MmRhcy9oNElHSG4NCkM5WmEyeitrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo8L0NlcnRpZmljYXRlPg0KPENlcnRpZmljYXRlIGZvcm1hdD0icGVtIj4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KPCEtLWh0dHBzOi8vdC5tZS95dXJpaXJvb3QtLT4NCk1JSUZIRENDQXdTZ0F3SUJBZ0lKQU5VUDhsdWo4dGF6TUEwR0NTcUdTSWIzRFFFQkN3VUFNQnN4R1RBWEJnTlYNCkJBVVRFR1k1TWpBd09XVTROVE5pTm1Jd05EVXdIaGNOTVRreE1USXlNakF6TnpVNFdoY05NelF4TVRFNE1qQXoNCk56VTRXakFiTVJrd0Z3WURWUVFGRXhCbU9USXdNRGxsT0RVellqWmlNRFExTUlJQ0lqQU5CZ2txaGtpRzl3MEINCkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQXI3YkhnaXV4cHdIc0s3UXVpOHhVRm1Pcjc1Z3ZNc2QvZFRFRERKZFMNClN4dGY2QW43eHlxcFJSOTBQTDJhYnhNMWRFcWxYbmYydHF3MU5lNFh3bDVqbFJmZG5KTG1OMHBUeS80bGo0LzcNCnR2MFNrM2lpS2t5cG5FVXRSNldmTWdIMFFaZktITTErZGkreTlURlJ0djZ5Ly8wcmIrVCtXOGE5bnNOTC9nZ2oNCm5hcjg2NDYxcU8wck9zMmNYanAza09HMUZFSjVNVm1GbUJHdG5yS3BhNzNYcFh5VHFSeEIvTTBuMW4vVzluR3ENCkM0RlNZYTA0VDZONVJJWkdCTjJ6Mk1UNUlLR2JGbGJDOFVyVzBEeFc3QVlJbVFRY0h0R2wvbTAwUUxWV3V0SFENCm9WSlluRlBsWFRjSFl2QVNMdStSaGhzYkRteE1nSkowbWNEcHZzQzRQanZCK1R4eXdFbGdTNzB2RTBYbUxEK08NCkp0dnNCc2xIWnZQQktDT2RUME1TK3RnU09JZmdhK3oxWjFnNytEVmFnZjdxdXZtYWc4amZQaW95S3Z4bksvRWcNCnNUVVZpMmdoenE4d20yN3VkL21JTTdBWTJxRU9SUjhHbzNUVkI0SHpXUWdwWnJ0M2k1TUlsQ2FZNTA0THpTUmkNCmlnSEN6QVBsSHdzK1cwckI1TitlcjUvMnBKS25mQlNEaUNpRkFWdENMT1o3Z0xpTW0wamhPMkI2dFVYSEkvK00NClJQankwMmk1OWxJTk1SUmV2NTZHS3RjZDlxTy8wa1VKV2RaVGRBMlhvUzgyaXhQdlp0WFFwVXB1TDEyYWIrOUUNCmFESzhaNFJISllZZkNUM1E1dk5BWGFpV1ErOFBUV20yUWdCUi9ia3dTV2MrTnBVRmdOUE45UHZRaThXRWc1VW0NCkFHTUNBd0VBQWFOak1HRXdIUVlEVlIwT0JCWUVGRFpoNFFCOGlBVUpVWXRFYkVmL0dreko2azhTTUI4R0ExVWQNCkl3UVlNQmFBRkRaaDRRQjhpQVVKVVl0RWJFZi9Ha3pKNms4U01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RnWUQNClZSMFBBUUgvQkFRREFnSUVNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUNBUUJPTWFCYzhvdW1YYjJ2b2M3WENXbnUNClhLaEJCSzNlMktNR3ozOXQ3bEEzWFhSZTJaTExBa0xNNXkzSjd0VVJrZjVhMVN1dGZkT3lYQW1lRTZTUm84M1UNCmg2V3N6b2RtTWt4SzVHTTRKR3JudDRwQmlzdTVpZ1hFeWRhVzdxcTJDZEM2RE9HakcrbUVrTjgvVEE2cDNjbm8NCkwvc1B5ejZldmRqTGxTZUo4ckZCSDZ4V3lJWkNicmNwWUVKelhhVU9FYXh4WHhnWXo1L2NUaVZLTjJNMUcyb2sNClFCVUlZU1k2YmpFTDRhVU41Y2ZvN29nUDNVdmxpRW8zRW8wWWd3dXpSMnYwS1I2QzFjWnFaSlNUbmdoSUMvdkENCkQzMktkTlErYzNOK3ZsMk9Uc1VWTUMxR2lXa25nTngxT08xK2tYVytZVG5uVFVPdE9Jc3dVUC9WcWQ1U1lnQUkNCm1NQWZZOFU5L2lJZ2tRajZUMlc2RnNTY3k5NElOOWZGaEUxVXR6bUxvQkl1VUZzVlhKTVR6K0p1Y3RoK0lxb1cNCkZ1YTl2MVI5My9rOThwNDFwanRGWCtIOERzbFZnZlAwOTd2anU0S0RscU42NHhWMWdydzNaTGw0Q2lPZS9BOTENCm9lTG0yVUhPcTZ3bjNlc0I0cjJFSVFLYjZqVFZHdTVzWUNjZFdwWHIwQVVWcWNBQlBkZ0wrSDdxSmd1QncwOW8NCmptNnhOSXJ3Mk9vY3JES3N1ZGsvb2tyL0F3cUV5UEt3OVduTWxRZ0xJS3cxck9ERzJOdlU5b1IzR1ZHZE1rVUINClp1dEw4VnVGa0VSUUd0NnZRMk9DdzBzVjQ3Vk1rdVliYWNLL3h5WkZpUmNyUEpQYjQxemdiUWo5WEFFeUxLQ0gNCmV4MFNkRHJ4K3RXVURxRzhBdDJKSEE9PQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KPC9DZXJ0aWZpY2F0ZT4NCjwvQ2VydGlmaWNhdGVDaGFpbj4NCjwvS2V5Pg0KPC9LZXlib3g+DQo8L0FuZHJvaWRBdHRlc3RhdGlvbj4NCjwhLS1UaGFua3MgZm9yIHVzZSBteSBrZXlib3guIEpvaW4gbXkgZ3JvdXA6IGh0dHBzOi8vdC5tZS95dXJpaXJvb3QtLT4= -------------------------------------------------------------------------------- /Module/webroot/css/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://mui.kernelsu.org/internal/colors.css'); 2 | 3 | /* ============================================ 4 | 🔹 COLOR PALETTE VARIABLES 5 | Define all main colors here for easy theme management 6 | ============================================ */ 7 | :root { 8 | --green: #66bb6a; 9 | --primary-red: #ef5350; 10 | --accent-pink: #4fc3f7; 11 | --deep-pink: #82d7ff; 12 | --gothic-black: #121212; 13 | --gothic-purple: #1e1e1e; 14 | --soft-white: #ffffff; 15 | --soft-gray: #2c2c2c; 16 | --secondary-bg: #1e1e1e; 17 | --secondary-border: #2c2c2c; 18 | --nav-inactive: #888; 19 | } 20 | 21 | /* ================================================= 22 | 🔹 MONET 23 | Credits to bindhosts for being a great reference 24 | ==================================================== */ 25 | :root { 26 | --monet-bg-primary: var(--background, #F5F5F5); 27 | --monet-bg-secondary: var(--tonalSurface, #fff); 28 | --monet-bg-input: var(--surfaceBright, #F5F5F5); 29 | --monet-text-primary: var(--onSurface, #000); 30 | --monet-text-muted: #757575; 31 | --monet-border-color: var(--outlineVariant, #ccc); 32 | --monet-border-alt: var(--filledTonalButtonContainerColor, #ddd); 33 | --monet-border-alt-text: var(--filledTonalButtonContentColor, #333); 34 | --monet-btn-primary: var(--primary, #007bff); 35 | --monet-btn-primary-text: var(--onPrimary, #fff); 36 | --monet-shadow-light: rgba(0, 0, 0, 0.2); 37 | --monet-shadow-medium: rgba(0, 0, 0, 0.5); 38 | } 39 | 40 | @media (prefers-color-scheme: dark) { 41 | :root { 42 | --monet-bg-primary: var(--background, #151515); 43 | --monet-bg-secondary: var(--tonalSurface, #292929); 44 | --monet-bg-input: var(--surfaceBright, #1b1b1b); 45 | --monet-text-primary: var(--onSurface, #eee); 46 | --monet-text-muted: #C2C2C2; 47 | --monet-border-color: var(--outlineVariant, #636363); 48 | --monet-border-alt: var(--filledTonalButtonContainerColor, #666); 49 | --monet-border-alt-text: var(--filledTonalButtonContentColor, #eee); 50 | } 51 | } 52 | 53 | .theme-transition * { 54 | transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease !important; 55 | } 56 | 57 | /* ============================================ 58 | 🔹 GLOBAL BASE STYLES 59 | Reset, box-sizing, body background and font setup 60 | ============================================ */ 61 | * { 62 | box-sizing: border-box; 63 | } 64 | body { 65 | position: relative; 66 | z-index: 0; 67 | background-color: var(--gothic-black); 68 | font-family: 'Inter', sans-serif; 69 | color: var(--soft-white); 70 | } 71 | 72 | /* ============================================ 73 | 🔹 PAGE LAYOUT AND VISIBILITY 74 | ============================================ */ 75 | #page-content { 76 | min-height: calc(100vh - 64px); 77 | max-width: 1024px; 78 | margin: 0 auto; 79 | padding: 0.5rem 10px 0.5rem; 80 | overflow: hidden; 81 | } 82 | .page { 83 | display: none; 84 | flex-direction: column; 85 | width: 100%; 86 | opacity: 0; 87 | transform: translateX(20px); 88 | transition: opacity 0.3s ease, transform 0.3s ease; 89 | pointer-events: none; 90 | overflow-y: auto; 91 | } 92 | .page.active { 93 | display: flex; 94 | opacity: 1; 95 | transform: translateX(0); 96 | pointer-events: auto; 97 | z-index: 10; 98 | margin-bottom: 64px; 99 | } 100 | 101 | /* ============================================ 102 | 🔹 BOTTOM NAVIGATION BAR 103 | ============================================ */ 104 | .bottom-nav { 105 | position: fixed; 106 | bottom: 0; left: 0; 107 | width: 100%; 108 | height: 64px; 109 | background-color: var(--gothic-purple); 110 | border-top: 1px solid var(--secondary-border); 111 | display: flex; 112 | justify-content: space-around; 113 | align-items: center; 114 | z-index: 1000; 115 | } 116 | .nav-btn { 117 | flex: 1; 118 | padding: 0.75rem 0; 119 | font-size: 13px; 120 | color: var(--nav-inactive); 121 | background: none; 122 | border: none; 123 | display: flex; 124 | flex-direction: column; 125 | align-items: center; 126 | justify-content: center; 127 | transition: color 0.3s ease; 128 | cursor: pointer; 129 | } 130 | .nav-btn.active { 131 | color: var(--accent-pink); 132 | } 133 | .nav-icon { 134 | width: 22px; 135 | height: 22px; 136 | margin-bottom: 4px; 137 | object-fit: contain; 138 | filter: brightness(0.6); 139 | transition: filter 0.3s ease; 140 | } 141 | .nav-btn.active .nav-icon { 142 | filter: brightness(1.2); 143 | } 144 | 145 | /* ============================================ 146 | 🔹 REFRESH SECTION 147 | ============================================ */ 148 | .refresh-section { 149 | display: flex; 150 | justify-content: end; 151 | margin-bottom: 1rem; 152 | } 153 | 154 | .refresh-btn-main { 155 | display: flex; 156 | align-items: center; 157 | gap: 0.75rem; 158 | padding: 0.75rem 1.5rem; 159 | background-color: var(--secondary-border); 160 | color: var(--soft-white); 161 | border: 1px solid #3a3a3a; 162 | border-radius: 12px; 163 | cursor: pointer; 164 | font-size: 14px; 165 | font-weight: 500; 166 | transition: all 0.2s ease; 167 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); 168 | } 169 | 170 | .refresh-btn-main:hover { 171 | background-color: #3a3a3a; 172 | border-color: var(--accent-pink); 173 | transform: translateY(-2px); 174 | box-shadow: 0 4px 16px rgba(79, 195, 247, 0.3); 175 | } 176 | 177 | .refresh-btn-main img { 178 | width: 18px; 179 | height: 18px; 180 | filter: brightness(0.8); 181 | transition: filter 0.2s ease; 182 | } 183 | 184 | .refresh-btn-main:hover img { 185 | filter: brightness(1); 186 | } 187 | 188 | .version-text { 189 | font-size: 22px; 190 | font-weight: 800; 191 | color: var(--accent-pink); 192 | } 193 | 194 | /* ============================================ 195 | 🔹 INFO CARDS GRID 196 | ============================================ */ 197 | .info-cards-grid { 198 | display: grid; 199 | grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); 200 | gap: 1.5rem; 201 | margin-top: 1rem; 202 | } 203 | 204 | .info-card { 205 | background: linear-gradient(145deg, var(--gothic-purple), #1a1a1a); 206 | border: 1px solid var(--secondary-border); 207 | border-radius: 16px; 208 | padding: 1.5rem; 209 | transition: all 0.3s ease; 210 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); 211 | position: relative; 212 | overflow: hidden; 213 | } 214 | 215 | .info-card::before { 216 | content: ''; 217 | position: absolute; 218 | top: 0; 219 | left: 0; 220 | right: 0; 221 | height: 3px; 222 | background: linear-gradient(90deg, var(--accent-pink), var(--deep-pink)); 223 | opacity: 0.6; 224 | } 225 | 226 | .info-card:hover { 227 | transform: translateY(-4px); 228 | box-shadow: 0 8px 24px rgba(79, 195, 247, 0.2); 229 | border-color: var(--accent-pink); 230 | } 231 | 232 | .info-card:hover::before { 233 | opacity: 1; 234 | } 235 | 236 | .card-header { 237 | margin-bottom: 1rem; 238 | } 239 | 240 | .card-header h3 { 241 | font-size: 14px; 242 | font-weight: 600; 243 | color: var(--nav-inactive); 244 | margin: 0; 245 | text-transform: uppercase; 246 | letter-spacing: 0.5px; 247 | } 248 | 249 | .card-content { 250 | display: flex; 251 | align-items: center; 252 | justify-content: center; 253 | min-height: 3rem; 254 | } 255 | 256 | .card-value { 257 | font-size: 16px; 258 | font-weight: 600; 259 | color: var(--soft-white); 260 | padding: 0.5rem 1rem; 261 | background-color: rgba(79, 195, 247, 0.1); 262 | border: 1px solid rgba(79, 195, 247, 0.3); 263 | border-radius: 10px; 264 | text-align: center; 265 | min-width: 120px; 266 | transition: all 0.2s ease; 267 | white-space: nowrap; 268 | } 269 | 270 | .card-value:hover { 271 | background-color: rgba(79, 195, 247, 0.2); 272 | border-color: var(--accent-pink); 273 | transform: scale(1.05); 274 | } 275 | 276 | .status-card { 277 | border-color: #ef5350; 278 | } 279 | 280 | .status-card::before { 281 | background: linear-gradient(90deg, #ef5350, #e57373); 282 | } 283 | 284 | .status-card .card-value { 285 | background-color: rgba(239, 83, 80, 0.1); 286 | border-color: rgba(239, 83, 80, 0.3); 287 | color: #ef5350; 288 | } 289 | 290 | .status-card.offline { 291 | border-color: #ef5350; 292 | } 293 | 294 | .status-card.offline::before { 295 | background: linear-gradient(90deg, #ef5350, #e57373); 296 | } 297 | 298 | .status-card.offline .card-value { 299 | background-color: rgba(239, 83, 80, 0.1); 300 | border-color: rgba(239, 83, 80, 0.3); 301 | color: #ef5350; 302 | } 303 | 304 | .status-card.online { 305 | border-color: var(--green); 306 | } 307 | 308 | .status-card.online::before { 309 | background: linear-gradient(90deg, var(--green), #81c784); 310 | } 311 | 312 | .status-card.online .card-value { 313 | background-color: rgba(102, 187, 106, 0.1); 314 | border-color: rgba(102, 187, 106, 0.3); 315 | color: var(--green); 316 | } 317 | 318 | /* ============================================ 319 | 🔹 INFO BOX (for other sections) 320 | ============================================ */ 321 | .info-box { 322 | position: relative; 323 | background-color: var(--gothic-purple); 324 | padding: 1rem; 325 | border-radius: 10px; 326 | border: 1px solid var(--secondary-border); 327 | font-size: 14px; 328 | line-height: 1.6; 329 | overflow-x: auto; 330 | } 331 | .info-content { 332 | margin-top: 2rem; 333 | } 334 | 335 | /* ============================================ 336 | 🔹 ACTION BOX AND BUTTONS 337 | ============================================ */ 338 | .action-box { 339 | margin-top: 1.5rem; 340 | padding: 1.5rem; 341 | background-color: rgba(29, 29, 29, 0.3); 342 | border-radius: 12px; 343 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.3); 344 | animation: fadeIn 0.3s ease; 345 | } 346 | .action-title { 347 | font-size: 16px; 348 | font-weight: 600; 349 | margin-bottom: 1rem; 350 | border-bottom: 1px solid var(--secondary-border); 351 | padding-bottom: 0.5rem; 352 | text-align: center; 353 | text-transform: uppercase; 354 | letter-spacing: 1px; 355 | color: var(--accent-pink); 356 | } 357 | .action-buttons { 358 | display: flex; 359 | flex-direction: column; 360 | align-items: center; 361 | gap: 1rem; 362 | margin-top: 1rem; 363 | } 364 | .action-buttons button, 365 | .action-buttons .menu-btn { 366 | width: 100%; 367 | max-width: 360px; 368 | padding: 1rem 1.5rem; 369 | font-size: 15px; 370 | font-weight: 500; 371 | color: var(--soft-white); 372 | background-color: #2a2a2a; 373 | border: 1px solid #3a3a3a; 374 | border-radius: 14px; 375 | cursor: pointer; 376 | text-align: center; 377 | transition: background-color 0.2s ease, transform 0.1s ease, border 0.2s ease; 378 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); 379 | } 380 | .action-buttons button:hover, 381 | .action-buttons .menu-btn:hover { 382 | background-color: #3a3a3a; 383 | border-color: #4a4a4a; 384 | color: var(--soft-white); 385 | } 386 | .action-buttons button:active, 387 | .action-buttons .menu-btn:active { 388 | background-color: #444; 389 | transform: scale(0.97); 390 | } 391 | 392 | /* ============================================ 393 | 🔹 SETTINGS BUTTONS 394 | ============================================ */ 395 | .setting-btn { 396 | width: 100%; 397 | margin: 0.5rem 0; 398 | padding: 0.75rem; 399 | font-size: 14px; 400 | font-weight: 500; 401 | border-radius: 10px; 402 | background-color: var(--secondary-border); 403 | color: var(--soft-white); 404 | border: none; 405 | cursor: pointer; 406 | transition: background 0.2s ease; 407 | } 408 | .setting-btn:hover { 409 | background-color: #3a3a3a; 410 | } 411 | .note { 412 | font-size: 12px; 413 | color: var(--nav-inactive); 414 | margin-bottom: 1rem; 415 | } 416 | 417 | /* ============================================ 418 | 🔹 DROPDOWN COMPONENT 419 | ============================================ */ 420 | .custom-dropdown { 421 | position: relative; 422 | width: 100%; 423 | } 424 | .dropdown-list { 425 | display: none; 426 | list-style: none; 427 | margin-top: 0.25rem; 428 | padding: 0; 429 | background-color: var(--gothic-purple); 430 | border: 1px solid var(--secondary-border); 431 | border-radius: 10px; 432 | max-height: 240px; 433 | overflow-y: auto; 434 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); 435 | scrollbar-width: thin; 436 | scrollbar-color: var(--secondary-border) var(--gothic-purple); 437 | } 438 | .dropdown-list.show { 439 | display: block; 440 | } 441 | .dropdown-list li { 442 | padding: 0.75rem; 443 | font-size: 14px; 444 | cursor: pointer; 445 | border-bottom: 1px solid var(--secondary-border); 446 | transition: background 0.2s ease; 447 | } 448 | .dropdown-list li:hover { 449 | background-color: #333; 450 | } 451 | .dropdown-list li.selected { 452 | background-color: var(--accent-pink); 453 | color: var(--soft-white); 454 | font-weight: bold; 455 | } 456 | 457 | /* ============================================ 458 | 🔹 DEVELOPER INFO SECTION 459 | ============================================ */ 460 | #dev-info { 461 | margin-top: 2rem; 462 | padding: 1rem; 463 | background-color: var(--gothic-purple); 464 | border-radius: 12px; 465 | border: 1px solid var(--secondary-border); 466 | } 467 | #dev-info h3 { 468 | font-size: 16px; 469 | font-weight: 600; 470 | color: var(--accent-pink); 471 | margin-bottom: 1rem; 472 | border-bottom: 1px solid var(--secondary-border); 473 | padding-bottom: 0.5rem; 474 | text-align: center; 475 | } 476 | 477 | /* ============================================ 478 | 🔹 CONTRIBUTORS GRID 479 | ============================================ */ 480 | .contrib-grid { 481 | display: grid; 482 | grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); 483 | gap: 1.5rem; 484 | margin-top: 1rem; 485 | padding-bottom: 1rem; 486 | box-sizing: border-box; 487 | } 488 | .container-behind { 489 | background-color: rgba(34, 22, 34, 0.3); 490 | position: relative; 491 | z-index: 0; 492 | } 493 | .contrib-card { 494 | background: linear-gradient(to bottom right, #1f1f1f, #262626); 495 | border: 1px solid var(--secondary-border); 496 | border-radius: 14px; 497 | padding: 1.2rem; 498 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); 499 | backdrop-filter: blur(4px); 500 | position: relative; 501 | z-index: 1; 502 | text-align: center; 503 | text-decoration: none; 504 | transition: all 0.25s ease; 505 | } 506 | .contrib-card:hover { 507 | transform: translateY(-4px); 508 | box-shadow: 0 4px 14px rgba(79, 195, 247, 0.15); 509 | border-color: var(--accent-pink); 510 | } 511 | .contrib-card img { 512 | width: 72px; 513 | height: 72px; 514 | border-radius: 50%; 515 | object-fit: cover; 516 | margin-bottom: 0.75rem; 517 | border: 2px solid var(--accent-pink); 518 | transition: border 0.3s ease; 519 | background-color: transparent; 520 | } 521 | .contrib-card:hover img { 522 | border-color: var(--deep-pink); 523 | } 524 | .contrib-name { 525 | font-size: 15px; 526 | font-weight: 600; 527 | color: var(--soft-white); 528 | margin-bottom: 0.3rem; 529 | } 530 | .contrib-role { 531 | font-size: 13px; 532 | color: var(--nav-inactive); 533 | line-height: 1.4; 534 | } 535 | 536 | /* ============================================ 537 | 🔹 UPDATE BOX 538 | ============================================ */ 539 | .update-box { 540 | padding: 2rem; 541 | background-color: var(--gothic-purple); 542 | border-radius: 16px; 543 | border: 1px solid var(--secondary-border); 544 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.25); 545 | text-align: center; 546 | animation: fadeIn 0.3s ease; 547 | } 548 | .update-box .action-title { 549 | font-size: 16px; 550 | font-weight: 600; 551 | margin-bottom: 1.2rem; 552 | text-transform: uppercase; 553 | letter-spacing: 1px; 554 | border-bottom: 1px solid var(--secondary-border); 555 | padding-bottom: 0.5rem; 556 | color: var(--accent-pink); 557 | } 558 | .update-links { 559 | display: flex; 560 | flex-direction: column; 561 | align-items: center; 562 | gap: 1rem; 563 | margin: 1.5rem 0; 564 | } 565 | .update-link { 566 | display: flex; 567 | align-items: center; 568 | gap: 0.75rem; 569 | padding: 0.8rem 1.2rem; 570 | background-color: #2a2a2a; 571 | border: 1px solid #3a3a3a; 572 | border-radius: 12px; 573 | color: var(--soft-white); 574 | font-size: 14px; 575 | font-weight: 500; 576 | text-decoration: none; 577 | transition: background 0.2s ease, transform 0.1s ease; 578 | cursor: pointer; 579 | } 580 | .update-link:hover { 581 | background-color: #3a3a3a; 582 | transform: scale(1.03); 583 | } 584 | .update-icon { 585 | width: 40px; 586 | height: 40px; 587 | border-radius: 50%; 588 | object-fit: cover; 589 | overflow: hidden; 590 | } 591 | 592 | /* ============================================ 593 | 🔹 ANIMATIONS 594 | ============================================ */ 595 | @keyframes fadeIn { 596 | from { 597 | opacity: 0; 598 | transform: translateY(5px); 599 | } 600 | to { 601 | opacity: 1; 602 | transform: translateY(0); 603 | } 604 | } 605 | 606 | /* ============================================ 607 | 🔹 RESPONSIVE MEDIA QUERIES 608 | ============================================ */ 609 | @media (max-width: 768px) { 610 | .nav-btn { 611 | font-size: 12px; 612 | padding: 0.5rem 0; 613 | } 614 | .nav-icon { 615 | width: 20px; 616 | height: 20px; 617 | } 618 | .action-buttons button, 619 | .setting-btn { 620 | font-size: 13px; 621 | padding: 0.75rem 1rem; 622 | } 623 | .info-box, 624 | .action-box, 625 | .update-box, 626 | #dev-info { 627 | padding: 1rem; 628 | } 629 | .contrib-grid { 630 | grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); 631 | } 632 | .update-icon { 633 | width: 32px; 634 | height: 32px; 635 | } 636 | 637 | .info-cards-grid { 638 | grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); 639 | gap: 1rem; 640 | } 641 | 642 | .info-card { 643 | padding: 1.2rem; 644 | } 645 | 646 | .card-header h3 { 647 | font-size: 13px; 648 | } 649 | 650 | .card-value { 651 | font-size: 14px; 652 | padding: 0.4rem 0.8rem; 653 | min-width: 100px; 654 | } 655 | 656 | .refresh-btn-main { 657 | padding: 0.6rem 1.2rem; 658 | font-size: 13px; 659 | } 660 | 661 | .refresh-btn-main img { 662 | width: 16px; 663 | height: 16px; 664 | } 665 | } 666 | 667 | @media (max-width: 480px) { 668 | .info-cards-grid { 669 | grid-template-columns: 1fr; 670 | gap: 1rem; 671 | } 672 | 673 | .info-card { 674 | padding: 1rem; 675 | } 676 | 677 | .card-header h3 { 678 | font-size: 12px; 679 | } 680 | 681 | .card-value { 682 | font-size: 13px; 683 | padding: 0.4rem 0.6rem; 684 | min-width: 80px; 685 | } 686 | } 687 | 688 | /* ============================================ 689 | 🔹 TYPOGRAPHY AND MISC 690 | ============================================ */ 691 | .main-title { 692 | font-size: 24px; 693 | font-weight: 700; 694 | color: var(--accent-pink); 695 | margin-top: 3rem; 696 | margin-bottom: 3rem; 697 | text-align: center; 698 | text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); 699 | letter-spacing: 1px; 700 | } 701 | .big-title { 702 | font-size: 32px; 703 | font-weight: 700; 704 | color: var(--accent-pink); 705 | margin-top: 3rem; 706 | margin-bottom: 3rem; 707 | text-align: center; 708 | } 709 | 710 | /* ============================================ 711 | 🔹 MENU BUTTONS 712 | ============================================ */ 713 | .menu-btn { 714 | background-color: #444; 715 | border: none; 716 | color: white; 717 | padding: 10px 18px; 718 | font-size: 14px; 719 | border-radius: 4px; 720 | cursor: pointer; 721 | margin-right: 10px; 722 | margin-left: 10px; 723 | transition: background-color 0.3s ease, box-shadow 0.3s ease; 724 | } 725 | .menu-btn:hover { 726 | background-color: #666; 727 | box-shadow: 0 0 8px var(--accent-pink); 728 | border: 1px solid var(--accent-pink); 729 | } 730 | .split-items { 731 | display: flex; 732 | flex-direction: row; 733 | gap: 10px; 734 | justify-content: space-between; 735 | align-items: center; 736 | } 737 | .gap-2 { 738 | gap: 2rem; 739 | } 740 | 741 | .menu-btn img { 742 | width: 16px; 743 | height: 16px; 744 | filter: brightness(0.8); 745 | transition: filter 0.2s ease; 746 | } 747 | 748 | .menu-btn:hover img { 749 | filter: brightness(1); 750 | } 751 | .button-group { 752 | display: flex; 753 | gap: 10px; 754 | margin-bottom: 1rem; 755 | } 756 | 757 | /* ============================================ 758 | 🔹 TOAST NOTIFICATION 759 | ============================================ */ 760 | #toast-container { 761 | position: fixed; 762 | top: 20px; 763 | right: 20px; 764 | z-index: 9999; 765 | display: flex; 766 | flex-direction: column; 767 | gap: 12px; 768 | max-width: 400px; 769 | pointer-events: none; 770 | } 771 | 772 | .toast { 773 | background: var(--secondary-bg); 774 | color: var(--soft-white); 775 | padding: 16px 20px; 776 | border-radius: 12px; 777 | font-size: 14px; 778 | font-weight: 500; 779 | line-height: 1.4; 780 | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); 781 | border: 1px solid var(--secondary-border); 782 | opacity: 0; 783 | transform: translateX(100%); 784 | animation: toast-slidein 0.3s ease forwards, 785 | toast-slideout 0.3s ease 3s forwards; 786 | pointer-events: auto; 787 | cursor: pointer; 788 | transition: transform 0.2s ease; 789 | } 790 | 791 | .toast:hover { 792 | transform: translateX(0) scale(1.02); 793 | } 794 | 795 | .toast.success { 796 | border-left: 4px solid var(--green); 797 | } 798 | 799 | .toast.error { 800 | border-left: 4px solid var(--primary-red); 801 | } 802 | 803 | .toast.warning { 804 | border-left: 4px solid #ffc107; 805 | } 806 | 807 | .toast.info { 808 | border-left: 4px solid var(--accent-pink); 809 | } 810 | 811 | @keyframes toast-slidein { 812 | to { 813 | opacity: 1; 814 | transform: translateX(0); 815 | } 816 | } 817 | 818 | @keyframes toast-slideout { 819 | to { 820 | opacity: 0; 821 | transform: translateX(100%); 822 | } 823 | } 824 | 825 | /* ============================================ 826 | 🔹 SECTIONS 827 | ============================================ */ 828 | .sec-title { 829 | font-size: 25px; 830 | font-weight: 600; 831 | color: var(--accent-pink); 832 | margin-top: 0; 833 | margin-bottom: 1rem; 834 | } 835 | 836 | /* Responsive penyesuaian */ 837 | @media (max-width: 480px) { 838 | #toast-container { 839 | top: 10px; 840 | right: 10px; 841 | left: 10px; 842 | max-width: none; 843 | } 844 | 845 | .toast { 846 | font-size: 13px; 847 | padding: 12px 16px; 848 | border-radius: 8px; 849 | } 850 | } 851 | --------------------------------------------------------------------------------