From 7bef3d93819828bd1c44037e451ec99ae435efa5 Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 12:13:34 +0530 Subject: [PATCH 1/5] fix(ci): resolve syntax errors and unclosed if blocks in workflows --- .github/workflows/android13.yml | 2 -- .github/workflows/android14.yml | 2 -- .github/workflows/android16.yml | 5 +++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android13.yml b/.github/workflows/android13.yml index 4260f42..08190ee 100644 --- a/.github/workflows/android13.yml +++ b/.github/workflows/android13.yml @@ -334,8 +334,6 @@ jobs: FEATURES_LIST+=("- Add Gboard Support") fi - if [ ${#FEATURES_LIST[@]} -eq 0 ]; then - if [ ${#FEATURES_LIST[@]} -eq 0 ]; then FEATURES="- Signature Verification Bypass (default)" else diff --git a/.github/workflows/android14.yml b/.github/workflows/android14.yml index 623c43d..174ec18 100644 --- a/.github/workflows/android14.yml +++ b/.github/workflows/android14.yml @@ -334,8 +334,6 @@ jobs: FEATURES_LIST+=("- Add Gboard Support") fi - if [ ${#FEATURES_LIST[@]} -eq 0 ]; then - if [ ${#FEATURES_LIST[@]} -eq 0 ]; then FEATURES="- Signature Verification Bypass (default)" else diff --git a/.github/workflows/android16.yml b/.github/workflows/android16.yml index 5512adc..a5d2f62 100644 --- a/.github/workflows/android16.yml +++ b/.github/workflows/android16.yml @@ -312,7 +312,7 @@ jobs: await github.rest.git.deleteRef({ owner: context.repo.owner, repo: context.repo.repo, - ref: 'tags/${{ steps.release_info.outputs.tag }}' + ref: 'tags/' + '${{ steps.release_info.outputs.tag }}' }); } catch (e) { console.log('Tag might not exist, continuing...'); @@ -402,7 +402,8 @@ jobs: tag_name: ${{ steps.release_info.outputs.tag }} name: ${{ steps.release_info.outputs.name }} files: ${{ steps.find_zip.outputs.file_path }} - body: ${{ steps.generate_release_body.outputs.release_body }} + body: | + ${{ steps.generate_release_body.outputs.release_body }} - name: Upload patched jars uses: actions/upload-artifact@v4 From a2d169c49e46b7a97b106cea86a161cd5616653d Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 12:13:38 +0530 Subject: [PATCH 2/5] perf(core): optimize smali method search and fix printf I/O error --- scripts/core/patching.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) mode change 100644 => 100755 scripts/core/patching.sh diff --git a/scripts/core/patching.sh b/scripts/core/patching.sh old mode 100644 new mode 100755 index 795de52..4d13ba9 --- a/scripts/core/patching.sh +++ b/scripts/core/patching.sh @@ -5,11 +5,7 @@ find_smali_method_file() { local decompile_dir="$1" local method="$2" - # returns first match (stdout) - find "$decompile_dir" -type f -name "*.smali" -print0 | - xargs -0 grep -s -l -- ".method" 2>/dev/null | - xargs -r -I{} sh -c "grep -s -q \"[[:space:]]*\\.method.*${method}\" \"{}\" && printf '%s\n' \"{}\"" | - head -n1 + grep -r -l --include="*.smali" "[[:space:]]*\.method.*${method}" "$decompile_dir" 2>/dev/null | head -n1 } add_static_return_patch() { From 48ca29f342f0ab20a5e9b3347cdd919c50e8e034 Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 12:13:42 +0530 Subject: [PATCH 3/5] refactor(scripts): remove redundant functions and unify patching logic --- scripts/patcher_a13.sh | 128 +---------------------------------------- scripts/patcher_a14.sh | 128 +---------------------------------------- 2 files changed, 2 insertions(+), 254 deletions(-) mode change 100644 => 100755 scripts/patcher_a13.sh diff --git a/scripts/patcher_a13.sh b/scripts/patcher_a13.sh old mode 100644 new mode 100755 index ccc1ede..95e4e1a --- a/scripts/patcher_a13.sh +++ b/scripts/patcher_a13.sh @@ -95,134 +95,8 @@ recompile_jar() { echo "Created patched JAR: $patched_jar" } -# Function to patch method with direct file path (no searching) -patch_method_in_file() { - local method="$1" - local ret_val="$2" - local file="$3" - - # Check if file exists - if [ ! -f "$file" ]; then - echo "⚠ File not found: $(basename "$file")" - return - fi - - local start - start=$(grep -n "^[[:space:]]*\.method.* $method" "$file" | cut -d: -f1 | head -n1) - [ -z "$start" ] && { - echo "⚠ Method $method not found in $(basename "$file")" - return - } - - local total_lines end=0 i="$start" - total_lines=$(wc -l <"$file") - while [ "$i" -le "$total_lines" ]; do - line=$(sed -n "${i}p" "$file") - [[ "$line" == *".end method"* ]] && { - end="$i" - break - } - i=$((i + 1)) - done - - [ "$end" -eq 0 ] && { - echo "⚠ End not found for $method" - return - } - - local method_head - method_head=$(sed -n "${start}p" "$file") - method_head_escaped=$(printf "%s\n" "$method_head" | sed 's/\\/\\\\/g') - - sed -i "${start},${end}c\\ -$method_head_escaped\\ - .registers 8\\ - const/4 v0, 0x$ret_val\\ - return v0\\ -.end method" "$file" - - echo "✓ Patched $method to return $ret_val in $(basename "$file")" -} - -# Function to add static return patch (legacy - searches for file) -add_static_return_patch() { - local method="$1" - local ret_val="$2" - local decompile_dir="$3" - local file - - # Simple working approach from old script - file=$(find "$decompile_dir" -type f -name "*.smali" -print0 | xargs -0 grep -l ".method.* $method" 2>/dev/null | head -n 1) - - [ -z "$file" ] && return - - # Call the new function with found file - patch_method_in_file "$method" "$ret_val" "$file" -} +# Note: patching functions are sourced from helper.sh -> core/patching.sh -# Function to patch return-void method with direct file path -patch_return_void_in_file() { - local method="$1" - local file="$2" - - # Check if file exists - if [ ! -f "$file" ]; then - echo "⚠ File not found: $(basename "$file")" - return - fi - - local start - start=$(grep -n "^[[:space:]]*\.method.* $method" "$file" | cut -d: -f1 | head -n1) - [ -z "$start" ] && { - echo "⚠ Method $method not found in $(basename "$file")" - return - } - - local total_lines end=0 i="$start" - total_lines=$(wc -l <"$file") - while [ "$i" -le "$total_lines" ]; do - line=$(sed -n "${i}p" "$file") - [[ "$line" == *".end method"* ]] && { - end="$i" - break - } - i=$((i + 1)) - done - - [ "$end" -eq 0 ] && { - echo "⚠ Method $method end not found" - return - } - - local method_head - method_head=$(sed -n "${start}p" "$file") - method_head_escaped=$(printf "%s\n" "$method_head" | sed 's/\\/\\\\/g') - - sed -i "${start},${end}c\\ -$method_head_escaped\\ - .registers 8\\ - return-void\\ -.end method" "$file" - - echo "✓ Patched $method → return-void in $(basename "$file")" -} - -# Function to patch return-void method (legacy - searches for file) -patch_return_void_method() { - local method="$1" - local decompile_dir="$2" - local file - - # Simple working approach from old script - file=$(find "$decompile_dir" -type f -name "*.smali" -print0 | xargs -0 grep -l ".method.* $method" 2>/dev/null | head -n 1) - [ -z "$file" ] && { - echo "Method $method not found" - return - } - - # Call the new function with found file - patch_return_void_in_file "$method" "$file" -} # ============================================ # Feature-specific patch functions for framework.jar diff --git a/scripts/patcher_a14.sh b/scripts/patcher_a14.sh index 4abd2ce..025c911 100644 --- a/scripts/patcher_a14.sh +++ b/scripts/patcher_a14.sh @@ -95,134 +95,8 @@ recompile_jar() { echo "Created patched JAR: $patched_jar" } -# Function to patch method with direct file path (no searching) -patch_method_in_file() { - local method="$1" - local ret_val="$2" - local file="$3" - - # Check if file exists - if [ ! -f "$file" ]; then - echo "⚠ File not found: $(basename "$file")" - return - fi - - local start - start=$(grep -n "^[[:space:]]*\.method.* $method" "$file" | cut -d: -f1 | head -n1) - [ -z "$start" ] && { - echo "⚠ Method $method not found in $(basename "$file")" - return - } - - local total_lines end=0 i="$start" - total_lines=$(wc -l <"$file") - while [ "$i" -le "$total_lines" ]; do - line=$(sed -n "${i}p" "$file") - [[ "$line" == *".end method"* ]] && { - end="$i" - break - } - i=$((i + 1)) - done - - [ "$end" -eq 0 ] && { - echo "⚠ End not found for $method" - return - } - - local method_head - method_head=$(sed -n "${start}p" "$file") - method_head_escaped=$(printf "%s\n" "$method_head" | sed 's/\\/\\\\/g') - - sed -i "${start},${end}c\\ -$method_head_escaped\\ - .registers 8\\ - const/4 v0, 0x$ret_val\\ - return v0\\ -.end method" "$file" - - echo "✓ Patched $method to return $ret_val in $(basename "$file")" -} - -# Function to add static return patch (legacy - searches for file) -add_static_return_patch() { - local method="$1" - local ret_val="$2" - local decompile_dir="$3" - local file - - # Simple working approach from old script - file=$(find "$decompile_dir" -type f -name "*.smali" -print0 | xargs -0 grep -l ".method.* $method" 2>/dev/null | head -n 1) - - [ -z "$file" ] && return - - # Call the new function with found file - patch_method_in_file "$method" "$ret_val" "$file" -} +# Note: patching functions are sourced from helper.sh -> core/patching.sh -# Function to patch return-void method with direct file path -patch_return_void_in_file() { - local method="$1" - local file="$2" - - # Check if file exists - if [ ! -f "$file" ]; then - echo "⚠ File not found: $(basename "$file")" - return - fi - - local start - start=$(grep -n "^[[:space:]]*\.method.* $method" "$file" | cut -d: -f1 | head -n1) - [ -z "$start" ] && { - echo "⚠ Method $method not found in $(basename "$file")" - return - } - - local total_lines end=0 i="$start" - total_lines=$(wc -l <"$file") - while [ "$i" -le "$total_lines" ]; do - line=$(sed -n "${i}p" "$file") - [[ "$line" == *".end method"* ]] && { - end="$i" - break - } - i=$((i + 1)) - done - - [ "$end" -eq 0 ] && { - echo "⚠ Method $method end not found" - return - } - - local method_head - method_head=$(sed -n "${start}p" "$file") - method_head_escaped=$(printf "%s\n" "$method_head" | sed 's/\\/\\\\/g') - - sed -i "${start},${end}c\\ -$method_head_escaped\\ - .registers 8\\ - return-void\\ -.end method" "$file" - - echo "✓ Patched $method → return-void in $(basename "$file")" -} - -# Function to patch return-void method (legacy - searches for file) -patch_return_void_method() { - local method="$1" - local decompile_dir="$2" - local file - - # Simple working approach from old script - file=$(find "$decompile_dir" -type f -name "*.smali" -print0 | xargs -0 grep -l ".method.* $method" 2>/dev/null | head -n 1) - [ -z "$file" ] && { - echo "Method $method not found" - return - } - - # Call the new function with found file - patch_return_void_in_file "$method" "$file" -} # ============================================ # Feature-specific patch functions for framework.jar From 6088617a735b400c394e4ff786ec22a9b6336799 Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 12:13:45 +0530 Subject: [PATCH 4/5] chore(scripts): update file permissions and cleanup --- scripts/core/apk_ops.sh | 0 scripts/core/kaorios_patches.sh | 0 scripts/core/logging.sh | 0 scripts/core/module.sh | 0 scripts/core/tools.sh | 0 scripts/helper.sh | 0 scripts/patcher_a16.sh | 0 services/README.md | 262 -------------------------------- 8 files changed, 262 deletions(-) mode change 100644 => 100755 scripts/core/apk_ops.sh mode change 100644 => 100755 scripts/core/kaorios_patches.sh mode change 100644 => 100755 scripts/core/logging.sh mode change 100644 => 100755 scripts/core/module.sh mode change 100644 => 100755 scripts/core/tools.sh mode change 100644 => 100755 scripts/helper.sh mode change 100644 => 100755 scripts/patcher_a16.sh delete mode 100644 services/README.md diff --git a/scripts/core/apk_ops.sh b/scripts/core/apk_ops.sh old mode 100644 new mode 100755 diff --git a/scripts/core/kaorios_patches.sh b/scripts/core/kaorios_patches.sh old mode 100644 new mode 100755 diff --git a/scripts/core/logging.sh b/scripts/core/logging.sh old mode 100644 new mode 100755 diff --git a/scripts/core/module.sh b/scripts/core/module.sh old mode 100644 new mode 100755 diff --git a/scripts/core/tools.sh b/scripts/core/tools.sh old mode 100644 new mode 100755 diff --git a/scripts/helper.sh b/scripts/helper.sh old mode 100644 new mode 100755 diff --git a/scripts/patcher_a16.sh b/scripts/patcher_a16.sh old mode 100644 new mode 100755 diff --git a/services/README.md b/services/README.md deleted file mode 100644 index be64402..0000000 --- a/services/README.md +++ /dev/null @@ -1,262 +0,0 @@ -# Framework Patcher Services - -This directory contains all the microservices for the Framework Patcher application. - -## Directory Structure - -``` -services/ -├── bot/ # Telegram Bot Service -│ ├── Framework/ # Modular bot framework -│ │ ├── __init__.py # Framework initialization -│ │ ├── __main__.py # Main entry point -│ │ ├── helpers/ # Helper modules -│ │ │ ├── provider.py # Device data provider -│ │ │ ├── shell.py # Shell command utilities -│ │ │ ├── workflows.py # GitHub workflow management -│ │ │ ├── pd_utils.py # Pixeldrain utilities -│ │ │ └── ... # Other helpers -│ │ └── plugins/ # Bot plugins -│ │ ├── user/ # User commands (start, patch, device, etc.) -│ │ └── dev/ # Developer commands (deploy, update, status, etc.) -│ ├── config.py # Configuration management -│ ├── requirements.txt # Python dependencies -│ └── logs/ # Bot logs -│ -└── web/ # Web Frontend & API - ├── index.html # Main web interface - ├── script.js # Frontend JavaScript - ├── styles.css # Styling - ├── server.py # FastAPI backend (optional) - └── logs/ # API logs -``` - -## Services Overview - -### 1. Telegram Bot (`services/bot/`) -- **Purpose**: Interactive Telegram bot for framework patching -- **Runtime**: Pterodactyl container -- **Port**: N/A (Telegram API) -- **Features**: - - Device codename validation with retry logic - - MIUI ROM version selection - - Auto-detection of Android version and API level - - GitHub workflow triggering - - File upload handling - -### 2. Web Frontend (`services/web/`) -- **Purpose**: Web interface for framework patching -- **Runtime**: Vercel (static + API routes) -- **Port**: 3000 (dev), 80/443 (production) -- **Features**: - - Modern responsive UI - - Device and version selection - - Auto-detection of Android version - - Feature toggle based on Android version - - GitHub workflow integration - -### 3. FastAPI Backend (`services/web/server.py`) -- **Purpose**: API endpoints for device data -- **Runtime**: Pterodactyl container (optional, can run standalone) -- **Port**: 8000 -- **Endpoints**: - - `GET /` - API information - - `GET /devices` - List all devices - - `GET /devices/{codename}/software` - Get device software versions - - `GET /codenames` - Get all codenames - -## Deployment - -### Deploy to Pterodactyl (Bot + API) - -Run the unified deployment script: - -```bash -./deploy.sh -``` - -This will: -1. Stop existing services -2. Backup current sessions -3. Update from Git (if applicable) -4. Install/update dependencies -5. Start both Bot and API services -6. Show service status - -### Deploy Web to Vercel - -1. **Prerequisites**: - - Vercel account - - Vercel CLI installed (`npm i -g vercel`) - -2. **Deploy**: - ```bash - vercel --prod - ``` - -3. **Environment Variables** (set in Vercel dashboard): - - None required for static frontend - - API calls go to your Pterodactyl-hosted FastAPI instance - -### Manual Service Control - -**Start Bot:** -```bash -cd services/bot -nohup python -m Framework > bot.log 2>&1 & -echo $! > bot.pid -``` - -**Start API:** -```bash -cd services/web -nohup python -m uvicorn server:app --host 0.0.0.0 --port 8000 > api.log 2>&1 & -echo $! > api.pid -``` - -**Stop Services:** -```bash -pkill -f "python -m Framework" -pkill -f "uvicorn" -``` - -**View Logs:** -```bash -# Bot logs -tail -f services/bot/bot.log - -# API logs -tail -f services/web/api.log -``` - -## Environment Configuration - -### Bot Environment Variables (`.env` in `services/bot/`) - -```env -BOT_TOKEN=your_telegram_bot_token -API_ID=your_telegram_api_id -API_HASH=your_telegram_api_hash -PIXELDRAIN_API_KEY=your_pixeldrain_api_key -GITHUB_TOKEN=your_github_token -GITHUB_OWNER=your_github_username -GITHUB_REPO=your_repo_name -GITHUB_WORKFLOW_ID=android15.yml -GITHUB_WORKFLOW_ID_A15=android15.yml -GITHUB_WORKFLOW_ID_A16=android16.yml -OWNER_ID=your_telegram_user_id -``` - -### API Configuration (`services/web/server.py`) - -The API fetches data from public Xiaomi firmware repositories, no configuration needed. - -## Development - -### Local Development - Bot - -```bash -cd services/bot -python -m Framework -``` - -### Local Development - Web + API - -```bash -# Terminal 1 - Start API -cd services/web -python -m uvicorn server:app --reload --port 8000 - -# Terminal 2 - Serve static files (optional) -python -m http.server 3000 -``` - -Or use Vercel dev: -```bash -vercel dev -``` - -## Monitoring - -### Check Service Status - -```bash -# Check if services are running -ps aux | grep -E "Framework|uvicorn" - -# Check PIDs -cat services/bot/bot.pid -cat services/web/api.pid - -# Check logs -tail -n 50 services/bot/bot.log -tail -n 50 services/web/api.log -``` - -### Bot Commands (Telegram) - -- `/start` - Start the bot -- `/start_patch` - Begin patching process -- `/cancel` - Cancel current operation -- `/update` - Update bot to latest version -- `/status` - Show bot status (owner only) -- `/restart` - Restart bot (owner only) - -## Troubleshooting - -### Bot Not Starting - -1. Check logs: `cat services/bot/bot.log` -2. Verify environment variables are set -3. Check Python dependencies: `pip install -r services/bot/requirements.txt` -4. Verify Telegram bot token is valid - -### API Not Responding - -1. Check if port 8000 is available: `lsof -i :8000` -2. Check logs: `cat services/web/api.log` -3. Verify dependencies: `pip install fastapi uvicorn httpx pyyaml` -4. Test API directly: `curl http://localhost:8000/` - -### Device Data Not Loading - -The bot and web interface fetch device data from: -- https://github.com/XiaomiFirmwareUpdater/xiaomi_devices -- https://github.com/xiaomifirmwareupdater/xiaomifirmwareupdater.github.io - -If data fails to load, check internet connectivity and that these repositories are accessible. - -## Architecture - -``` -┌─────────────────┐ -│ Vercel CDN │ -│ (Web Frontend) │ -└────────┬────────┘ - │ - │ HTTP/HTTPS - │ - ▼ -┌─────────────────────────────────────┐ -│ Pterodactyl Container │ -│ │ -│ ┌──────────────┐ ┌─────────────┐ │ -│ │ Telegram Bot │ │ FastAPI │ │ -│ │ (Port N/A) │ │ (Port 8000) │ │ -│ └──────┬───────┘ └──────┬──────┘ │ -│ │ │ │ -│ │ Shared Provider │ │ -│ └──────────────────┘ │ -└─────────────────────────────────────┘ - │ - │ GitHub API - ▼ -┌─────────────────┐ -│ GitHub Actions │ -│ (Workflows) │ -└─────────────────┘ -``` - -## License - -MIT License - See LICENSE file for details From ad7e78fae925ff263aa2a46065ce342a0a78f3c8 Mon Sep 17 00:00:00 2001 From: Jefino9488 Date: Sun, 26 Apr 2026 12:25:31 +0530 Subject: [PATCH 5/5] ci: add completion job for Feature Test Suite --- .github/workflows/feature-test-suite.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/feature-test-suite.yml b/.github/workflows/feature-test-suite.yml index 895e60b..c7bace9 100644 --- a/.github/workflows/feature-test-suite.yml +++ b/.github/workflows/feature-test-suite.yml @@ -290,4 +290,18 @@ jobs: if-no-files-found: warn path: | test-results/android${{ matrix.android_version }}/**/Framework-Patcher-android${{ matrix.android_version }}-*.zip - retention-days: 7 \ No newline at end of file + retention-days: 7 + + # Completion job to provide a static status check name for branch protection rules + check: + name: Feature Test Suite + needs: feature-tests + runs-on: ubuntu-latest + if: always() + steps: + - name: All tests passed + if: ${{ !(contains(needs.feature-tests.result, 'failure')) && !(contains(needs.feature-tests.result, 'cancelled')) }} + run: exit 0 + - name: Tests failed + if: ${{ contains(needs.feature-tests.result, 'failure') || contains(needs.feature-tests.result, 'cancelled') }} + run: exit 1 \ No newline at end of file