Compare commits

...
58 Commits
Author SHA1 Message Date
nezumi 7d5e85fc3e sync the author code 2026-07-21 11:01:29 +07:00
nezumi a14e4f9c7d fix: remove download archive url instagram 2026-05-15 11:50:27 +07:00
nezumi d7a7688aa8 fix: resolve the issues 2026-05-15 11:08:20 +07:00
nezumi c48c4abc17 feat: update the message content 2026-04-05 21:50:42 +07:00
nezumi 10f7aaf56f fix: resolve the apk build 2026-04-05 21:35:09 +07:00
Nezumi-2711 5785b1594a fix: apk download 2026-03-17 10:34:16 +07:00
Nezumi-2711 03625a35d5 fix: apk download 2026-03-17 10:05:39 +07:00
Nezumi-2711 bc51731aeb fix: apk download 2026-03-17 10:02:30 +07:00
Nezumi-2711 f0b44a12a1 fix: apk download 2026-03-17 09:55:23 +07:00
Nezumi-2711 ffa6e7a357 fix: download apk 2026-03-16 18:38:24 +07:00
Nezumi-2711 e8297c8d9a fix: download apk 2026-03-16 18:30:57 +07:00
Nezumi-2711 bb1398a32f fix: download apk 2026-03-16 18:14:38 +07:00
Nezumi-2711 34d34bc878 fix: download apk 2026-03-16 18:00:53 +07:00
nezumi d24f8939d0 fix: download apk issues 2026-02-24 17:04:12 +07:00
nezumi 3becfad4f7 fix: resolve the utils logic 2026-01-17 13:03:35 +07:00
nezumi 0e85707946 fix: resolve the utils logic 2026-01-17 12:58:05 +07:00
nezumi 117a2fde1b Update email content: add changelog, separate APKs/Modules, use Vietnam timezone 2026-01-09 22:27:26 +07:00
nezumi 8d9c8d40aa Add email notification feature using Resend API 2026-01-09 22:10:54 +07:00
nezumi bbde99482c feat: replace rvx patch to mophe patch 2026-01-04 21:48:54 +07:00
nezumi 9a7d8890aa Update build.sh 2025-05-18 10:16:54 +07:00
nezumi 57d950f57f Update build.sh 2025-05-18 10:06:28 +07:00
nezumi e0a5116d13 Update config.toml 2025-05-18 10:06:05 +07:00
nezumi 6e4565bc1b Update build.sh 2025-05-15 00:11:34 +07:00
nezumi f6d783c176 fix: ignore skipped content 2025-05-02 10:19:13 +07:00
nezumi 2da4a7c7cd update spotify config 2025-04-07 19:25:50 +07:00
nezumi 11af439fd5 add spotify patch 2025-04-07 19:16:28 +07:00
nezumi 1adcc80512 update github action 2025-04-03 22:54:01 +07:00
nezumi 596241c5d7 update github action 2025-04-03 22:51:51 +07:00
nezumi 26540719e9 update config 2025-04-03 22:49:57 +07:00
Loi Phan fbf816533d Update build.yml 2025-02-03 16:47:06 +07:00
Loi Phan d6582d2d63 Update ci.yml 2025-01-30 11:17:50 +07:00
Loi Phan 1a2af75601 Update config.toml 2025-01-30 11:15:35 +07:00
Loi Phan 6b33d5841d Update config.toml 2025-01-30 11:09:49 +07:00
Loi Phan 9f6f043d9a Update config.toml 2025-01-30 10:35:47 +07:00
Loi Phan 88ea74d38f Update ci.yml 2025-01-30 10:20:11 +07:00
Loi Phan ea7dd1d777 Update config.toml 2025-01-30 10:18:56 +07:00
Loi Phan 39e551c73c Update ci.yml 2025-01-30 09:59:04 +07:00
Loi Phan b5aac3781a Update ci.yml 2025-01-30 09:58:26 +07:00
Loi Phan 9ff2c72375 Update ci.yml 2025-01-30 09:57:34 +07:00
Loi Phan e65dfdaa1b Update config.toml 2025-01-30 09:57:20 +07:00
Loi Phan b2312718f9 Update config.toml 2025-01-30 09:53:07 +07:00
Loi Phan f1e8080202 Update config.toml 2025-01-30 09:51:19 +07:00
Loi Phan f428ad0cfe Update ci.yml 2025-01-30 09:50:21 +07:00
Loi Phan d28118c98c Update ci.yml 2025-01-30 09:42:54 +07:00
Loi Phan edfe08657a Update ci.yml 2025-01-30 09:42:09 +07:00
Loi Phan 03352030a1 Update README.md 2025-01-30 09:36:01 +07:00
Loi Phan c57014a391 update config 2025-01-30 09:33:24 +07:00
Loi Phan 1167a7c636 Update config.toml 2025-01-30 09:27:20 +07:00
Loi Phan fb7222a28f Update config.toml 2025-01-30 09:19:27 +07:00
nezumi 8e8c8634ef update config.toml 2025-01-22 22:00:09 +07:00
nezumi 7deb883720 update config 2025-01-22 20:25:45 +07:00
nezumi be1c20bb87 update config 2025-01-22 20:03:31 +07:00
nezumi 88a00ca413 update config 2025-01-22 19:41:27 +07:00
nezumi 788b36f083 update config 2025-01-22 19:24:00 +07:00
nezumi ae43197aa0 update config 2025-01-22 18:59:05 +07:00
nezumi c2fe93675e update config 2025-01-22 18:17:08 +07:00
nezumi aee01f1ca5 update config 2025-01-22 17:55:20 +07:00
nezumi 679631315e update config 2025-01-22 17:35:52 +07:00
28 changed files with 1208 additions and 565 deletions
+242 -25
View File
@@ -14,13 +14,13 @@ jobs:
permissions: write-all permissions: write-all
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/setup-java@v4 - uses: actions/setup-java@v5
with: with:
distribution: "zulu" distribution: "zulu"
java-version: "17" java-version: "21"
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
@@ -59,19 +59,21 @@ jobs:
cat build.md >> "$GITHUB_OUTPUT" cat build.md >> "$GITHUB_OUTPUT"
echo "${DELIM}" >> "$GITHUB_OUTPUT" echo "${DELIM}" >> "$GITHUB_OUTPUT"
cp -f build.md build.tmp cp -f build.md build.tmp
- name: Upload release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.next_ver_code.outputs.NEXT_VER_CODE }}
BODY: ${{ steps.get_output.outputs.BUILD_LOG }}
run: |
if gh release view "$TAG" >/dev/null 2>&1; then
gh release edit "$TAG" --title "Release" --notes "$BODY"
gh release upload "$TAG" ./build/* --clobber
else
gh release create "$TAG" ./build/* --title "Release" --notes "$BODY"
fi
- name: Upload modules to release - name: Update modules changelog and update json
uses: svenstaro/upload-release-action@v2
with:
body: ${{ steps.get_output.outputs.BUILD_LOG }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./build/*
release_name: ReVanced
tag: ${{ steps.next_ver_code.outputs.NEXT_VER_CODE }}
file_glob: true
overwrite: true
- name: Update changelog and Magisk update json
id: update_config id: update_config
run: | run: |
git checkout -f update || git switch --discard-changes --orphan update git checkout -f update || git switch --discard-changes --orphan update
@@ -86,8 +88,8 @@ jobs:
} }
cd build || { echo "build folder not found"; exit 1; } cd build || { echo "build folder not found"; exit 1; }
for OUTPUT in *magisk*.zip; do for OUTPUT in *module*.zip; do
[ "$OUTPUT" = "*magisk*.zip" ] && continue [ "$OUTPUT" = "*module*.zip" ] && continue
ZIP_S=$(unzip -p "$OUTPUT" module.prop) ZIP_S=$(unzip -p "$OUTPUT" module.prop)
if ! UPDATE_JSON=$(echo "$ZIP_S" | grep updateJson); then continue; fi if ! UPDATE_JSON=$(echo "$ZIP_S" | grep updateJson); then continue; fi
UPDATE_JSON="${UPDATE_JSON##*/}" UPDATE_JSON="${UPDATE_JSON##*/}"
@@ -100,12 +102,19 @@ jobs:
find . -name "*-update.json" | grep . || : >dummy-update.json find . -name "*-update.json" | grep . || : >dummy-update.json
- uses: stefanzweifel/git-auto-commit-action@v5 - name: Commit module json changes
with: run: |
branch: update git config user.name "github-actions[bot]"
skip_checkout: true git config user.email "github-actions[bot]@users.noreply.github.com"
file_pattern: build.md *-update.json
commit_message: Bump version ${{ steps.next_ver_code.outputs.NEXT_VER_CODE }} git add build.md *-update.json
if ! git diff --cached --quiet; then
git commit -m "Bump version ${{ steps.next_ver_code.outputs.NEXT_VER_CODE }}"
git push origin HEAD:update
else
echo "no changes!"
fi
- name: Report to Telegram - name: Report to Telegram
env: env:
@@ -114,7 +123,7 @@ jobs:
run: | run: |
cd build || { echo "build folder not found"; exit 1; } cd build || { echo "build folder not found"; exit 1; }
TG_CHAT="-1002417137882" TG_CHAT="@rvc_magisk"
NL=$'\n' NL=$'\n'
APKS="" APKS=""
MODULES="" MODULES=""
@@ -147,9 +156,9 @@ jobs:
curl -X POST --data-urlencode "parse_mode=Markdown" --data-urlencode "disable_web_page_preview=true" --data-urlencode "text=${MSG}" --data-urlencode "chat_id=${TG_CHAT}" "$POST" curl -X POST --data-urlencode "parse_mode=Markdown" --data-urlencode "disable_web_page_preview=true" --data-urlencode "text=${MSG}" --data-urlencode "chat_id=${TG_CHAT}" "$POST"
- name: Report to Discord - name: Report to Discord
if: env.TG_TOKEN != null
env: env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
if: env.DISCORD_WEBHOOK_URL != null
run: | run: |
cd build || { echo "build folder not found"; exit 1; } cd build || { echo "build folder not found"; exit 1; }
@@ -174,9 +183,14 @@ jobs:
${BODY} ${BODY}
**Download Links:** **Download Links:**
"
MODULES_MSG="
**Modules:** **Modules:**
${MODULES} ${MODULES}
"
APKS_MSG="
**APKs:** **APKs:**
${APKS} ${APKS}
" "
@@ -184,3 +198,206 @@ jobs:
curl -X POST -H "Content-Type: application/json" \ curl -X POST -H "Content-Type: application/json" \
-d "$(jq -n --arg content "$MSG" '{content: $content}')" \ -d "$(jq -n --arg content "$MSG" '{content: $content}')" \
"$DISCORD_WEBHOOK_URL" "$DISCORD_WEBHOOK_URL"
# curl -X POST -H "Content-Type: application/json" \
# -d "$(jq -n --arg content "$MODULES_MSG" '{content: $content}')" \
# "$DISCORD_WEBHOOK_URL"
curl -X POST -H "Content-Type: application/json" \
-d "$(jq -n --arg content "$APKS_MSG" '{content: $content}')" \
"$DISCORD_WEBHOOK_URL"
- name: Report to Noob Discord
env:
DISCORD_WEBHOOK_NOOB_URL: ${{ secrets.DISCORD_WEBHOOK_NOOB_URL }}
if: env.DISCORD_WEBHOOK_NOOB_URL != null
run: |
cd build || { echo "build folder not found"; exit 1; }
NL=$'\n'
APKS=""
MODULES=""
for OUTPUT in *; do
DL_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/releases/download/${{ steps.next_ver_code.outputs.NEXT_VER_CODE }}/${OUTPUT}"
if [[ $OUTPUT = *.apk ]]; then
APKS+="${NL}- [${OUTPUT}](${DL_URL})"
elif [[ $OUTPUT = *.zip ]]; then
MODULES+="${NL}- [${OUTPUT}](${DL_URL})"
fi
done
MODULES=${MODULES#"$NL"}
APKS=${APKS#"$NL"}
BODY="$(sed 's/^\* \*\*/- \*\*/g; s/^\* `/- \*\*/g; s/`/\*/g; s/^\* /\-/g; s/\*\*/\*/g; s/###//g; s/^- /- /g; /^==/d;' ../build.md)"
MSG="**New build is ready!**
${BODY}
**Download Links:**
"
MODULES_MSG="
**Modules:**
${MODULES}
"
APKS_MSG="
**APKs:**
${APKS}
"
curl -X POST -H "Content-Type: application/json" \
-d "$(jq -n --arg content "$MSG" '{content: $content}')" \
"$DISCORD_WEBHOOK_NOOB_URL"
# curl -X POST -H "Content-Type: application/json" \
# -d "$(jq -n --arg content "$MODULES_MSG" '{content: $content}')" \
# "$DISCORD_WEBHOOK_NOOB_URL"
curl -X POST -H "Content-Type: application/json" \
-d "$(jq -n --arg content "$APKS_MSG" '{content: $content}')" \
"$DISCORD_WEBHOOK_NOOB_URL"
- name: Send Email Notification (Resend)
env:
RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
MAIL_TO: ${{ secrets.MAIL_TO }}
MAIL_CC: ${{ secrets.MAIL_CC }}
MAIL_BCC: ${{ secrets.MAIL_BCC }}
MAIL_FROM: ${{ secrets.MAIL_FROM }}
if: env.RESEND_API_KEY != null && env.MAIL_TO != null
run: |
VERSION="${{ steps.next_ver_code.outputs.NEXT_VER_CODE }}"
RELEASE_URL="${{ github.server_url }}/${{ github.repository }}/releases/tag/${VERSION}"
REPO="${{ github.repository }}"
# Set default FROM address if not provided
FROM_ADDRESS="${MAIL_FROM:-ReVanced Build Bot <onboarding@resend.dev>}"
# Build download links from build folder (separate APKs and Modules)
cd build || { echo "build folder not found"; exit 1; }
APK_LINKS=""
MODULE_LINKS=""
for OUTPUT in *; do
DL_URL="${{ github.server_url }}/${{ github.repository }}/releases/download/${VERSION}/${OUTPUT}"
if [[ $OUTPUT = *.apk ]]; then
APK_LINKS+="<li style=\"margin: 8px 0;\">📦 <a href=\"${DL_URL}\" style=\"color: #667eea; text-decoration: none;\">${OUTPUT}</a></li>"
elif [[ $OUTPUT = *.zip ]]; then
MODULE_LINKS+="<li style=\"margin: 8px 0;\">📁 <a href=\"${DL_URL}\" style=\"color: #667eea; text-decoration: none;\">${OUTPUT}</a></li>"
fi
done
cd ..
# Get current time in Vietnam timezone (UTC+7)
BUILD_TIME=$(TZ='Asia/Ho_Chi_Minh' date '+%Y-%m-%d %H:%M:%S (UTC+7)')
# Get changelog from build.md and convert to HTML
if [ -f "build.md" ]; then
# Convert markdown to simple HTML
CHANGELOG_HTML=$(sed 's/^### \(.*\)/<h3 style="color: #667eea; font-size: 16px; margin: 15px 0 8px 0;">\1<\/h3>/g;
s/^\* \*\*\(.*\)\*\*/<li style="margin: 5px 0;"><strong>\1<\/strong><\/li>/g;
s/^\* \(.*\)/<li style="margin: 5px 0;">\1<\/li>/g;
s/^- \(.*\)/<li style="margin: 5px 0;">\1<\/li>/g;
s/`\([^`]*\)`/<code style="background: #e9ecef; padding: 2px 6px; border-radius: 3px; font-size: 13px;">\1<\/code>/g;
/^==/d;
/^$/d' build.md | tr '\n' ' ')
else
CHANGELOG_HTML="<p>No changelog available.</p>"
fi
# Create HTML email body (similar structure to Telegram)
HTML_BODY=$(cat <<EOF
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 0;">
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center;">
<h1 style="margin: 0;">🎉 New ReVanced Build!</h1>
<p style="margin: 10px 0 0 0; font-size: 18px;">Version: v${VERSION}</p>
<p style="margin: 5px 0 0 0; font-size: 14px; opacity: 0.9;">🕐 ${BUILD_TIME}</p>
</div>
<div style="padding: 25px; background: #f9f9f9;">
<!-- Changelog Section -->
<div style="margin-bottom: 25px; background: white; padding: 20px; border-radius: 8px; border-left: 4px solid #667eea;">
<h2 style="color: #667eea; font-size: 18px; margin: 0 0 15px 0;">📋 Changelog</h2>
<div style="font-size: 14px;">
${CHANGELOG_HTML}
</div>
</div>
<!-- Download Links Section -->
<div style="margin-bottom: 25px; background: white; padding: 20px; border-radius: 8px;">
<h2 style="color: #667eea; font-size: 18px; margin: 0 0 15px 0;"> Download Links</h2>
<!-- Modules -->
$(if [ -n "$MODULE_LINKS" ]; then echo "
<div style=\"margin-bottom: 15px;\">
<h3 style=\"color: #555; font-size: 15px; margin: 0 0 10px 0;\"> Modules:</h3>
<ul style=\"list-style: none; padding: 0; margin: 0;\">
${MODULE_LINKS}
</ul>
</div>
"; fi)
<!-- APKs -->
$(if [ -n "$APK_LINKS" ]; then echo "
<div>
<h3 style=\"color: #555; font-size: 15px; margin: 0 0 10px 0;\">📱 APKs:</h3>
<ul style=\"list-style: none; padding: 0; margin: 0;\">
${APK_LINKS}
</ul>
</div>
"; fi)
</div>
<!-- GitHub Button -->
<div style="text-align: center;">
<a href="${RELEASE_URL}" style="display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; text-decoration: none; border-radius: 25px; font-weight: bold;">
View Release on GitHub
</a>
</div>
</div>
<div style="text-align: center; padding: 20px; background: #333; color: #999; font-size: 12px;">
<p style="margin: 0;">This is an automated message from ReVanced Build Bot</p>
<p style="margin: 5px 0 0 0;">Repository: ${REPO}</p>
</div>
</body>
</html>
EOF
)
# Build JSON payload with TO, CC and BCC recipients
# Resend allows up to 50 recipients per field (to, cc, bcc)
JSON_PAYLOAD=$(jq -n \
--arg from "$FROM_ADDRESS" \
--arg to "$MAIL_TO" \
--arg cc "$MAIL_CC" \
--arg bcc "$MAIL_BCC" \
--arg subject "🚀 New ReVanced Build Available - v${VERSION}" \
--arg html "$HTML_BODY" \
'{
from: $from,
to: ($to | split(",") | map(select(. != "") | gsub("^\\s+|\\s+$"; ""))),
subject: $subject,
html: $html
}
+ (if $cc != "" then {cc: ($cc | split(",") | map(select(. != "") | gsub("^\\s+|\\s+$"; "")))} else {} end)
+ (if $bcc != "" then {bcc: ($bcc | split(",") | map(select(. != "") | gsub("^\\s+|\\s+$"; "")))} else {} end)'
)
echo "📧 Sending email notification..."
# Send email via Resend API
RESPONSE=$(curl -s -X POST "https://api.resend.com/emails" \
-H "Authorization: Bearer ${RESEND_API_KEY}" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
echo "Response: $RESPONSE"
echo "✅ Email sent successfully!"
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
+127
View File
@@ -0,0 +1,127 @@
name: Email Notification Test
on:
workflow_dispatch:
inputs:
recipient_email:
description: 'Email address to send test to (leave empty to use MAIL_TO secret)'
required: false
type: string
jobs:
send-test-email:
runs-on: ubuntu-latest
steps:
- name: Send Test Email (Resend)
env:
RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
MAIL_TO: ${{ inputs.recipient_email || secrets.MAIL_TO }}
MAIL_CC: ${{ secrets.MAIL_CC }}
MAIL_BCC: ${{ secrets.MAIL_BCC }}
MAIL_FROM: ${{ secrets.MAIL_FROM }}
run: |
if [ -z "$RESEND_API_KEY" ]; then
echo "❌ Error: RESEND_API_KEY secret is not set!"
exit 1
fi
if [ -z "$MAIL_TO" ]; then
echo "❌ Error: No email recipient specified!"
echo "Either provide recipient_email input or set MAIL_TO secret."
exit 1
fi
# Set default FROM address if not provided
FROM_ADDRESS="${MAIL_FROM:-ReVanced Build Bot <onboarding@resend.dev>}"
# Use Vietnam timezone (UTC+7)
VERSION="TEST-$(TZ='Asia/Ho_Chi_Minh' date +%Y%m%d-%H%M%S)"
SENT_TIME=$(TZ='Asia/Ho_Chi_Minh' date '+%Y-%m-%d %H:%M:%S (UTC+7)')
RELEASE_URL="${{ github.server_url }}/${{ github.repository }}/releases"
REPO="${{ github.repository }}"
# Create test HTML email body
HTML_BODY=$(cat <<EOF
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 0;">
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center;">
<h1 style="margin: 0;">🧪 Test Email</h1>
<p style="margin: 10px 0 0 0; font-size: 18px;">Version: ${VERSION}</p>
</div>
<div style="padding: 25px; background: #f9f9f9;">
<div style="margin-bottom: 25px;">
<h2 style="color: #667eea; font-size: 18px; margin: 0 0 10px 0;">✅ Email Configuration Working!</h2>
<p style="margin: 0;">If you received this email, it means your Resend configuration is working correctly!</p>
</div>
<div style="margin-bottom: 25px;">
<h2 style="color: #667eea; font-size: 18px; margin: 0 0 10px 0;">📋 Configuration Details</h2>
<ul style="list-style: none; padding: 0; margin: 0;">
<li>📧 From: ${FROM_ADDRESS}</li>
<li>📬 To: ${MAIL_TO}</li>
<li>🕐 Sent at: ${SENT_TIME}</li>
</ul>
</div>
<div style="margin-bottom: 25px; text-align: center;">
<a href="${RELEASE_URL}" style="display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; text-decoration: none; border-radius: 25px; font-weight: bold;">
View Releases
</a>
</div>
</div>
<div style="text-align: center; padding: 20px; background: #333; color: #999; font-size: 12px;">
<p style="margin: 0;">This is a TEST email from ReVanced Build Bot</p>
<p style="margin: 5px 0 0 0;">Repository: ${REPO}</p>
</div>
</body>
</html>
EOF
)
# Build JSON payload
JSON_PAYLOAD=$(jq -n \
--arg from "$FROM_ADDRESS" \
--arg to "$MAIL_TO" \
--arg cc "$MAIL_CC" \
--arg bcc "$MAIL_BCC" \
--arg subject "🧪 [TEST] ReVanced Build Email - ${VERSION}" \
--arg html "$HTML_BODY" \
'{
from: $from,
to: ($to | split(",") | map(select(. != "") | gsub("^\\s+|\\s+$"; ""))),
subject: $subject,
html: $html
}
+ (if $cc != "" then {cc: ($cc | split(",") | map(select(. != "") | gsub("^\\s+|\\s+$"; "")))} else {} end)
+ (if $bcc != "" then {bcc: ($bcc | split(",") | map(select(. != "") | gsub("^\\s+|\\s+$"; "")))} else {} end)'
)
echo "📧 Sending test email to: $MAIL_TO"
if [ -n "$MAIL_CC" ]; then echo "📋 CC: $MAIL_CC"; fi
if [ -n "$MAIL_BCC" ]; then echo "🔒 BCC: $MAIL_BCC"; fi
echo ""
# Send email via Resend API
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "https://api.resend.com/emails" \
-H "Authorization: Bearer ${RESEND_API_KEY}" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | sed '$d')
echo "Response: $BODY"
echo "HTTP Code: $HTTP_CODE"
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
echo ""
echo "✅ Test email sent successfully!"
echo "📬 Check your inbox at: $MAIL_TO"
else
echo ""
echo "❌ Failed to send email!"
echo "Please check your RESEND_API_KEY and email addresses."
exit 1
fi
+1
View File
@@ -6,3 +6,4 @@ test*
/logs /logs
build.md build.md
cmpr cmpr
*-temporary-files
+12 -6
View File
@@ -7,6 +7,9 @@ apkmirror-dlurl = "https://www.apkmirror.com/apk/inc/app"
# or uptodown-dlurl = "https://app.en.uptodown.com/android" # or uptodown-dlurl = "https://app.en.uptodown.com/android"
``` ```
> [!WARNING]
> When a patch name itself contains a single quote, double it inside the string (e.g. 'Hide ''Get Music Premium''').
## More about other options: ## More about other options:
There exists an example below with all defaults shown and all the keys explicitly set. There exists an example below with all defaults shown and all the keys explicitly set.
@@ -16,9 +19,10 @@ There exists an example below with all defaults shown and all the keys explicitl
parallel-jobs = 1 # amount of cores to use for parallel patching, if not set $(nproc) is used parallel-jobs = 1 # amount of cores to use for parallel patching, if not set $(nproc) is used
compression-level = 9 # module zip compression level compression-level = 9 # module zip compression level
remove-rv-integrations-checks = true # remove checks from the revanced integrations remove-rv-integrations-checks = true # remove checks from the revanced integrations
dpi = "nodpi anydpi 120-640dpi" # dpi packages to be searched in order. default: "nodpi anydpi"
patches-source = "revanced/revanced-patches" # where to fetch patches bundle from. default: "revanced/revanced-patches" patches-source = "revanced/revanced-patches" # where to fetch patches bundle from. default: "revanced/revanced-patches"
cli-source = "j-hc/revanced-cli" # where to fetch cli from. default: "j-hc/revanced-cli" cli-source = "ReVanced/revanced-cli" # where to fetch cli from. default: "ReVanced/revanced-cli"
# options like cli-source can also set per app # options like cli-source can also set per app
rv-brand = "ReVanced Extended" # rebrand from 'ReVanced' to something different. default: "ReVanced" rv-brand = "ReVanced Extended" # rebrand from 'ReVanced' to something different. default: "ReVanced"
@@ -48,13 +52,15 @@ excluded-patches = """\
""" """
included-patches = "'Some Patch'" # whitespace seperated list of non-default patches to include. default: "" included-patches = "'Some Patch'" # whitespace seperated list of non-default patches to include. default: ""
include-stock = true # includes stock apk in the module. default: true include-stock = "merged" # 'merged', 'split' or 'disable'. default: merged
exclusive-patches = false # exclude all patches by default. default: false exclusive-patches = false # exclude all patches by default. default: false
apkmirror-dlurl = "https://www.apkmirror.com/apk/inc/app" apkmirror-dlurl = "https://www.apkmirror.com/apk/inc/app"
uptodown-dlurl = "https://spotify.en.uptodown.com/android" uptodown-dlurl = "https://spotify.en.uptodown.com/android"
module-prop-name = "some-app-magisk" # magisk module prop name. # direct download url. the url must have point to an apk file with name format shown in this example
apkmirror-dpi = "360-480dpi" # used to select apk variant from apkmirror. default: nodpi direct-dlurl = "https://website/com.google.android.youtube-20.40.45-all.apk"
arch = "arm64-v8a" # 'arm64-v8a', 'arm-v7a', 'all', 'both'. 'both' downloads both arm64-v8a and arm-v7a. default: all
riplib = true # enables ripping x86 and x86_64 libs from apks with j-hc revanced cli. default: true
module-prop-name = "some-app-module" # module prop name.
dpi = "360-480dpi" # used to select apk variant from apkmirror. default: nodpi
arch = "arm64-v8a" # 'arm64-v8a', 'arm-v7a', 'all', 'both'. 'both' downloads both arm64-v8a and arm-v7a. default: all
``` ```
+11 -5
View File
@@ -10,10 +10,10 @@ Use [**zygisk-detach**](https://github.com/j-hc/zygisk-detach) to detach YouTube
<details><summary><big>Features</big></summary> <details><summary><big>Features</big></summary>
<ul> <ul>
<li>Support all present and future ReVanced and <a href="https://github.com/inotia00/revanced-patches">ReVanced Extended</a> apps</li> <li> Supports all present and future ReVanced apps (including projects implementing the same API)</li>
<li> Can build Magisk modules and non-root APKs</li> <li> Can build Magisk modules and non-root APKs</li>
<li> Updated daily with the latest versions of apps and patches</li> <li> Updated daily with the latest versions of apps and patches</li>
<li> Optimize APKs and modules for size</li> <li> Optimizes APKs and modules for size</li>
<li> Modules</li> <li> Modules</li>
<ul> <ul>
<li> recompile invalidated odex for faster usage</li> <li> recompile invalidated odex for faster usage</li>
@@ -23,7 +23,6 @@ Use [**zygisk-detach**](https://github.com/j-hc/zygisk-detach) to detach YouTube
<li> support Magisk and KernelSU</li> <li> support Magisk and KernelSU</li>
</ul> </ul>
</ul> </ul>
Note that the <a href="../../actions/workflows/ci.yml">CI workflow</a> is scheduled to build the modules and APKs everyday using GitHub Actions if there is a change in ReVanced patches. You may want to disable it.
</details> </details>
## To include/exclude patches or patch other apps ## To include/exclude patches or patch other apps
@@ -36,15 +35,22 @@ Note that the <a href="../../actions/workflows/ci.yml">CI workflow</a> is schedu
also see here [`CONFIG.md`](./CONFIG.md) also see here [`CONFIG.md`](./CONFIG.md)
## If you are having trouble with the classic mount method of the modules
such as,
- **"Reflash needed"** error after reboots
- **"Suspicious mount detected"** warnings from root detector apps
You can consider using [rvmm-zygisk-mount](https://github.com/j-hc/rvmm-zygisk-mount)
## Building Locally ## Building Locally
### On Termux ### On Termux
```console ```console
bash <(curl -sSf https://raw.githubusercontent.com/j-hc/revanced-magisk-module/main/build-termux.sh) bash <(curl -sSf https://raw.githubusercontent.com/j-hc/revanced-magisk-module/main/build-termux.sh)
``` ```
### On Desktop ### On Linux
```console ```console
$ git clone https://github.com/j-hc/revanced-magisk-module $ git clone https://github.com/j-hc/revanced-magisk-module --depth 1
$ cd revanced-magisk-module $ cd revanced-magisk-module
$ ./build.sh $ ./build.sh
``` ```
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -26,7 +26,7 @@ until
do sleep 1; done do sleep 1; done
if [ ! -f ~/.rvmm_"$(date '+%Y%m')" ]; then if [ ! -f ~/.rvmm_"$(date '+%Y%m')" ]; then
pr "Setting up environment..." pr "Setting up environment..."
yes "" | pkg update -y && pkg install -y git curl jq openjdk-17 zip yes "" | pkg update -y && pkg upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" && pkg install -y git curl jq openjdk-17 zip
: >~/.rvmm_"$(date '+%Y%m')" : >~/.rvmm_"$(date '+%Y%m')"
fi fi
mkdir -p /sdcard/Download/revanced-magisk-module/ mkdir -p /sdcard/Download/revanced-magisk-module/
+56 -63
View File
@@ -2,14 +2,20 @@
set -euo pipefail set -euo pipefail
shopt -s nullglob shopt -s nullglob
trap "rm -rf temp/*tmp.* temp/*/*tmp.* temp/*-temporary-files; exit 130" INT
source utils.sh
trap "abort" INT
if [ "${1-}" = "clean" ]; then if [ "${1-}" = "clean" ]; then
rm -rf temp build logs build.md rm -r "$TEMP_DIR" "$BUILD_DIR" build.md
exit 0 exit 0
fi fi
source utils.sh jq --version >/dev/null || abort "\`jq\` is not installed. install it with 'apt install jq' or equivalent"
java --version >/dev/null || abort "\`openjdk 17\` is not installed. install it with 'apt install openjdk-17-jre' or equivalent"
zip --version >/dev/null || abort "\`zip\` is not installed. install it with 'apt install zip' or equivalent"
set_prebuilts set_prebuilts
vtf() { if ! isoneof "${1}" "true" "false"; then abort "ERROR: '${1}' is not a valid option for '${2}': only true or false is allowed"; fi; } vtf() { if ! isoneof "${1}" "true" "false"; then abort "ERROR: '${1}' is not a valid option for '${2}': only true or false is allowed"; fi; }
@@ -25,7 +31,7 @@ REMOVE_RV_INTEGRATIONS_CHECKS=$(toml_get "$main_config_t" remove-rv-integrations
DEF_PATCHES_VER=$(toml_get "$main_config_t" patches-version) || DEF_PATCHES_VER="latest" DEF_PATCHES_VER=$(toml_get "$main_config_t" patches-version) || DEF_PATCHES_VER="latest"
DEF_CLI_VER=$(toml_get "$main_config_t" cli-version) || DEF_CLI_VER="latest" DEF_CLI_VER=$(toml_get "$main_config_t" cli-version) || DEF_CLI_VER="latest"
DEF_PATCHES_SRC=$(toml_get "$main_config_t" patches-source) || DEF_PATCHES_SRC="ReVanced/revanced-patches" DEF_PATCHES_SRC=$(toml_get "$main_config_t" patches-source) || DEF_PATCHES_SRC="ReVanced/revanced-patches"
DEF_CLI_SRC=$(toml_get "$main_config_t" cli-source) || DEF_CLI_SRC="j-hc/revanced-cli" DEF_CLI_SRC=$(toml_get "$main_config_t" cli-source) || DEF_CLI_SRC="ReVanced/revanced-cli"
DEF_RV_BRAND=$(toml_get "$main_config_t" rv-brand) || DEF_RV_BRAND="ReVanced" DEF_RV_BRAND=$(toml_get "$main_config_t" rv-brand) || DEF_RV_BRAND="ReVanced"
mkdir -p "$TEMP_DIR" "$BUILD_DIR" mkdir -p "$TEMP_DIR" "$BUILD_DIR"
@@ -35,21 +41,17 @@ if [ "${2-}" = "--config-update" ]; then
fi fi
: >build.md : >build.md
ENABLE_MAGISK_UPDATE=$(toml_get "$main_config_t" enable-magisk-update) || ENABLE_MAGISK_UPDATE=true ENABLE_MODULE_UPDATE=$(toml_get "$main_config_t" enable-module-update) || ENABLE_MODULE_UPDATE=true
if [ "$ENABLE_MAGISK_UPDATE" = true ] && [ -z "${GITHUB_REPOSITORY-}" ]; then if [ "$ENABLE_MODULE_UPDATE" = true ] && [ -z "${GITHUB_REPOSITORY-}" ]; then
pr "You are building locally. Magisk updates will not be enabled." pr "You are building locally. Module updates will not be enabled."
ENABLE_MAGISK_UPDATE=false ENABLE_MODULE_UPDATE=false
fi fi
if ((COMPRESSION_LEVEL > 9)) || ((COMPRESSION_LEVEL < 0)); then abort "compression-level must be within 0-9"; fi if ((COMPRESSION_LEVEL > 9)) || ((COMPRESSION_LEVEL < 0)); then abort "compression-level must be within 0-9"; fi
jq --version >/dev/null || abort "\`jq\` is not installed. install it with 'apt install jq' or equivalent" rm -rf module/bin/*/tmp.*
java --version >/dev/null || abort "\`openjdk 17\` is not installed. install it with 'apt install openjdk-17-jre' or equivalent" for file in "$TEMP_DIR"/*/changelog.md; do
zip --version >/dev/null || abort "\`zip\` is not installed. install it with 'apt install zip' or equivalent" [ -f "$file" ] && : >"$file"
done
rm -rf revanced-magisk/bin/*/tmp.*
if [ "$(echo "$TEMP_DIR"/*-rv/changelog.md)" ]; then
: >"$TEMP_DIR"/*-rv/changelog.md || :
fi
mkdir -p ${MODULE_TEMPLATE_DIR}/bin/arm64 ${MODULE_TEMPLATE_DIR}/bin/arm ${MODULE_TEMPLATE_DIR}/bin/x86 ${MODULE_TEMPLATE_DIR}/bin/x64 mkdir -p ${MODULE_TEMPLATE_DIR}/bin/arm64 ${MODULE_TEMPLATE_DIR}/bin/arm ${MODULE_TEMPLATE_DIR}/bin/x86 ${MODULE_TEMPLATE_DIR}/bin/x64
gh_dl "${MODULE_TEMPLATE_DIR}/bin/arm64/cmpr" "https://github.com/j-hc/cmpr/releases/latest/download/cmpr-arm64-v8a" gh_dl "${MODULE_TEMPLATE_DIR}/bin/arm64/cmpr" "https://github.com/j-hc/cmpr/releases/latest/download/cmpr-arm64-v8a"
@@ -57,7 +59,6 @@ gh_dl "${MODULE_TEMPLATE_DIR}/bin/arm/cmpr" "https://github.com/j-hc/cmpr/releas
gh_dl "${MODULE_TEMPLATE_DIR}/bin/x86/cmpr" "https://github.com/j-hc/cmpr/releases/latest/download/cmpr-x86" gh_dl "${MODULE_TEMPLATE_DIR}/bin/x86/cmpr" "https://github.com/j-hc/cmpr/releases/latest/download/cmpr-x86"
gh_dl "${MODULE_TEMPLATE_DIR}/bin/x64/cmpr" "https://github.com/j-hc/cmpr/releases/latest/download/cmpr-x86_64" gh_dl "${MODULE_TEMPLATE_DIR}/bin/x64/cmpr" "https://github.com/j-hc/cmpr/releases/latest/download/cmpr-x86_64"
declare -A cliriplib
idx=0 idx=0
for table_name in $(toml_get_table_names); do for table_name in $(toml_get_table_names); do
if [ -z "$table_name" ]; then continue; fi if [ -z "$table_name" ]; then continue; fi
@@ -76,22 +77,13 @@ for table_name in $(toml_get_table_names); do
cli_src=$(toml_get "$t" cli-source) || cli_src=$DEF_CLI_SRC cli_src=$(toml_get "$t" cli-source) || cli_src=$DEF_CLI_SRC
cli_ver=$(toml_get "$t" cli-version) || cli_ver=$DEF_CLI_VER cli_ver=$(toml_get "$t" cli-version) || cli_ver=$DEF_CLI_VER
if ! RVP="$(get_rv_prebuilts "$cli_src" "$cli_ver" "$patches_src" "$patches_ver")"; then if ! PREBUILTS="$(get_prebuilts "$cli_src" "$cli_ver" "$patches_src" "$patches_ver")"; then
abort "could not download rv prebuilts" epr "Could not get prebuilts"
continue
fi fi
read -r rv_cli_jar rv_patches_jar <<<"$RVP" read -r patches_jar cli_jar <<<"$PREBUILTS"
app_args[cli]=$rv_cli_jar app_args[cli]=$cli_jar
app_args[ptjar]=$rv_patches_jar app_args[ptjar]=$patches_jar
if [[ -v cliriplib[${app_args[cli]}] ]]; then app_args[riplib]=${cliriplib[${app_args[cli]}]}; else
if [[ $(java -jar "${app_args[cli]}" patch 2>&1) == *rip-lib* ]]; then
cliriplib[${app_args[cli]}]=true
app_args[riplib]=true
else
cliriplib[${app_args[cli]}]=false
app_args[riplib]=false
fi
fi
if [ "${app_args[riplib]}" = "true" ] && [ "$(toml_get "$t" riplib)" = "false" ]; then app_args[riplib]=false; fi
app_args[rv_brand]=$(toml_get "$t" rv-brand) || app_args[rv_brand]=$DEF_RV_BRAND app_args[rv_brand]=$(toml_get "$t" rv-brand) || app_args[rv_brand]=$DEF_RV_BRAND
app_args[excluded_patches]=$(toml_get "$t" excluded-patches) || app_args[excluded_patches]="" app_args[excluded_patches]=$(toml_get "$t" excluded-patches) || app_args[excluded_patches]=""
@@ -108,48 +100,44 @@ for table_name in $(toml_get_table_names); do
abort "ERROR: build-mode '${app_args[build_mode]}' is not a valid option for '${table_name}': only 'both', 'apk' or 'module' is allowed" abort "ERROR: build-mode '${app_args[build_mode]}' is not a valid option for '${table_name}': only 'both', 'apk' or 'module' is allowed"
fi fi
} || app_args[build_mode]=apk } || app_args[build_mode]=apk
app_args[uptodown_dlurl]=$(toml_get "$t" uptodown-dlurl) && { app_args[include_stock]=$(toml_get "$t" include-stock) && {
app_args[uptodown_dlurl]=${app_args[uptodown_dlurl]%/} if ! isoneof "${app_args[include_stock]}" disable merged split; then
app_args[uptodown_dlurl]=${app_args[uptodown_dlurl]%download} abort "ERROR: include-stock '${app_args[include_stock]}' is not a valid option for '${table_name}': only 'disable', 'merged' or 'split' is allowed"
app_args[uptodown_dlurl]=${app_args[uptodown_dlurl]%/} fi
app_args[dl_from]=uptodown } || app_args[include_stock]=merged
} || app_args[uptodown_dlurl]=""
app_args[apkmirror_dlurl]=$(toml_get "$t" apkmirror-dlurl) && { for dl_from in "${DL_SRCS[@]}"; do
app_args[apkmirror_dlurl]=${app_args[apkmirror_dlurl]%/} if app_args[${dl_from}_dlurl]=$(toml_get "$t" "${dl_from}-dlurl"); then
app_args[dl_from]=apkmirror app_args[${dl_from}_dlurl]=${app_args[${dl_from}_dlurl]%/}
} || app_args[apkmirror_dlurl]="" app_args[${dl_from}_dlurl]=${app_args[${dl_from}_dlurl]%download}
app_args[archive_dlurl]=$(toml_get "$t" archive-dlurl) && { app_args[${dl_from}_dlurl]=${app_args[${dl_from}_dlurl]%/}
app_args[archive_dlurl]=${app_args[archive_dlurl]%/} app_args[dl_from]=${dl_from}
app_args[dl_from]=archive else
} || app_args[archive_dlurl]="" app_args[${dl_from}_dlurl]=""
if [ -z "${app_args[dl_from]-}" ]; then abort "ERROR: no 'apkmirror_dlurl', 'uptodown_dlurl' or 'archive_dlurl' option was set for '$table_name'."; fi fi
done
if [ -z "${app_args[dl_from]-}" ]; then abort "ERROR: no 'dlurl' option was set for '$table_name'. (${DL_SRCS[*]})"; fi
app_args[arch]=$(toml_get "$t" arch) || app_args[arch]="all" app_args[arch]=$(toml_get "$t" arch) || app_args[arch]="all"
if [ "${app_args[arch]}" != "both" ] && [ "${app_args[arch]}" != "all" ] && [[ ${app_args[arch]} != "arm64-v8a"* ]] && [[ ${app_args[arch]} != "arm-v7a"* ]]; then if ! isoneof "${app_args[arch]}" "both" "all" "arm64-v8a" "arm-v7a" "x86_64" "x86"; then
abort "wrong arch '${app_args[arch]}' for '$table_name'" abort "wrong arch '${app_args[arch]}' for '$table_name'"
fi fi
app_args[include_stock]=$(toml_get "$t" include-stock) || app_args[include_stock]=true && vtf "${app_args[include_stock]}" "include-stock" app_args[pkg_name]=$(toml_get "$t" pkg-name) || app_args[pkg_name]=""
app_args[dpi]=$(toml_get "$t" apkmirror-dpi) || app_args[dpi]="nodpi" app_args[dpi]=$(toml_get "$t" dpi) || app_args[dpi]=""
table_name_f=${table_name,,} table_name_f=${table_name,,}
table_name_f=${table_name_f// /-} table_name_f=${table_name_f// /-}
app_args[module_prop_name]=$(toml_get "$t" module-prop-name) || { app_args[module_prop_name]=$(toml_get "$t" module-prop-name) || app_args[module_prop_name]="${table_name_f}-jhc"
app_args[module_prop_name]="${table_name_f}-jhc"
if [ "${app_args[arch]}" = "arm64-v8a" ]; then
app_args[module_prop_name]="${app_args[module_prop_name]}-arm64"
elif [ "${app_args[arch]}" = "arm-v7a" ]; then
app_args[module_prop_name]="${app_args[module_prop_name]}-arm"
fi
}
if [ "${app_args[arch]}" = both ]; then if [ "${app_args[arch]}" = both ]; then
app_args[table]="$table_name (arm64-v8a)" app_args[table]="$table_name (arm64-v8a)"
app_args[arch]="arm64-v8a" app_args[arch]="arm64-v8a"
app_args[module_prop_name]="${app_args[module_prop_name]}-arm64" module_prop_name_b=${app_args[module_prop_name]}
app_args[module_prop_name]="${module_prop_name_b}-arm64"
idx=$((idx + 1)) idx=$((idx + 1))
build_rv "$(declare -p app_args)" & build_rv "$(declare -p app_args)" &
app_args[table]="$table_name (arm-v7a)" app_args[table]="$table_name (arm-v7a)"
app_args[arch]="arm-v7a" app_args[arch]="arm-v7a"
app_args[module_prop_name]="${app_args[module_prop_name]}-arm" app_args[module_prop_name]="${module_prop_name_b}-arm"
if ((idx >= PARALLEL_JOBS)); then if ((idx >= PARALLEL_JOBS)); then
wait -n wait -n
idx=$((idx - 1)) idx=$((idx - 1))
@@ -157,18 +145,23 @@ for table_name in $(toml_get_table_names); do
idx=$((idx + 1)) idx=$((idx + 1))
build_rv "$(declare -p app_args)" & build_rv "$(declare -p app_args)" &
else else
if [ "${app_args[arch]}" = "arm64-v8a" ]; then
app_args[module_prop_name]="${app_args[module_prop_name]}-arm64"
elif [ "${app_args[arch]}" = "arm-v7a" ]; then
app_args[module_prop_name]="${app_args[module_prop_name]}-arm"
fi
idx=$((idx + 1)) idx=$((idx + 1))
build_rv "$(declare -p app_args)" & build_rv "$(declare -p app_args)" &
fi fi
done done
wait wait
rm -rf temp/tmp.* _clean_tmp
if [ -z "$(ls -A1 "${BUILD_DIR}")" ]; then abort "All builds failed."; fi if [ -z "$(ls -A1 "${BUILD_DIR}")" ]; then abort "All builds failed."; fi
log "\nInstall [Microg](https://github.com/ReVanced/GmsCore/releases) for non-root YouTube and YT Music APKs" log "\nInstall [Microg](https://github.com/ReVanced/GmsCore/releases) for non-root YouTube and YT Music APKs"
log "Use [zygisk-detach](https://github.com/j-hc/zygisk-detach) to detach root ReVanced YouTube and YT Music from Play Store" log "Use [zygisk-detach](https://github.com/j-hc/zygisk-detach) to detach YouTube and YT Music modules from Play Store"
log "\n[revanced-magisk-module](https://github.com/j-hc/revanced-magisk-module)\n" log "\n[revanced-magisk-module](https://github.com/j-hc/revanced-magisk-module)\n"
log "$(cat "$TEMP_DIR"/*-rv/changelog.md)" log "$(cat "$TEMP_DIR"/*/changelog.md)"
SKIPPED=$(cat "$TEMP_DIR"/skipped 2>/dev/null || :) SKIPPED=$(cat "$TEMP_DIR"/skipped 2>/dev/null || :)
if [ -n "$SKIPPED" ]; then if [ -n "$SKIPPED" ]; then
+55 -48
View File
@@ -1,4 +1,4 @@
enable-magisk-update = false # set this to false if you do not want to receive updates for the module in magisk app enable-module-update = true # set this to false if you do not want to receive updates for the module
parallel-jobs = 1 parallel-jobs = 1
# add 'enabled = false' for not patching a specific app or remove it from the config # add 'enabled = false' for not patching a specific app or remove it from the config
@@ -8,66 +8,73 @@ parallel-jobs = 1
[YouTube] [YouTube]
build-mode = "both" build-mode = "both"
excluded-patches = "'Hide timestamp'" excluded-patches = "'Custom branding'"
included-patches = ""
version = "auto"
apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube" apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube"
uptodown-dlurl = "https://youtube.en.uptodown.com/android" uptodown-dlurl = "https://youtube.en.uptodown.com/android"
# archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.youtube" archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.youtube"
[YouTube-Morphe]
app-name = "YouTube"
patches-source = "MorpheApp/morphe-patches"
cli-source = "MorpheApp/morphe-cli"
rv-brand = "Morphe"
build-mode = "both"
excluded-patches = "'Custom branding'"
apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube"
uptodown-dlurl = "https://youtube.en.uptodown.com/android"
archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.youtube"
[Music] [Music]
build-mode = "both" build-mode = "both"
arch = "both" arch = "both"
excluded-patches = "'Custom branding'"
apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube-music" apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube-music"
uptodown-dlurl = "https://youtube-music.en.uptodown.com/android" uptodown-dlurl = "https://youtube-music.en.uptodown.com/android"
# archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.apps.youtube.music" archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.apps.youtube.music"
[Music-Morphe]
app-name = "Music"
patches-source = "MorpheApp/morphe-patches"
cli-source = "MorpheApp/morphe-cli"
rv-brand = "Morphe"
build-mode = "both"
arch = "both"
excluded-patches = "'Custom branding'"
apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube-music"
uptodown-dlurl = "https://youtube-music.en.uptodown.com/android"
archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.apps.youtube.music"
[Reddit-Morphe]
app-name = "Reddit"
rv-brand = "Morphe"
build-mode = "apk"
patches-source = "MorpheApp/morphe-patches"
cli-source = "MorpheApp/morphe-cli"
apkmirror-dlurl = "https://www.apkmirror.com/apk/redditinc/reddit/"
archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.reddit.frontpage"
uptodown-dlurl = "https://reddit-official-app.en.uptodown.com/android"
excluded-patches = "'Custom branding name for Reddit'"
dpi = "120-640dpi"
[Twitter]
enabled = false
patches-source = "crimera/piko"
cli-source = "MorpheApp/morphe-cli"
rv-brand = "Piko"
apkmirror-dlurl = "https://www.apkmirror.com/apk/x-corp/twitter/"
archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.twitter.android"
build-mode = "module"
version = "11.81.0-release.0"
include-stock = "split"
[GooglePhotos] [GooglePhotos]
build-mode = "both" build-mode = "both"
arch = "both" arch = "both"
version = "auto"
apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/photos/" apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/photos/"
uptodown-dlurl = "https://google-photos.en.uptodown.com/android" uptodown-dlurl = "https://google-photos.en.uptodown.com/android"
archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.apps.photos"
[Music-Extended] [Twitch]
app-name = "Music"
patches-source = "inotia00/revanced-patches"
cli-source = "inotia00/revanced-cli"
rv-brand = "ReVanced Extended"
build-mode = "both"
arch = "both"
apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube-music"
# archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.apps.youtube.music"
[YouTube-Extended]
app-name = "YouTube"
patches-source = "inotia00/revanced-patches"
cli-source = "inotia00/revanced-cli"
rv-brand = "ReVanced Extended"
build-mode = "both"
apkmirror-dlurl = "https://www.apkmirror.com/apk/google-inc/youtube"
included-patches = "'Custom header for YouTube'"
excluded-patches = "'Custom branding icon for YouTube' 'Custom branding name for YouTube'"
# archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.google.android.youtube"
[Reddit-Extended]
patches-source = "inotia00/revanced-patches"
cli-source = "inotia00/revanced-cli"
rv-brand = "ReVanced Extended"
apkmirror-dlurl = "https://www.apkmirror.com/apk/redditinc/reddit/"
# archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.reddit.frontpage"
[TikTok]
enabled = false enabled = false
# archive-dlurl = "https://archive.org/download/jhc-apks/apks/com.zhiliaoapp.musically" apkmirror-dlurl = "https://www.apkmirror.com/apk/twitch-interactive-inc/twitch/"
included-patches = "'SIM spoof'" uptodown-dlurl = "https://twitch.en.uptodown.com/android"
[Messenger]
enabled = false
apkmirror-dlurl = "https://www.apkmirror.com/apk/facebook-2/messenger/"
arch = "arm64-v8a"
[Spotify]
enabled = false
uptodown-dlurl = "https://spotify.en.uptodown.com/android"
BIN
View File
Binary file not shown.
+23
View File
@@ -0,0 +1,23 @@
#!/system/bin/sh
MODDIR=${0%/*}
. "$MODDIR/utils.sh"
DFILE="$MODDIR/disabled_by_action"
if [ -z "$(get_mounts)" ]; then
rm -f "$DFILE"
if mount_nosleep; then
echo "* Enabled successfully"
cp -f "$MODDIR/module.prop.orig" "$MODDIR/module.prop"
else
echo "* Failed"
fi
echo ""
get_mounts
else
touch "$DFILE"
umount_all
echo "* Disabled"
ch_desc "⛔ Disabled by action"
fi
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+185
View File
@@ -0,0 +1,185 @@
#!/system/bin/sh
MODDIR=$MODPATH
. "$MODPATH/utils.sh"
ui_print ""
if [ -n "$MODULE_ARCH" ] && [ "$MODULE_ARCH" != "$ARCH" ]; then
abort "ERROR: Wrong arch
Your device: $ARCH
Module: $MODULE_ARCH"
fi
if [ "$ARCH" = "arm" ]; then
ARCH_LIB=armeabi-v7a
elif [ "$ARCH" = "arm64" ]; then
ARCH_LIB=arm64-v8a
elif [ "$ARCH" = "x86" ]; then
ARCH_LIB=x86
elif [ "$ARCH" = "x64" ]; then
ARCH_LIB=x86_64
else abort "ERROR: unreachable: ${ARCH}"; fi
set_perm_recursive "$MODPATH/bin" 0 0 0755 0777
umount_all
if OP=$(dumpsys package "$PKG_NAME") && [ "$OP" ]; then
if echo "$OP" | grep -m1 pkgFlags | grep -Fq UPDATED_SYSTEM_APP; then
pmex uninstall-system-updates "$PKG_NAME" >/dev/null 2>&1
fi
else
if pmex install-existing "$PKG_NAME" >/dev/null 2>&1; then
pmex uninstall-system-updates "$PKG_NAME" >/dev/null 2>&1
fi
fi
INS=true
if BASEPATH=$(get_basepath); then
if [ "${BASEPATH:1:4}" != data ]; then
ui_print "* Detected $PKG_NAME as a system app"
SCNM="/data/adb/post-fs-data.d/$PKG_NAME-uninstall.sh"
mkdir -p /data/adb/post-fs-data.d
echo "mount -t tmpfs none $BASEPATH" >"$SCNM"
chmod +x "$SCNM"
ui_print "* Created the uninstall script."
ui_print ""
ui_print "* Reboot and reflash the module!"
abort
fi
VERSION=$(get_app_version)
if [ "$VERSION" ] && [ "$VERSION" = "$PKG_VER" ]; then
ui_print "* $PKG_NAME is up-to-date ($VERSION)"
INS=false
elif [ ! -f "$MODPATH/stock/base.apk" ]; then
ui_print "ERROR: Version mismatch
installed: '$VERSION'
module: '$PKG_VER'"
abort
fi
# TODO:
# elif "${MODPATH:?}/bin/$ARCH/cmpr" "$BASEPATH/base.apk" "$MODPATH/$PKG_NAME.apk"; then
# ui_print "* $PKG_NAME is up-to-date"
# INS=false
# fi
fi
install() {
if [ ! -f "$MODPATH/stock/base.apk" ]; then
abort "ERROR: Stock $PKG_NAME apk was not found"
fi
install_err=""
VERIF1=$(settings get global verifier_verify_adb_installs)
VERIF2=$(settings get global package_verifier_enable)
settings put global verifier_verify_adb_installs 0
settings put global package_verifier_enable 0
SZ=$(stat -c "%s" "$MODPATH"/stock/*.apk | awk '{sum += $0} END {print sum}')
for IT in 1 2; do
ui_print "* Updating $PKG_NAME to $PKG_VER"
if ! SES=$(pmex install-create --user 0 -i com.android.vending -r -S "$SZ"); then
ui_print "ERROR: install-create failed"
install_err="$SES"
break
fi
SES=${SES#*[} SES=${SES%]*}
for apki in "$MODPATH/stock"/*.apk; do
set_perm "${apki}" 1000 1000 644 u:object_r:apk_data_file:s0
if ! op=$(pmex install-write -S "$SZ" "$SES" "$(basename "${apki}")" "${apki}"); then
ui_print "ERROR: install-write failed"
install_err="$op"
break
fi
done
if [ "$install_err" ]; then break; fi
if ! op=$(pmex install-commit "$SES"); then
ui_print "$op"
if echo "$op" | grep -q -e INSTALL_FAILED_VERSION_DOWNGRADE -e INSTALL_FAILED_UPDATE_INCOMPATIBLE -e INSTALL_FAILED_DUPLICATE; then
ui_print "* Uninstalling..."
ex_unins_arg=""
if echo "$op" | grep -q INSTALL_FAILED_DUPLICATE; then
ex_unins_arg="-k"
fi
if ! op=$(pmex uninstall --user 0 $ex_unins_arg "$PKG_NAME"); then
ui_print "$op"
if [ $IT = 2 ]; then
install_err="ERROR: pm uninstall failed."
break
fi
fi
continue
fi
ui_print "ERROR: install-commit failed"
install_err="$op"
break
fi
if BASEPATH=$(get_basepath); then
:
else
install_err=" "
break
fi
break
done
settings put global verifier_verify_adb_installs "$VERIF1"
settings put global package_verifier_enable "$VERIF2"
if [ "$install_err" ]; then
abort "$install_err"
fi
}
if [ $INS = true ] && ! install; then abort; fi
BASEPATHLIB=${BASEPATH}/lib/${ARCH}
if [ $INS = true ] || [ -z "$(ls -A1 "$BASEPATHLIB")" ]; then
ui_print "* Extracting native libs"
if [ ! -d "$BASEPATHLIB" ]; then mkdir -p "$BASEPATHLIB"; else rm -f "$BASEPATHLIB"/* >/dev/null 2>&1 || :; fi
if op=$(unzip -o -j "$MODPATH/stock/base.apk" "lib/${ARCH_LIB}/*" -d "$BASEPATHLIB" 2>&1); then
set_perm_recursive "${BASEPATH}/lib" 1000 1000 755 755 u:object_r:apk_data_file:s0
else
echo >&2 "ERROR: extracting native libs failed: '$op'"
fi
fi
set_perm "$MODPATH/base.apk" 1000 1000 644 u:object_r:apk_data_file:s0
ui_print "* Mounting $PKG_NAME"
# move out the apk from /data/adb/modules/.. to /data/adb/rvhc to not trip some root detections
mkdir -p "/data/adb/rvhc"
mv -f "$MODPATH/base.apk" "$RVPATH"
if ! op=$(su -M -c mount -o bind "$RVPATH" "$BASEPATH/base.apk" 2>&1); then
ui_print "ERROR: Mount failed!"
ui_print "$op"
fi
am force-stop "$PKG_NAME"
ui_print "* Optimizing $PKG_NAME"
cmd package compile -m speed-profile -f "$PKG_NAME" >/dev/null 2>&1
# nohup cmd package compile -m speed-profile -f "$PKG_NAME" >/dev/null 2>&1
if [ "$KSU" ]; then
DUMPSYS=$(dumpsys package "$PKG_NAME" 2>&1)
UID=$(echo "$DUMPSYS" | grep -m1 uid=)
UID=${UID#*=} UID=${UID%% *}
if [ -z "$UID" ]; then
UID=$(echo "$DUMPSYS" | grep -m1 userId=)
UID=${UID#*=} UID=${UID%% *}
fi
if [ "$UID" ]; then
if ! OP=$("${MODPATH:?}/bin/$ARCH/ksu_profile" "$UID" "$PKG_NAME" 2>&1); then
ui_print " $OP"
ui_print " * In your root manager app,"
ui_print " disable 'Unmount modules' for $PKG_NAME"
fi
else
ui_print "ERROR: UID could not be found for $PKG_NAME"
fi
fi
rm -rf "${MODPATH:?}/bin" "$MODPATH/stock/"
cp -f "$MODPATH/module.prop" "$MODPATH/module.prop.orig"
ui_print "* Done"
ui_print " by j-hc (github.com/j-hc)"
ui_print " "
+26
View File
@@ -0,0 +1,26 @@
#!/system/bin/sh
MODDIR=${0%/*}
. "$MODDIR/utils.sh"
run() {
until [ "$(getprop sys.boot_completed)" = 1 ]; do sleep 1; done
until [ -d "/sdcard/Android" ]; do sleep 1; done
while
BASEPATH=$(get_basepath)
SVCL=$?
[ $SVCL = 20 ]
do sleep 2; done
if [ $SVCL != 0 ]; then
ch_desc_err "App not installed"
return
fi
sleep 4
mount_rv "$BASEPATH"
}
if [ ! -f "$MODDIR/disabled_by_action" ]; then
run
fi
+9
View File
@@ -0,0 +1,9 @@
#!/system/bin/sh
MODDIR=${0%/*}
. "$MODDIR/config"
rm -f "/data/adb/rvhc/${MODDIR##*/}.apk"
rmdir "/data/adb/rvhc"
rm -f "/data/adb/post-fs-data.d/$PKG_NAME-uninstall.sh"
+74
View File
@@ -0,0 +1,74 @@
#!/system/bin/sh
RVPATH=/data/adb/rvhc/${MODDIR##*/}.apk
. "$MODDIR/config"
ch_desc() {
sed -i "s/^des.*/description=${1}/g" "$MODDIR/module.prop"
}
ch_desc_err() {
ch_desc "⚠️ Needs reflash: '${1}'"
}
pmex() {
OP=$(pm "$@" 2>&1 </dev/null)
RET=$?
echo "$OP"
return $RET
}
get_app_version() {
VERSION=$(dumpsys package "$PKG_NAME" 2>&1 | grep -m1 versionName=) VERSION="${VERSION#*=}"
echo "$VERSION"
}
get_basepath() {
BASEPATH=$(pmex path "$PKG_NAME")
SVCL=$?
BASEPATH=${BASEPATH##*:} BASEPATH=${BASEPATH%/*}
echo "$BASEPATH"
return $SVCL
}
umount_all() {
su -M -c grep -F "$PKG_NAME" /proc/mounts | while read -r line; do
mp=${line#* } mp=${mp%% *} mp=${mp%%\\*}
su -M -c umount -l "${mp}"
done
am force-stop "$PKG_NAME" || :
}
get_mounts() {
su -M -c grep -F "$PKG_NAME" /proc/mounts || :
}
mount_rv() {
if [ ! -d "${1}/lib" ]; then
ch_desc_err "Mount failed. Dont report this, consider using rvmm-zygisk-mount"
return 1
fi
VERSION=$(get_app_version)
if [ "$VERSION" != "$PKG_VER" ] && [ "$VERSION" ]; then
ch_desc_err "Version mismatch (installed:${VERSION}, module:$PKG_VER)"
return 1
fi
umount_all
if ! chcon u:object_r:apk_data_file:s0 "$RVPATH"; then
ch_desc_err "Apk not found"
return 1
fi
mount -o bind "$RVPATH" "${1}/base.apk"
am force-stop "$PKG_NAME"
cp -f "$MODDIR/module.prop.orig" "$MODDIR/module.prop"
return 0
}
mount_nosleep() {
if ! BASEPATH=$(get_basepath); then
ch_desc_err "App not installed"
return 1
fi
mount_rv "$BASEPATH"
}
-176
View File
@@ -1,176 +0,0 @@
. "$MODPATH/config"
ui_print ""
if [ -n "$MODULE_ARCH" ] && [ "$MODULE_ARCH" != "$ARCH" ]; then
abort "ERROR: Wrong arch
Your device: $ARCH
Module: $MODULE_ARCH"
fi
if [ "$ARCH" = "arm" ]; then
ARCH_LIB=armeabi-v7a
elif [ "$ARCH" = "arm64" ]; then
ARCH_LIB=arm64-v8a
elif [ "$ARCH" = "x86" ]; then
ARCH_LIB=x86
elif [ "$ARCH" = "x64" ]; then
ARCH_LIB=x86_64
else abort "ERROR: unreachable: ${ARCH}"; fi
RVPATH=/data/adb/rvhc/${MODPATH##*/}.apk
set_perm_recursive "$MODPATH/bin" 0 0 0755 0777
if su -M -c true >/dev/null 2>/dev/null; then
alias mm='su -M -c'
else alias mm='nsenter -t1 -m'; fi
mm grep -F "$PKG_NAME" /proc/mounts | while read -r line; do
ui_print "* Un-mount"
mp=${line#* } mp=${mp%% *}
mm umount -l "${mp%%\\*}"
done
am force-stop "$PKG_NAME"
pmex() {
OP=$(pm "$@" 2>&1 </dev/null)
RET=$?
echo "$OP"
return $RET
}
if ! pmex path "$PKG_NAME" >&2; then
if pmex install-existing "$PKG_NAME" >&2; then
BASEPATH=$(pmex path "$PKG_NAME") || abort "ERROR: pm path failed $BASEPATH"
echo >&2 "'$BASEPATH'"
BASEPATH=${BASEPATH##*:} BASEPATH=${BASEPATH%/*}
if [ "${BASEPATH:1:4}" = data ]; then
if pmex uninstall -k --user 0 "$PKG_NAME" >&2; then
rm -rf "$BASEPATH" 2>&1
ui_print "* Cleared existing $PKG_NAME package"
ui_print "* Reboot and reflash"
abort
else abort "ERROR: pm uninstall failed"; fi
else ui_print "* Installed stock $PKG_NAME package"; fi
fi
fi
IS_SYS=false
INS=true
if BASEPATH=$(pmex path "$PKG_NAME"); then
echo >&2 "'$BASEPATH'"
BASEPATH=${BASEPATH##*:} BASEPATH=${BASEPATH%/*}
if [ "${BASEPATH:1:4}" != data ]; then
ui_print "* $PKG_NAME is a system app."
IS_SYS=true
elif [ ! -f "$MODPATH/$PKG_NAME.apk" ]; then
ui_print "* Stock $PKG_NAME APK was not found"
VERSION=$(dumpsys package "$PKG_NAME" | grep -m1 versionName) VERSION="${VERSION#*=}"
if [ "$VERSION" = "$PKG_VER" ] || [ -z "$VERSION" ]; then
ui_print "* Skipping stock installation"
INS=false
else
abort "ERROR: Version mismatch
installed: $VERSION
module: $PKG_VER
"
fi
elif "${MODPATH:?}/bin/$ARCH/cmpr" "$BASEPATH/base.apk" "$MODPATH/$PKG_NAME.apk"; then
ui_print "* $PKG_NAME is up-to-date"
INS=false
fi
fi
install() {
if [ ! -f "$MODPATH/$PKG_NAME.apk" ]; then
abort "ERROR: Stock $PKG_NAME apk was not found"
fi
ui_print "* Updating $PKG_NAME to $PKG_VER"
VERIF_ADB=$(settings get global verifier_verify_adb_installs)
settings put global verifier_verify_adb_installs 0
SZ=$(stat -c "%s" "$MODPATH/$PKG_NAME.apk")
for IT in 1 2; do
if ! SES=$(pmex install-create --user 0 -i com.android.vending -r -d -S "$SZ"); then
ui_print "ERROR: install-create failed"
settings put global verifier_verify_adb_installs "$VERIF_ADB"
abort "$SES"
fi
SES=${SES#*[} SES=${SES%]*}
set_perm "$MODPATH/$PKG_NAME.apk" 1000 1000 644 u:object_r:apk_data_file:s0
if ! op=$(pmex install-write -S "$SZ" "$SES" "$PKG_NAME.apk" "$MODPATH/$PKG_NAME.apk"); then
ui_print "ERROR: install-write failed"
settings put global verifier_verify_adb_installs "$VERIF_ADB"
abort "$op"
fi
if ! op=$(pmex install-commit "$SES"); then
if echo "$op" | grep -q INSTALL_FAILED_VERSION_DOWNGRADE; then
ui_print "* Handling INSTALL_FAILED_VERSION_DOWNGRADE.."
if [ "$IS_SYS" = true ]; then
mkdir -p /data/adb/rvhc/empty /data/adb/post-fs-data.d
SCNM="/data/adb/post-fs-data.d/$PKG_NAME-uninstall.sh"
echo "mount -o bind /data/adb/rvhc/empty $BASEPATH" >"$SCNM"
chmod +x "$SCNM"
ui_print "* Created the uninstall script."
ui_print ""
ui_print "* Reboot and reflash the module!"
abort
else
ui_print "* Uninstalling..."
if ! op=$(pmex uninstall -k --user 0 "$PKG_NAME"); then
ui_print "$op"
if [ $IT = 2 ]; then abort "ERROR: pm uninstall failed."; fi
fi
continue
fi
fi
ui_print "ERROR: install-commit failed"
settings put global verifier_verify_adb_installs "$VERIF_ADB"
abort "$op"
fi
if BASEPATH=$(pmex path "$PKG_NAME"); then
BASEPATH=${BASEPATH##*:} BASEPATH=${BASEPATH%/*}
else
settings put global verifier_verify_adb_installs "$VERIF_ADB"
abort "ERROR: install $PKG_NAME manually and reflash the module"
fi
break
done
settings put global verifier_verify_adb_installs "$VERIF_ADB"
}
if [ $INS = true ] && ! install; then abort; fi
BASEPATHLIB=${BASEPATH}/lib/${ARCH}
if [ $INS = true ] || [ -z "$(ls -A1 "$BASEPATHLIB")" ]; then
ui_print "* Extracting native libs"
if [ ! -d "$BASEPATHLIB" ]; then mkdir -p "$BASEPATHLIB"; else rm -f "$BASEPATHLIB"/* >/dev/null 2>&1 || :; fi
if ! op=$(unzip -o -j "$MODPATH/$PKG_NAME.apk" "lib/${ARCH_LIB}/*" -d "$BASEPATHLIB" 2>&1); then
ui_print "ERROR: extracting native libs failed"
abort "$op"
fi
set_perm_recursive "${BASEPATH}/lib" 1000 1000 755 755 u:object_r:apk_data_file:s0
fi
ui_print "* Setting Permissions"
set_perm "$MODPATH/base.apk" 1000 1000 644 u:object_r:apk_data_file:s0
ui_print "* Mounting $PKG_NAME"
mkdir -p "/data/adb/rvhc"
RVPATH=/data/adb/rvhc/${MODPATH##*/}.apk
mv -f "$MODPATH/base.apk" "$RVPATH"
if ! op=$(mm mount -o bind "$RVPATH" "$BASEPATH/base.apk" 2>&1); then
ui_print "ERROR: Mount failed!"
ui_print "$op"
fi
am force-stop "$PKG_NAME"
ui_print "* Optimizing $PKG_NAME"
nohup cmd package compile --reset "$PKG_NAME" >/dev/null 2>&1 &
ui_print "* Cleanup"
rm -rf "${MODPATH:?}/bin" "$MODPATH/$PKG_NAME.apk"
if [ "$KSU" ] && [ -d "/data/adb/modules/zygisk-assistant" ]; then
ui_print "* If you are using zygisk-assistant, you need to"
ui_print " give root permissions to $PKG_NAME"
fi
ui_print "* Done"
ui_print " by j-hc (github.com/j-hc)"
ui_print " "
-49
View File
@@ -1,49 +0,0 @@
#!/system/bin/sh
MODDIR=${0%/*}
RVPATH=/data/adb/rvhc/${MODDIR##*/}.apk
. "$MODDIR/config"
err() {
[ ! -f "$MODDIR/err" ] && cp "$MODDIR/module.prop" "$MODDIR/err"
sed -i "s/^des.*/description=⚠️ Needs reflash: '${1}'/g" "$MODDIR/module.prop"
}
until [ "$(getprop sys.boot_completed)" = 1 ]; do sleep 1; done
until [ -d "/sdcard/Android" ]; do sleep 1; done
while
BASEPATH=$(pm path "$PKG_NAME" 2>&1 </dev/null)
SVCL=$?
[ $SVCL = 20 ]
do sleep 2; done
run() {
if [ $SVCL != 0 ]; then
err "app not installed"
return
fi
sleep 4
BASEPATH=${BASEPATH##*:} BASEPATH=${BASEPATH%/*}
if [ ! -d "$BASEPATH/lib" ]; then # TODO: is this ok? idk
ls -Zla "$BASEPATH" >"$MODDIR/log.txt"
ls -Zla "$BASEPATH/lib" >>"$MODDIR/log.txt"
else rm "$MODDIR/log.txt" >/dev/null 2>&1; fi
VERSION=$(dumpsys package "$PKG_NAME" | grep -m1 versionName) VERSION="${VERSION#*=}"
if [ "$VERSION" != "$PKG_VER" ] && [ "$VERSION" ]; then
err "version mismatch (installed:${VERSION}, module:$PKG_VER)"
return
fi
grep "$PKG_NAME" /proc/mounts | while read -r line; do
mp=${line#* } mp=${mp%% *}
umount -l "${mp%%\\*}"
done
if ! chcon u:object_r:apk_data_file:s0 "$RVPATH"; then
err "apk not found"
return
fi
mount -o bind "$RVPATH" "$BASEPATH/base.apk"
am force-stop "$PKG_NAME"
[ -f "$MODDIR/err" ] && mv -f "$MODDIR/err" "$MODDIR/module.prop"
}
run
-9
View File
@@ -1,9 +0,0 @@
#!/system/bin/sh
{
MODDIR=${0%/*}
. "$MODDIR/config"
rm "/data/adb/rvhc/${MODDIR##*/}.apk"
rmdir "/data/adb/rvhc"
rm "/data/adb/post-fs-data.d/$PKG_NAME-uninstall.sh"
} &
+1 -2
View File
@@ -1,5 +1,4 @@
a2a1ad7ba7f41dfca4514e2afeb90691719af6d0fdbed4b09bbf0ed897701ceb com.google.android.apps.youtube.music a2a1ad7ba7f41dfca4514e2afeb90691719af6d0fdbed4b09bbf0ed897701ceb com.google.android.apps.youtube.music
3d7a1223019aa39d9ea0e3436ab7c0896bfb4fb679f4de5fe7c23f326c8f994a com.google.android.youtube 3d7a1223019aa39d9ea0e3436ab7c0896bfb4fb679f4de5fe7c23f326c8f994a com.google.android.youtube
970b91143813b4c9d5f3634f672c9fcaa5621b4efaaedafd6c235cbbb869736f com.reddit.frontpage 970b91143813b4c9d5f3634f672c9fcaa5621b4efaaedafd6c235cbbb869736f com.reddit.frontpage
9041803e91bcb814b4b4399fb5c85a91640b755e5e8ba76813814bf4cf2ab5ba com.zhiliaoapp.musically 1338f9b049893cc70b78432a177582f90bd4bc6296ea4ed35bcc7df59687ac53 tv.twitch.android.app
1338f9b049893cc70b78432a177582f90bd4bc6296ea4ed35bcc7df59687ac53 tv.twitch.android.app
+384 -180
View File
@@ -1,10 +1,11 @@
#!/usr/bin/env bash #!/usr/bin/env bash
MODULE_TEMPLATE_DIR="revanced-magisk" MODULE_TEMPLATE_DIR="module"
CWD=$(pwd) CWD=$(pwd)
TEMP_DIR="temp" TEMP_DIR="temp"
BIN_DIR="bin" BIN_DIR="bin"
BUILD_DIR="build" BUILD_DIR="build"
DL_SRCS=("direct" "archive" "apkmirror" "uptodown")
if [ "${GITHUB_TOKEN-}" ]; then GH_HEADER="Authorization: token ${GITHUB_TOKEN}"; else GH_HEADER=; fi if [ "${GITHUB_TOKEN-}" ]; then GH_HEADER="Authorization: token ${GITHUB_TOKEN}"; else GH_HEADER=; fi
NEXT_VER_CODE=${NEXT_VER_CODE:-$(date +'%Y%m%d')} NEXT_VER_CODE=${NEXT_VER_CODE:-$(date +'%Y%m%d')}
@@ -22,12 +23,15 @@ toml_get_table_names() { jq -r -e 'to_entries[] | select(.value | type == "objec
toml_get_table_main() { jq -r -e 'to_entries | map(select(.value | type != "object")) | from_entries' <<<"$__TOML__"; } toml_get_table_main() { jq -r -e 'to_entries | map(select(.value | type != "object")) | from_entries' <<<"$__TOML__"; }
toml_get_table() { jq -r -e ".\"${1}\"" <<<"$__TOML__"; } toml_get_table() { jq -r -e ".\"${1}\"" <<<"$__TOML__"; }
toml_get() { toml_get() {
local op local op quote_placeholder=$'\001'
op=$(jq -r ".\"${2}\" | values" <<<"$1") op=$(jq -r ".\"${2}\" | values" <<<"$1")
if [ "$op" ]; then if [ "$op" ]; then
op="${op#"${op%%[![:space:]]*}"}" op="${op#"${op%%[![:space:]]*}"}"
op="${op%"${op##*[![:space:]]}"}" op="${op%"${op##*[![:space:]]}"}"
op=${op//\\\'/$quote_placeholder}
op=${op//"''"/$quote_placeholder}
op=${op//"'"/'"'} op=${op//"'"/'"'}
op=${op//$quote_placeholder/$'\''}
echo "$op" echo "$op"
else return 1; fi else return 1; fi
} }
@@ -35,38 +39,48 @@ toml_get() {
pr() { echo -e "\033[0;32m[+] ${1}\033[0m"; } pr() { echo -e "\033[0;32m[+] ${1}\033[0m"; }
epr() { epr() {
echo >&2 -e "\033[0;31m[-] ${1}\033[0m" echo >&2 -e "\033[0;31m[-] ${1}\033[0m"
if [ "${GITHUB_REPOSITORY-}" ]; then echo -e "::error::utils.sh [-] ${1}\n"; fi if [ "${GITHUB_REPOSITORY-}" ]; then echo >&2 -e "::error::utils.sh [-] ${1}\n"; fi
} }
abort() { wpr() {
epr "ABORT: ${1-}" echo >&2 -e "\033[0;33m[!] ${1}\033[0m"
exit 1 if [ "${GITHUB_REPOSITORY-}" ]; then echo >&2 -e "::warning::utils.sh [!] ${1}\n"; fi
} }
get_rv_prebuilts() { _clean_tmp() {
rm -rf ./${TEMP_DIR}/*tmp.* ./${TEMP_DIR}/*tmp_* ./${TEMP_DIR}/*/*tmp.* ./${TEMP_DIR}/*-temporary-files ./*-temporary-files
}
abort() {
epr "ABORT: ${1-}"
_clean_tmp
trap - SIGTERM SIGINT EXIT
kill -9 -- -$$ 2>/dev/null
exit 1
}
java() { env -i java --enable-native-access=ALL-UNNAMED "$@"; }
get_prebuilts() {
local cli_src=$1 cli_ver=$2 patches_src=$3 patches_ver=$4 local cli_src=$1 cli_ver=$2 patches_src=$3 patches_ver=$4
pr "Getting prebuilts (${patches_src%/*})" >&2 pr "Getting prebuilts (${patches_src%/*})" >&2
local cl_dir=${patches_src%/*} local cl_dir=${patches_src%/*}
cl_dir=${TEMP_DIR}/${cl_dir,,}-rv cl_dir=${TEMP_DIR}/${cl_dir,,}-rv
[ -d "$cl_dir" ] || mkdir "$cl_dir" [ -d "$cl_dir" ] || mkdir "$cl_dir"
for src_ver in "$cli_src CLI $cli_ver revanced-cli" "$patches_src Patches $patches_ver patches"; do
for src_ver in "Patches $patches_src $patches_ver" "CLI $cli_src $cli_ver"; do
set -- $src_ver set -- $src_ver
local src=$1 tag=$2 ver=${3-} fprefix=$4 local tag=$1 src=$2 ver=${3-}
local ext
if [ "$tag" = "CLI" ]; then
ext="jar"
local grab_cl=false
elif [ "$tag" = "Patches" ]; then
ext="rvp"
local grab_cl=true
else abort unreachable; fi
local dir=${src%/*} local dir=${src%/*}
dir=${TEMP_DIR}/${dir,,}-rv dir=${TEMP_DIR}/${dir,,}-rv
[ -d "$dir" ] || mkdir "$dir" [ -d "$dir" ] || mkdir "$dir"
local rv_rel="https://api.github.com/repos/${src}/releases" name_ver local rv_rel="https://api.github.com/repos/${src}/releases" name_ver
if [ "$ver" = "dev" ]; then if [ "$ver" = "dev" ]; then
name_ver="*-dev*" local resp
elif [ "$ver" = "latest" ]; then resp=$(gh_req "$rv_rel" -) || return 1
ver=$(jq -e -r '.[] | .tag_name' <<<"$resp" | get_highest_ver) || return 1
fi
if [ "$ver" = "latest" ]; then
rv_rel+="/latest" rv_rel+="/latest"
name_ver="*" name_ver="*"
else else
@@ -74,14 +88,40 @@ get_rv_prebuilts() {
name_ver="$ver" name_ver="$ver"
fi fi
local url file tag_name name local file
file=$(find "$dir" -name "${fprefix}-${name_ver#v}.${ext}" -type f 2>/dev/null) if [ "$tag" = "CLI" ]; then
file=$(find "$dir" -maxdepth 1 -name "*cli-${name_ver#v}*.jar" -o -name "*desktop-${name_ver#v}*.jar" -type f 2>/dev/null)
local grab_cl=false
elif [ "$tag" = "Patches" ]; then
file=$(find "$dir" -maxdepth 1 -name "*patches-${name_ver#v}.*" -type f 2>/dev/null)
local grab_cl=true
else abort unreachable; fi
local url tag_name matches
if [ "$ver" = "latest" ]; then
file=$(grep -v '/[^/]*dev[^/]*$' <<<"$file" | head -1)
else
file=$(grep "/[^/]*${ver#v}[^/]*\$" <<<"$file" | head -1)
fi
if [ -z "$file" ]; then if [ -z "$file" ]; then
local resp asset name local resp asset name
resp=$(gh_req "$rv_rel" -) || return 1 resp=$(gh_req "$rv_rel" -) || return 1
if [ "$ver" = "dev" ]; then resp=$(jq -r '.[0]' <<<"$resp"); fi tag_name=$(jq -r '.tag_name' <<<"$resp") || return 1
tag_name=$(jq -r '.tag_name' <<<"$resp") matches=$(jq -e '.assets | map(select(.name | (endswith("asc") or endswith("json")) | not))' <<<"$resp") || return 1
asset=$(jq -e -r ".assets[] | select(.name | endswith(\"$ext\"))" <<<"$resp") || return 1 if [ "$(jq 'length' <<<"$matches")" -gt 1 ]; then
local matches_new
matches_new=$(jq -e -r 'map(select(.name | contains("-dev") | not))' <<<"$matches")
if [ "$(jq 'length' <<<"$matches_new")" -eq 1 ]; then
matches=$matches_new
fi
fi
if [ "$(jq 'length' <<<"$matches")" -eq 0 ]; then
epr "No asset was found"
return 1
elif [ "$(jq 'length' <<<"$matches")" -ne 1 ]; then
wpr "More than 1 asset was found for this release. Falling back to the first one found..."
fi
asset=$(jq -r ".[0]" <<<"$matches")
url=$(jq -r .url <<<"$asset") url=$(jq -r .url <<<"$asset")
name=$(jq -r .name <<<"$asset") name=$(jq -r .name <<<"$asset")
file="${dir}/${name}" file="${dir}/${name}"
@@ -89,23 +129,21 @@ get_rv_prebuilts() {
echo "$tag: $(cut -d/ -f1 <<<"$src")/${name} " >>"${cl_dir}/changelog.md" echo "$tag: $(cut -d/ -f1 <<<"$src")/${name} " >>"${cl_dir}/changelog.md"
else else
grab_cl=false grab_cl=false
local for_err=$file
if [ "$ver" = "latest" ]; then
file=$(grep -v '/[^/]*dev[^/]*$' <<<"$file" | head -1)
else file=$(grep "/[^/]*${ver#v}[^/]*\$" <<<"$file" | head -1); fi
if [ -z "$file" ]; then abort "filter fail: '$for_err' with '$ver'"; fi
name=$(basename "$file") name=$(basename "$file")
tag_name=$(cut -d'-' -f3- <<<"$name") tag_name=$(cut -d'-' -f3- <<<"$name")
tag_name=v${tag_name%.*} tag_name=v${tag_name%.*}
fi fi
if [ "$tag" = "Patches" ]; then if [ "$tag" = "Patches" ]; then
if [ $grab_cl = true ]; then echo -e "[Changelog](https://github.com/${src}/releases/tag/${tag_name})\n" >>"${cl_dir}/changelog.md"; fi if [ "$grab_cl" = true ]; then echo -e "[Changelog](https://github.com/${src}/releases/tag/${tag_name})\n" >>"${cl_dir}/changelog.md"; fi
if [ "$REMOVE_RV_INTEGRATIONS_CHECKS" = true ]; then if [ "$REMOVE_RV_INTEGRATIONS_CHECKS" = true ]; then
local extensions_ext
extensions_ext=$(unzip -l "${file}" "extensions/shared.*" | grep -o "shared\..*") extensions_ext="${extensions_ext#*.}"
if ! ( if ! (
mkdir -p "${file}-zip" || return 1 mkdir -p "${file}-zip" || return 1
unzip -qo "${file}" -d "${file}-zip" || return 1 unzip -qo "${file}" -d "${file}-zip" || return 1
java -cp "${BIN_DIR}/paccer.jar:${BIN_DIR}/dexlib2.jar" com.jhc.Main "${file}-zip/extensions/shared.rve" "${file}-zip/extensions/shared-patched.rve" || return 1 java -cp "${BIN_DIR}/paccer.jar:${BIN_DIR}/dexlib2.jar" com.jhc.Main "${file}-zip/extensions/shared.${extensions_ext}" "${file}-zip/extensions/shared-patched.${extensions_ext}" || return 1
mv -f "${file}-zip/extensions/shared-patched.rve" "${file}-zip/extensions/shared.rve" || return 1 mv -f "${file}-zip/extensions/shared-patched.${extensions_ext}" "${file}-zip/extensions/shared.${extensions_ext}" || return 1
rm "${file}" || return 1 rm "${file}" || return 1
cd "${file}-zip" || abort cd "${file}-zip" || abort
zip -0rq "${CWD}/${file}" . || return 1 zip -0rq "${CWD}/${file}" . || return 1
@@ -122,16 +160,12 @@ get_rv_prebuilts() {
set_prebuilts() { set_prebuilts() {
APKSIGNER="${BIN_DIR}/apksigner.jar" APKSIGNER="${BIN_DIR}/apksigner.jar"
if [ "$OS" = Android ]; then local arch
local arch arch=$(uname -m)
if [ "$(uname -m)" = aarch64 ]; then arch=arm64; else arch=arm; fi if [ "$arch" = aarch64 ]; then arch=arm64; elif [ "${arch:0:5}" = "armv7" ]; then arch=arm; fi
HTMLQ="${BIN_DIR}/htmlq/htmlq-${arch}" HTMLQ="${BIN_DIR}/htmlq/htmlq-${arch}"
AAPT2="${BIN_DIR}/aapt2/aapt2-${arch}" AAPT2="${BIN_DIR}/aapt2/aapt2-${arch}"
TOML="${BIN_DIR}/toml/tq-${arch}" TOML="${BIN_DIR}/toml/tq-${arch}"
else
HTMLQ="${BIN_DIR}/htmlq/htmlq-x86_64"
TOML="${BIN_DIR}/toml/tq-x86_64"
fi
} }
config_update() { config_update() {
@@ -144,7 +178,7 @@ config_update() {
if [ -z "$table_name" ]; then continue; fi if [ -z "$table_name" ]; then continue; fi
t=$(toml_get_table "$table_name") t=$(toml_get_table "$table_name")
enabled=$(toml_get "$t" enabled) || enabled=true enabled=$(toml_get "$t" enabled) || enabled=true
if [ "$enabled" = false ]; then continue; fi if [ "$enabled" = "false" ]; then continue; fi
PATCHES_SRC=$(toml_get "$t" patches-source) || PATCHES_SRC=$DEF_PATCHES_SRC PATCHES_SRC=$(toml_get "$t" patches-source) || PATCHES_SRC=$DEF_PATCHES_SRC
PATCHES_VER=$(toml_get "$t" patches-version) || PATCHES_VER=$DEF_PATCHES_VER PATCHES_VER=$(toml_get "$t" patches-version) || PATCHES_VER=$DEF_PATCHES_VER
if [[ -v sources["$PATCHES_SRC/$PATCHES_VER"] ]]; then if [[ -v sources["$PATCHES_SRC/$PATCHES_VER"] ]]; then
@@ -153,17 +187,17 @@ config_update() {
sources["$PATCHES_SRC/$PATCHES_VER"]=0 sources["$PATCHES_SRC/$PATCHES_VER"]=0
local rv_rel="https://api.github.com/repos/${PATCHES_SRC}/releases" local rv_rel="https://api.github.com/repos/${PATCHES_SRC}/releases"
if [ "$PATCHES_VER" = "dev" ]; then if [ "$PATCHES_VER" = "dev" ]; then
last_patches=$(gh_req "$rv_rel" - | jq -e -r '.[0]') last_patches=$(gh_req "$rv_rel" - | jq -e -r '.[0]') || continue
elif [ "$PATCHES_VER" = "latest" ]; then elif [ "$PATCHES_VER" = "latest" ]; then
last_patches=$(gh_req "$rv_rel/latest" -) last_patches=$(gh_req "$rv_rel/latest" -) || continue
else else
last_patches=$(gh_req "$rv_rel/tags/${ver}" -) last_patches=$(gh_req "$rv_rel/tags/${ver}" -) || continue
fi fi
if ! last_patches=$(jq -e -r '.assets[] | select(.name | endswith("rvp")) | .name' <<<"$last_patches"); then if ! last_patches=$(jq -e -r '.assets[] | select(.name | (endswith("asc") or endswith("json")) | not) | .name' <<<"$last_patches"); then
abort oops abort "config_update error: '$last_patches'"
fi fi
if [ "$last_patches" ]; then if [ "$last_patches" ]; then
if ! OP=$(grep "^Patches: ${PATCHES_SRC%%/*}/" build.md | grep "$last_patches"); then if ! OP=$(grep "^Patches: ${PATCHES_SRC%%/*}/" build.md | grep -m1 "$last_patches"); then
sources["$PATCHES_SRC/$PATCHES_VER"]=1 sources["$PATCHES_SRC/$PATCHES_VER"]=1
prcfg=true prcfg=true
upped+=("$table_name") upped+=("$table_name")
@@ -186,17 +220,20 @@ config_update() {
_req() { _req() {
local ip="$1" op="$2" local ip="$1" op="$2"
shift 2 shift 2
if [ "$op" = - ]; then local dlp="$op"
curl -L -c "$TEMP_DIR/cookie.txt" -b "$TEMP_DIR/cookie.txt" --connect-timeout 5 --retry 0 --fail -s -S "$@" "$ip" if [ "$op" != - ]; then
else
if [ -f "$op" ]; then return; fi if [ -f "$op" ]; then return; fi
local dlp
dlp="$(dirname "$op")/tmp.$(basename "$op")" dlp="$(dirname "$op")/tmp.$(basename "$op")"
if [ -f "$dlp" ]; then if [ -f "$dlp" ]; then
while [ -f "$dlp" ]; do sleep 1; done while [ -f "$dlp" ]; do sleep 1; done
return return
fi fi
curl -L -c "$TEMP_DIR/cookie.txt" -b "$TEMP_DIR/cookie.txt" --connect-timeout 5 --retry 0 --fail -s -S "$@" "$ip" -o "$dlp" || return 1 fi
if ! curl -L -c "$TEMP_DIR/cookie.txt" -b "$TEMP_DIR/cookie.txt" --connect-timeout 10 --retry 1 --fail -s -S "$@" "$ip" -o "$dlp"; then
epr "Request failed: $ip"
return 1
fi
if [ "$dlp" != - ]; then
mv -f "$dlp" "$op" mv -f "$dlp" "$op"
fi fi
} }
@@ -214,10 +251,11 @@ get_highest_ver() {
local vers m local vers m
vers=$(tee) vers=$(tee)
m=$(head -1 <<<"$vers") m=$(head -1 <<<"$vers")
if ! semver_validate "$m"; then echo "$m"; else sort -rV <<<"$vers" | head -1; fi if ! semver_validate "$m"; then echo "$m"; else sort -s -t- -k1,1Vr <<<"$vers" | head -1; fi
} }
semver_validate() { semver_validate() {
local a="${1%-*}" local a="${1%-*}"
local a="${a#v}"
local ac="${a//[.0-9]/}" local ac="${a//[.0-9]/}"
[ ${#ac} = 0 ] [ ${#ac} = 0 ]
} }
@@ -241,16 +279,52 @@ get_patch_last_supported_ver() {
return return
fi fi
fi fi
if ! op=$(java -jar "$rv_cli_jar" list-versions "$rv_patches_jar" -f "$pkg_name" 2>&1 | tail -n +3 | awk '{$1=$1}1'); then op=$(patches_list_versions "$cli_jar" "$patches_jar" "$pkg_name") || return 1
epr "list-versions: '$op'" op=$(sed -n '/Most common compatible versions:/,$p' <<<"$op" | sed '1d' | awk '{$1=$1}1')
return 1
fi
if [ "$op" = "Any" ]; then return; fi if [ "$op" = "Any" ]; then return; fi
pcount=$(head -1 <<<"$op") pcount=${pcount#*(} pcount=${pcount% *} pcount=$(head -1 <<<"$op") pcount=${pcount#*(} pcount=${pcount% *}
if [ -z "$pcount" ]; then abort "unreachable: '$pcount'"; fi if [ -z "$pcount" ]; then
abort "No patches found for '$pkg_name' in patches '$patches_jar'"
fi
grep -F "($pcount patch" <<<"$op" | sed 's/ (.* patch.*//' | get_highest_ver || return 1 grep -F "($pcount patch" <<<"$op" | sed 's/ (.* patch.*//' | get_highest_ver || return 1
} }
patches_list_versions() {
local cli_jar=$1 patches_jar=$2 pkg_name=$3 op cmd
local cmd_base="java -jar '$cli_jar' list-versions"
# TODO: remove this later
local cli_name
cli_name=$(basename "$cli_jar")
if [ "${cli_name::8}" = revanced ]; then cmd_base+=" -b"; fi
cmd="${cmd_base} --patches='$patches_jar' -f '$pkg_name'"
if op=$(eval "$cmd" 2>&1); then
echo "$op"
return
fi
cmd="${cmd_base} '$patches_jar' -f '$pkg_name'"
if op=$(eval "$cmd" 2>&1); then
echo "$op"
return
fi
epr "Could not list versions $cli_jar: '$op'"
return 1
}
patches_list() {
local cli_jar=$1 patches_jar=$2 pkg_name=$3 op
if ! op=$(java -jar "$cli_jar" list-patches -p "$patches_jar" --filter-package-name "$pkg_name" --versions --packages -b 2>&1); then
if ! op=$(java -jar "$cli_jar" list-patches --patches "$patches_jar" -f "$pkg_name" --with-versions --with-packages 2>&1); then
epr "Could not get patches list $cli_jar: '$op'"
return 1
fi
fi
echo "$op"
}
isoneof() { isoneof() {
local i=$1 v local i=$1 v
shift shift
@@ -261,77 +335,92 @@ isoneof() {
merge_splits() { merge_splits() {
local bundle=$1 output=$2 local bundle=$1 output=$2
pr "Merging splits" pr "Merging splits"
gh_dl "$TEMP_DIR/apkeditor.jar" "https://github.com/REAndroid/APKEditor/releases/download/V1.3.9/APKEditor-1.3.9.jar" >/dev/null || return 1 gh_dl "$TEMP_DIR/apkeditor.jar" "https://github.com/REAndroid/APKEditor/releases/download/V1.4.7/APKEditor-1.4.7.jar" >/dev/null || return 1
if ! OP=$(java -jar "$TEMP_DIR/apkeditor.jar" merge -i "${bundle}" -o "${bundle}.mzip" -clean-meta -f 2>&1); then if ! OP=$(java -jar "$TEMP_DIR/apkeditor.jar" merge -i "$bundle" -o "${output}-unsigned" -clean-meta -f 2>&1); then
epr "$OP" epr "APKEditor error: $OP"
return 1 return 1
fi fi
# this is required because of apksig # sign the merged stock apk
mkdir "${bundle}-zip" if ! OP=$(java -jar "$APKSIGNER" sign --ks ks-p12.keystore --ks-pass pass:123456789 --key-pass pass:123456789 --ks-key-alias jhc \
unzip -qo "${bundle}.mzip" -d "${bundle}-zip" --out "${output}" "${output}-unsigned"); then
pushd "${bundle}-zip" || abort epr "apksigner error: $OP"
zip -0rq "${CWD}/${bundle}.zip" . return 1
popd || abort
# if building module, sign the merged apk properly
if isoneof "module" "${build_mode_arr[@]}"; then
patch_apk "${bundle}.zip" "${output}" "--exclusive" "${args[cli]}" "${args[ptjar]}"
local ret=$?
else
cp "${bundle}.zip" "${output}"
local ret=$?
fi fi
rm -r "${bundle}-zip" "${bundle}.zip" "${bundle}.mzip" || : rm "${output}.idsig" "${output}-unsigned" 2>/dev/null || :
return $ret return 0
} }
# -------------------- apkmirror -------------------- # -------------------- apkmirror --------------------
apk_mirror_search() { apkmirror_search() {
local resp="$1" dpi="$2" arch="$3" apk_bundle="$4" local resp="$1" dpi="$2" arch="$3" apk_bundle="$4"
local apparch dlurl node app_table local dlurl="" node app_table emptyCheck
if [ "$arch" = all ]; then
apparch=(universal noarch 'arm64-v8a + armeabi-v7a') local apparch=('universal' 'noarch' 'arm64-v8a + armeabi-v7a')
else apparch=("$arch" universal noarch 'arm64-v8a + armeabi-v7a'); fi if [ "$arch" != "all" ]; then
apparch+=("$arch")
fi
local appdpi=("nodpi" "anydpi")
if [ "$dpi" ]; then
appdpi+=($dpi)
fi
for ((n = 1; n < 40; n++)); do for ((n = 1; n < 40; n++)); do
node=$($HTMLQ "div.table-row.headerFont:nth-last-child($n)" -r "span:nth-child(n+3)" <<<"$resp") node=$($HTMLQ "div.table-row.headerFont:nth-last-child($n)" -r "span:nth-child(n+3)" <<<"$resp")
if [ -z "$node" ]; then break; fi if [ -z "$node" ]; then break; fi
emptyCheck=$($HTMLQ -t -w "div.table-cell:nth-child(1) > a:nth-child(1)" <<<"$node" | xargs)
if [ -z "$emptyCheck" ]; then break; fi
app_table=$($HTMLQ --text --ignore-whitespace <<<"$node") app_table=$($HTMLQ --text --ignore-whitespace <<<"$node")
if [ "$(sed -n 3p <<<"$app_table")" = "$apk_bundle" ] && [ "$(sed -n 6p <<<"$app_table")" = "$dpi" ] && if [ "$(sed -n 3p <<<"$app_table")" != "$apk_bundle" ]; then continue; fi
dlurl=$($HTMLQ --base https://www.apkmirror.com --attribute href "div:nth-child(1) > a:nth-child(1)" <<<"$node")
if isoneof "$(sed -n 6p <<<"$app_table")" "${appdpi[@]}" &&
isoneof "$(sed -n 4p <<<"$app_table")" "${apparch[@]}"; then isoneof "$(sed -n 4p <<<"$app_table")" "${apparch[@]}"; then
dlurl=$($HTMLQ --base https://www.apkmirror.com --attribute href "div:nth-child(1) > a:nth-child(1)" <<<"$node")
echo "$dlurl" echo "$dlurl"
return 0 return 0
fi fi
done done
if [ "$n" -eq 2 ] && [ "$dlurl" ]; then
# only one apk exists, return it
echo "$dlurl"
return 0
fi
return 1 return 1
} }
dl_apkmirror() { dl_apkmirror() {
local url=$1 version=${2// /-} output=$3 arch=$4 dpi=$5 is_bundle=false local url=$1 version=${2// /-} output=$3 arch=$4 dpi=$5 is_bundle=false
if [ -f "${output}.apkm" ]; then if [ -f "${output}.apkm" ]; then
is_bundle=true merge_splits "${output}.apkm" "${output}"
else return 0
if [ "$arch" = "arm-v7a" ]; then arch="armeabi-v7a"; fi
local resp node app_table dlurl=""
url="${url}/${url##*/}-${version//./-}-release/"
resp=$(req "$url" -) || return 1
node=$($HTMLQ "div.table-row.headerFont:nth-last-child(1)" -r "span:nth-child(n+3)" <<<"$resp")
if [ "$node" ]; then
if ! dlurl=$(apk_mirror_search "$resp" "$dpi" "${arch}" "APK"); then
if ! dlurl=$(apk_mirror_search "$resp" "$dpi" "${arch}" "BUNDLE"); then
return 1
else is_bundle=true; fi
fi
[ -z "$dlurl" ] && return 1
resp=$(req "$dlurl" -)
fi
url=$(echo "$resp" | $HTMLQ --base https://www.apkmirror.com --attribute href "a.btn") || return 1
url=$(req "$url" - | $HTMLQ --base https://www.apkmirror.com --attribute href "span > a[rel = nofollow]") || return 1
fi fi
if [ "$arch" = "arm-v7a" ]; then arch="armeabi-v7a"; fi
local resp node app_table apkmname dlurl=""
apkmname=$($HTMLQ "h1.marginZero" --text <<<"$__APKMIRROR_RESP__")
apkmname="${apkmname,,}" apkmname="${apkmname// /-}" apkmname="${apkmname//[^a-z0-9-]/}"
url="${url}/${apkmname}-${version//./-}-release/"
resp=$(req "$url" -) || return 1
node=$($HTMLQ "div.table-row.headerFont:nth-last-child(1)" -r "span:nth-child(n+3)" <<<"$resp")
if [ "$node" ]; then
for type in APK BUNDLE; do
if dlurl=$(apkmirror_search "$resp" "$dpi" "$arch" "$type"); then
if [ "$type" = "BUNDLE" ]; then
is_bundle=true
else is_bundle=false; fi
break 2
fi
done
if [ -z "$dlurl" ]; then return 1; fi
resp=$(req "$dlurl" -)
fi
url=$(echo "$resp" | $HTMLQ --base https://www.apkmirror.com --attribute href "a.btn") || return 1
url=$(req "$url" - | $HTMLQ --base https://www.apkmirror.com --attribute href "span > a[rel = nofollow]") || return 1
if [ "$is_bundle" = true ]; then if [ "$is_bundle" = true ]; then
req "$url" "${output}.apkm" req "$url" "${output}.apkm" || return 1
merge_splits "${output}.apkm" "${output}" merge_splits "${output}.apkm" "${output}"
else else
req "$url" "${output}" req "$url" "${output}" || return 1
fi fi
} }
get_apkmirror_vers() { get_apkmirror_vers() {
@@ -352,47 +441,70 @@ get_apkmirror_vers() {
} }
get_apkmirror_pkg_name() { sed -n 's;.*id=\(.*\)" class="accent_color.*;\1;p' <<<"$__APKMIRROR_RESP__"; } get_apkmirror_pkg_name() { sed -n 's;.*id=\(.*\)" class="accent_color.*;\1;p' <<<"$__APKMIRROR_RESP__"; }
get_apkmirror_resp() { get_apkmirror_resp() {
__APKMIRROR_RESP__=$(req "${1}" -) __APKMIRROR_RESP__=$(req "${1}" -) || return 1
__APKMIRROR_CAT__="${1##*/}" __APKMIRROR_CAT__="${1##*/}"
} }
# -------------------- uptodown -------------------- # -------------------- uptodown --------------------
get_uptodown_resp() { get_uptodown_resp() {
__UPTODOWN_RESP__=$(req "${1}/versions" -) __UPTODOWN_RESP__=$(req "${1}/versions" -) || return 1
__UPTODOWN_RESP_PKG__=$(req "${1}/download" -) __UPTODOWN_RESP_PKG__=$(req "${1}/download" -) || return 1
} }
get_uptodown_vers() { $HTMLQ --text ".version" <<<"$__UPTODOWN_RESP__"; } get_uptodown_vers() { $HTMLQ --text ".version" <<<"$__UPTODOWN_RESP__"; }
dl_uptodown() { dl_uptodown() {
local uptodown_dlurl=$1 version=$2 output=$3 arch=$4 _dpi=$5 local uptodown_dlurl=$1 version=$2 output=$3 arch=$4 _dpi=$5
if [ "$arch" = "arm-v7a" ]; then arch="armeabi-v7a"; fi if [ "$arch" = "arm-v7a" ]; then arch="armeabi-v7a"; fi
local apparch=('arm64-v8a, armeabi-v7a, x86_64' 'arm64-v8a, armeabi-v7a, x86, x86_64' 'arm64-v8a, armeabi-v7a')
if [ "$arch" != all ]; then
apparch+=("$arch")
fi
local op resp data_code local op resp data_code
data_code=$($HTMLQ "#detail-app-name" --attribute data-code <<<"$__UPTODOWN_RESP__") data_code=$($HTMLQ "#detail-app-name" --attribute data-code <<<"$__UPTODOWN_RESP__")
local versionURL="" local versionURL=""
for i in {1..5}; do local is_bundle=false
for i in {1..20}; do
resp=$(req "${uptodown_dlurl}/apps/${data_code}/versions/${i}" -) resp=$(req "${uptodown_dlurl}/apps/${data_code}/versions/${i}" -)
if ! op=$(jq -e -r ".data | map(select(.version == \"${version}\" and .kindFile == \"apk\")) | .[0]" <<<"$resp"); then if ! op=$(jq -e -r ".data | map(select(.version == \"${version}\")) | .[0]" <<<"$resp"); then
continue continue
fi fi
if [ "$(jq -e -r ".kindFile" <<<"$op")" = "xapk" ]; then is_bundle=true; fi
if versionURL=$(jq -e -r '.versionURL' <<<"$op"); then break; else return 1; fi if versionURL=$(jq -e -r '.versionURL' <<<"$op"); then break; else return 1; fi
done done
if [ -z "$versionURL" ]; then return 1; fi if [ -z "$versionURL" ]; then return 1; fi
versionURL=$(jq -e -r '.url + "/" + .extraURL + "/" + (.versionID | tostring)' <<<"$versionURL")
resp=$(req "$versionURL" -) || return 1 resp=$(req "$versionURL" -) || return 1
if [ "$arch" != all ]; then
local data_version files node_arch data_file_id local data_version files node_arch="" data_file_id node_class
data_version=$($HTMLQ '.button.variants' --attribute data-version <<<"$resp") || return 1 data_version=$($HTMLQ '.button.variants' --attribute data-version <<<"$resp") || return 1
if [ "$data_version" ]; then
files=$(req "${uptodown_dlurl%/*}/app/${data_code}/version/${data_version}/files" - | jq -e -r .content) || return 1 files=$(req "${uptodown_dlurl%/*}/app/${data_code}/version/${data_version}/files" - | jq -e -r .content) || return 1
for ((n = 1; n < 12; n += 2)); do for ((n = 1; n < 12; n += 1)); do
node_arch=$($HTMLQ ".content > p:nth-child($n)" --text <<<"$files" | xargs) || return 1 node_class=$($HTMLQ -w -t ".content > :nth-child($n)" --attribute class <<<"$files") || return 1
if [ "$node_class" != "variant" ]; then
node_arch=$($HTMLQ -w -t ".content > :nth-child($n)" <<<"$files" | xargs) || return 1
continue
fi
if [ -z "$node_arch" ]; then return 1; fi if [ -z "$node_arch" ]; then return 1; fi
if [ "$node_arch" != "$arch" ]; then continue; fi if ! isoneof "$node_arch" "${apparch[@]}"; then continue; fi
data_file_id=$($HTMLQ "div.variant:nth-child($((n + 1))) > .v-report" --attribute data-file-id <<<"$files") || return 1
resp=$(req "${uptodown_dlurl}/download/${data_file_id}" -) file_type=$($HTMLQ -w -t ".content > :nth-child($n) > .v-file > span" <<<"$files") || return 1
if [ "$file_type" = "xapk" ]; then is_bundle=true; else is_bundle=false; fi
data_file_id=$($HTMLQ ".content > :nth-child($n) > .v-report" --attribute data-file-id <<<"$files") || return 1
resp=$(req "${uptodown_dlurl}/download/${data_file_id}-x" -)
break break
done done
if [ $n -eq 12 ]; then return 1; fi
fi fi
local data_url local data_url
data_url=$($HTMLQ "#detail-download-button" --attribute data-url <<<"$resp") || return 1 data_url=$($HTMLQ "#detail-download-button" --attribute data-url <<<"$resp") || return 1
req "https://dw.uptodown.com/dwn/${data_url}" "$output" if [ $is_bundle = true ]; then
req "https://dw.uptodown.com/dwn/${data_url}" "$output.apkm" || return 1
merge_splits "${output}.apkm" "${output}"
else
req "https://dw.uptodown.com/dwn/${data_url}" "$output"
fi
} }
get_uptodown_pkg_name() { $HTMLQ --text "tr.full:nth-child(1) > td:nth-child(3)" <<<"$__UPTODOWN_RESP_PKG__"; } get_uptodown_pkg_name() { $HTMLQ --text "tr.full:nth-child(1) > td:nth-child(3)" <<<"$__UPTODOWN_RESP_PKG__"; }
@@ -400,8 +512,19 @@ get_uptodown_pkg_name() { $HTMLQ --text "tr.full:nth-child(1) > td:nth-child(3)"
dl_archive() { dl_archive() {
local url=$1 version=$2 output=$3 arch=$4 local url=$1 version=$2 output=$3 arch=$4
local path version=${version// /} local path version=${version// /}
path=$(grep "${version_f#v}-${arch// /}" <<<"$__ARCHIVE_RESP__") || return 1
req "${url}/${path}" "$output" if [ -f "${output}.apkm" ]; then
merge_splits "${output}.apkm" "$output"
return 0
fi
path=$(grep -m1 "${version_f#v}-${arch// /}" <<<"$__ARCHIVE_RESP__") || return 1
if [ "${path##*.}" = "apkm" ]; then
req "${url}/${path}" "${output}.apkm" || return 1
merge_splits "${output}.apkm" "$output"
else
req "${url}/${path}" "${output}" || return 1
fi
} }
get_archive_resp() { get_archive_resp() {
local r local r
@@ -411,13 +534,40 @@ get_archive_resp() {
} }
get_archive_vers() { sed 's/^[^-]*-//;s/-\(all\|arm64-v8a\|arm-v7a\)\.apk//g' <<<"$__ARCHIVE_RESP__"; } get_archive_vers() { sed 's/^[^-]*-//;s/-\(all\|arm64-v8a\|arm-v7a\)\.apk//g' <<<"$__ARCHIVE_RESP__"; }
get_archive_pkg_name() { echo "$__ARCHIVE_PKG_NAME__"; } get_archive_pkg_name() { echo "$__ARCHIVE_PKG_NAME__"; }
# -------------------- direct --------------------
dl_direct() {
local url=$1 version=${2// /-} output=$3 arch=$4 _dpi=$5
if ! grep -q "${version_f#v}-${arch// /}" <<<"$url"; then
epr "Given direct-dlurl for $output is not compatible. Set proper 'arch' and 'version' options."
return 1
fi
if [ "${url##*.}" = "apkm" ]; then
req "$url" "${output}.apkm" || return 1
merge_splits "${output}.apkm" "$output"
else
req "$url" "${output}" || return 1
fi
}
get_direct_vers() { cut -d- -f2 <<<"$__DIRECT_APKNAME__"; }
get_direct_pkg_name() { cut -d- -f1 <<<"$__DIRECT_APKNAME__"; }
get_direct_resp() { __DIRECT_APKNAME__=$(awk -F/ '{print $NF}' <<<"$1"); }
# -------------------------------------------------- # --------------------------------------------------
patch_apk() { patch_apk() {
local stock_input=$1 patched_apk=$2 patcher_args=$3 rv_cli_jar=$4 rv_patches_jar=$5 local stock_input=$1 patched_apk=$2 patcher_args=$3 cli_jar=$4 patches_jar=$5
local cmd="env -u GITHUB_REPOSITORY java -jar $rv_cli_jar patch $stock_input --purge -o $patched_apk -p $rv_patches_jar --keystore=ks.keystore \ local tmp_files
--keystore-entry-password=123456789 --keystore-password=123456789 --signer=jhc --keystore-entry-alias=jhc $patcher_args" tmp_files="$(pwd)/$(mktemp -d -p "$TEMP_DIR")"
if [ "$OS" = Android ]; then cmd+=" --custom-aapt2-binary=${AAPT2}"; fi
local cmd="java -jar '$cli_jar' patch '$stock_input' -o '$patched_apk' -p '$patches_jar' --keystore=ks.keystore \
--keystore-entry-password=123456789 --keystore-password=123456789 --signer=jhc --keystore-entry-alias=jhc -t '$tmp_files' $patcher_args"
# TODO: remove this later
local cli_name
cli_name=$(basename "$cli_jar")
if [ "${cli_name::8}" = revanced ]; then cmd+=" -b"; fi
if [ "$OS" = Android ]; then cmd+=" --custom-aapt2-binary='${AAPT2}'"; fi
pr "$cmd" pr "$cmd"
if eval "$cmd"; then [ -f "$patched_apk" ]; else if eval "$cmd"; then [ -f "$patched_apk" ]; else
rm "$patched_apk" 2>/dev/null || : rm "$patched_apk" 2>/dev/null || :
@@ -430,6 +580,7 @@ check_sig() {
local sig local sig
if grep -q "$pkg_name" sig.txt; then if grep -q "$pkg_name" sig.txt; then
sig=$(java -jar "$APKSIGNER" verify --print-certs "$file" | grep ^Signer | grep SHA-256 | tail -1 | awk '{print $NF}') sig=$(java -jar "$APKSIGNER" verify --print-certs "$file" | grep ^Signer | grep SHA-256 | tail -1 | awk '{print $NF}')
echo "$pkg_name signature: ${sig}"
grep -qFx "$sig $pkg_name" sig.txt grep -qFx "$sig $pkg_name" sig.txt
fi fi
} }
@@ -452,29 +603,35 @@ build_rv() {
[ "${args[exclusive_patches]}" = true ] && p_patcher_args+=("--exclusive") [ "${args[exclusive_patches]}" = true ] && p_patcher_args+=("--exclusive")
local tried_dl=() local tried_dl=()
for dl_p in archive apkmirror uptodown; do if [ "${args[pkg_name]}" ]; then
if [ -z "${args[${dl_p}_dlurl]}" ]; then continue; fi pkg_name="${args[pkg_name]}"
if ! get_${dl_p}_resp "${args[${dl_p}_dlurl]}" || ! pkg_name=$(get_"${dl_p}"_pkg_name); then else
args[${dl_p}_dlurl]="" for dl_p in "${DL_SRCS[@]}"; do
epr "ERROR: Could not find ${table} in ${dl_p}" if [ -z "${args[${dl_p}_dlurl]}" ]; then continue; fi
continue if ! get_${dl_p}_resp "${args[${dl_p}_dlurl]}" || ! pkg_name=$(get_"${dl_p}"_pkg_name); then
fi args[${dl_p}_dlurl]=""
tried_dl+=("$dl_p") epr "ERROR: Could not find ${table} in ${dl_p}"
dl_from=$dl_p continue
break fi
done tried_dl+=("$dl_p")
dl_from=$dl_p
break
done
fi
if [ -z "$pkg_name" ]; then if [ -z "$pkg_name" ]; then
epr "empty pkg name, not building ${table}." epr "empty pkg name, not building ${table}."
return 0 return 0
fi fi
pr "Package name of '${table}' is '$pkg_name'"
local list_patches local list_patches
list_patches=$(java -jar "$rv_cli_jar" list-patches "$rv_patches_jar" -f "$pkg_name" -v -p 2>&1) list_patches=$(patches_list "$cli_jar" "$patches_jar" "$pkg_name") || return 1
local get_latest_ver=false local get_latest_ver=false
if [ "$version_mode" = auto ]; then if [ "$version_mode" = auto ]; then
if ! version=$(get_patch_last_supported_ver "$list_patches" "$pkg_name" \ if ! version=$(get_patch_last_supported_ver "$list_patches" "$pkg_name" \
"${args[included_patches]}" "${args[excluded_patches]}" "${args[exclusive_patches]}"); then "${args[included_patches]}" "${args[excluded_patches]}" "${args[exclusive_patches]}"); then
exit 1 epr "get_patch_last_supported_ver failed '$list_patches'"
return
elif [ -z "$version" ]; then get_latest_ver=true; fi elif [ -z "$version" ]; then get_latest_ver=true; fi
elif isoneof "$version_mode" latest beta; then elif isoneof "$version_mode" latest beta; then
get_latest_ver=true get_latest_ver=true
@@ -506,35 +663,52 @@ build_rv() {
version_f=${version_f#v} version_f=${version_f#v}
local stock_apk="${TEMP_DIR}/${pkg_name}-${version_f}-${arch_f}.apk" local stock_apk="${TEMP_DIR}/${pkg_name}-${version_f}-${arch_f}.apk"
if [ ! -f "$stock_apk" ]; then if [ ! -f "$stock_apk" ]; then
for dl_p in archive apkmirror uptodown; do for dl_p in "${DL_SRCS[@]}"; do
if [ -z "${args[${dl_p}_dlurl]}" ]; then continue; fi if [ -z "${args[${dl_p}_dlurl]}" ]; then continue; fi
pr "Downloading '${table}' from ${dl_p}" pr "Downloading '${table}' from '${dl_p}'"
if ! isoneof $dl_p "${tried_dl[@]}"; then get_${dl_p}_resp "${args[${dl_p}_dlurl]}"; fi if ! isoneof $dl_p "${tried_dl[@]}"; then
if ! get_${dl_p}_resp "${args[${dl_p}_dlurl]}"; then
epr "ERROR: Could not get '${table}' from '${dl_p}'"
continue
fi
fi
if ! dl_${dl_p} "${args[${dl_p}_dlurl]}" "$version" "$stock_apk" "$arch" "${args[dpi]}" "$get_latest_ver"; then if ! dl_${dl_p} "${args[${dl_p}_dlurl]}" "$version" "$stock_apk" "$arch" "${args[dpi]}" "$get_latest_ver"; then
epr "ERROR: Could not download '${table}' from ${dl_p} with version '${version}', arch '${arch}', dpi '${args[dpi]}'" epr "ERROR: Could not download '${table}' from '${dl_p}' with version '${version}', arch '${arch}', dpi '${args[dpi]}'"
continue continue
fi fi
break break
done done
if [ ! -f "$stock_apk" ]; then return 0; fi if [ ! -f "$stock_apk" ]; then
epr "Stock apk not found ($stock_apk)"
return 0
fi
fi fi
if ! check_sig "$stock_apk" "$pkg_name"; then
abort "apk signature mismatch '$stock_apk'" local sig_op
if [ -f "${stock_apk}.apkm" ]; then
rm -rf "${stock_apk}-zip" || :
unzip -j "${stock_apk}.apkm" -d "${stock_apk}-zip" >/dev/null
for a in "${stock_apk}"-zip/*.apk; do
if ! sig_op=$(check_sig "$a" "$pkg_name" 2>&1); then
epr "Not building $table, apk signature mismatch '$a': $sig_op"
return 0
fi
done
rm -rf "${stock_apk}-zip" || :
else
if ! sig_op=$(check_sig "$stock_apk" "$pkg_name" 2>&1); then
epr "Not building $table, apk signature mismatch '$stock_apk': $sig_op"
return 0
fi
fi fi
log "${table}: ${version}" log "${table}: ${version}"
local microg_patch local microg_patch
microg_patch=$(grep "^Name: " <<<"$list_patches" | grep -i "gmscore\|microg" || :) microg_patch=${microg_patch#*: } microg_patch=$(grep "^Name: " <<<"$list_patches" | grep -i "gmscore\|microg" || :) microg_patch=${microg_patch#*: }
if [ -n "$microg_patch" ] && [[ ${p_patcher_args[*]} =~ $microg_patch ]]; then if [ -n "$microg_patch" ] && [[ ${p_patcher_args[*]} =~ $microg_patch ]]; then
epr "You cant include/exclude microg patch as that's done by rvmm builder automatically." wpr "You cant include/exclude microg patch as that's done by rvmm builder automatically."
p_patcher_args=("${p_patcher_args[@]//-[ei] ${microg_patch}/}") p_patcher_args=("${p_patcher_args[@]//-[ei] ${microg_patch}/}")
fi fi
local spoof_streams_patch
spoof_streams_patch=$(grep "^Name: " <<<"$list_patches" | grep -i "spoof" | grep -i "streams" || :) spoof_streams_patch=${spoof_streams_patch#*: }
if [ -n "$spoof_streams_patch" ] && [[ ${p_patcher_args[*]} =~ $spoof_streams_patch ]]; then
epr "You cant include/exclude spoof stream patch as that's done by rvmm builder automatically."
p_patcher_args=("${p_patcher_args[@]//-[ei] ${spoof_streams_patch}/}")
fi
local patcher_args patched_apk build_mode local patcher_args patched_apk build_mode
local rv_brand_f=${args[rv_brand],,} local rv_brand_f=${args[rv_brand],,}
@@ -543,7 +717,7 @@ build_rv() {
for build_mode in "${build_mode_arr[@]}"; do for build_mode in "${build_mode_arr[@]}"; do
patcher_args=("${p_patcher_args[@]}") patcher_args=("${p_patcher_args[@]}")
pr "Building '${table}' in '$build_mode' mode" pr "Building '${table}' in '$build_mode' mode"
if [ -n "$microg_patch" ] || [ -n "$spoof_streams_patch" ]; then if [ -n "$microg_patch" ]; then
patched_apk="${TEMP_DIR}/${app_name_l}-${rv_brand_f}-${version_f}-${arch_f}-${build_mode}.apk" patched_apk="${TEMP_DIR}/${app_name_l}-${rv_brand_f}-${version_f}-${arch_f}-${build_mode}.apk"
else else
patched_apk="${TEMP_DIR}/${app_name_l}-${rv_brand_f}-${version_f}-${arch_f}.apk" patched_apk="${TEMP_DIR}/${app_name_l}-${rv_brand_f}-${version_f}-${arch_f}.apk"
@@ -555,34 +729,39 @@ build_rv() {
patcher_args+=("-d \"${microg_patch}\"") patcher_args+=("-d \"${microg_patch}\"")
fi fi
fi fi
if [ -n "$spoof_streams_patch" ]; then
if [ "$build_mode" = apk ]; then local stock_apk_to_patch="${stock_apk}.stripped.apk"
patcher_args+=("-e \"${spoof_streams_patch}\"") cp -f "$stock_apk" "$stock_apk_to_patch"
elif [ "$build_mode" = module ]; then if [ "$build_mode" = module ]; then
patcher_args+=("-d \"${spoof_streams_patch}\"") zip -d "$stock_apk_to_patch" "lib/*" >/dev/null 2>&1 || :
fi else
fi if [ "$arch" = "arm64-v8a" ]; then
if [ "${args[riplib]}" = true ]; then zip -d "$stock_apk_to_patch" "lib/armeabi-v7a/*" "lib/x86_64/*" "lib/x86/*" >/dev/null 2>&1 || :
patcher_args+=("--rip-lib x86_64 --rip-lib x86") elif [ "$arch" = "arm-v7a" ]; then
if [ "$build_mode" = module ]; then zip -d "$stock_apk_to_patch" "lib/arm64-v8a/*" "lib/x86_64/*" "lib/x86/*" >/dev/null 2>&1 || :
patcher_args+=("--rip-lib arm64-v8a --rip-lib armeabi-v7a --unsigned") elif [ "$arch" = "x86" ]; then
zip -d "$stock_apk_to_patch" "lib/arm64-v8a/*" "lib/x86_64/*" "lib/armeabi-v7a/*" >/dev/null 2>&1 || :
elif [ "$arch" = "x86_64" ]; then
zip -d "$stock_apk_to_patch" "lib/arm64-v8a/*" "lib/armeabi-v7a/*" "lib/x86/*" >/dev/null 2>&1 || :
else else
if [ "$arch" = "arm64-v8a" ]; then zip -d "$stock_apk_to_patch" "lib/x86_64/*" "lib/x86/*" >/dev/null 2>&1 || :
patcher_args+=("--rip-lib armeabi-v7a")
elif [ "$arch" = "arm-v7a" ]; then
patcher_args+=("--rip-lib arm64-v8a")
fi
fi fi
fi fi
if [ "${NORB:-}" != true ] || [ ! -f "$patched_apk" ]; then
if ! patch_apk "$stock_apk" "$patched_apk" "${patcher_args[*]}" "${args[cli]}" "${args[ptjar]}"; then local apk_output="${BUILD_DIR}/${app_name_l}-${rv_brand_f}-v${version_f}-${arch_f}.apk"
if [ "${NORB:-}" != true ] || { [ ! -f "$patched_apk" ] && [ ! -f "$apk_output" ]; }; then
if ! patch_apk "$stock_apk_to_patch" "$patched_apk" "${patcher_args[*]}" "${args[cli]}" "${args[ptjar]}"; then
epr "Building '${table}' failed!" epr "Building '${table}' failed!"
return 0 return 0
fi fi
fi fi
rm "$stock_apk_to_patch"
if [ "$build_mode" = apk ]; then if [ "$build_mode" = apk ]; then
local apk_output="${BUILD_DIR}/${app_name_l}-${rv_brand_f}-v${version_f}-${arch_f}.apk" if [ "${NORB:-}" != true ] || { [ ! -f "$patched_apk" ] && [ ! -f "$apk_output" ]; }; then
mv -f "$patched_apk" "$apk_output" mv -f "$patched_apk" "$apk_output"
else
cp -f "$patched_apk" "$apk_output"
fi
pr "Built ${table} (non-root): '${apk_output}'" pr "Built ${table} (non-root): '${apk_output}'"
continue continue
fi fi
@@ -592,18 +771,43 @@ build_rv() {
local upj="${table,,}-update.json" local upj="${table,,}-update.json"
module_config "$base_template" "$pkg_name" "$version" "$arch" module_config "$base_template" "$pkg_name" "$version" "$arch"
local patches_ver="${patches_jar##*-}"
module_prop \ module_prop \
"${args[module_prop_name]}" \ "${args[module_prop_name]}" \
"${app_name} ${args[rv_brand]}" \ "${app_name} ${args[rv_brand]}" \
"$version" \ "${version} (patches ${patches_ver})" \
"${app_name} ${args[rv_brand]} Magisk module" \ "${app_name} ${args[rv_brand]} module" \
"https://raw.githubusercontent.com/${GITHUB_REPOSITORY-}/update/${upj}" \ "https://raw.githubusercontent.com/${GITHUB_REPOSITORY-}/update/${upj}" \
"$base_template" "$base_template"
local module_output="${app_name_l}-${rv_brand_f}-magisk-v${version_f}-${arch_f}.zip" local module_output="${app_name_l}-${rv_brand_f}-module-v${version_f}-${arch_f}.zip"
pr "Packing module ${table}" pr "Packing module ${table}"
cp -f "$patched_apk" "${base_template}/base.apk" cp -f "$patched_apk" "${base_template}/base.apk"
if [ "${args[include_stock]}" = true ]; then cp -f "$stock_apk" "${base_template}/${pkg_name}.apk"; fi
if [ "${args[include_stock]}" != "disable" ]; then
mkdir -p "${base_template}/stock/"
if [ "${args[include_stock]}" = "merged" ]; then
cp -f "$stock_apk" "${base_template}/stock/base.apk"
elif [ "${args[include_stock]}" = "split" ]; then
if [ ! -f "${stock_apk}.apkm" ]; then
epr "Cannot include as 'split' because stock apk of $table_name is not a bundle"
return 0
fi
if [ "$arch" = "arm64-v8a" ]; then
unzip -j "${stock_apk}.apkm" '*.apk' -x '*x86_64.apk' -x '*x86.apk' -x '*armeabi_v7a.apk' -d "${base_template}/stock/" >/dev/null 2>&1
elif [ "$arch" = "arm-v7a" ]; then
unzip -j "${stock_apk}.apkm" '*.apk' -x '*x86_64.apk' -x '*x86.apk' -x '*arm64_v8a.apk' -d "${base_template}/stock/" >/dev/null 2>&1
elif [ "$arch" = "x86" ]; then
unzip -j "${stock_apk}.apkm" '*.apk' -x '*x86_64.apk' -x '*arm64_v8a.apk' -x '*armeabi_v7a.apk' -d "${base_template}/stock/" >/dev/null 2>&1
elif [ "$arch" = "x86_64" ]; then
unzip -j "${stock_apk}.apkm" '*.apk' -x '*x86.apk' -x '*arm64_v8a.apk' -x '*armeabi_v7a.apk' -d "${base_template}/stock/" >/dev/null 2>&1
else
unzip -j "${stock_apk}.apkm" '*.apk' -x '*x86_64.apk' -x '*x86.apk' -d "${base_template}/stock/" >/dev/null 2>&1
fi
fi
fi
pushd >/dev/null "$base_template" || abort "Module template dir not found" pushd >/dev/null "$base_template" || abort "Module template dir not found"
zip -"$COMPRESSION_LEVEL" -FSqr "${CWD}/${BUILD_DIR}/${module_output}" . zip -"$COMPRESSION_LEVEL" -FSqr "${CWD}/${BUILD_DIR}/${module_output}" .
popd >/dev/null || : popd >/dev/null || :
@@ -628,10 +832,10 @@ MODULE_ARCH=$ma" >"$1/config"
module_prop() { module_prop() {
echo "id=${1} echo "id=${1}
name=${2} name=${2}
version=v${3} (${NEXT_VER_CODE}) version=v${3}
versionCode=${NEXT_VER_CODE} versionCode=${NEXT_VER_CODE}
author=j-hc author=j-hc
description=${4}" >"${6}/module.prop" description=${4}" >"${6}/module.prop"
if [ "$ENABLE_MAGISK_UPDATE" = true ]; then echo "updateJson=${5}" >>"${6}/module.prop"; fi if [ "$ENABLE_MODULE_UPDATE" = true ]; then echo "updateJson=${5}" >>"${6}/module.prop"; fi
} }