Last active
May 20, 2023 18:16
-
-
Save chsbuffer/a0584f837f36f2a0da613df419f7a41b to your computer and use it in GitHub Desktop.
Revanced script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Revanced Script # | |
Download and Patch Youtube and Youtube Music with latest Revanced assets | |
prerequisite: | |
Python ^3.8 in PATH | |
JRE 17+ in PATH | |
python-requests ^2.28.1 | |
python-bs4 / beautifulsoup4 ^4.11.1 | |
usage: | |
$ python revanced-script.py | |
note: | |
Patched apk goes to $HOME/Downloads, or the script's directory if Downloads doesn't exist. | |
Working directory at $TEMP/revanced-script. | |
Put exist keystore next to the script to sign with it, otherwise go to working directory to gather the generated keystore. | |
Revanced assets are only updated once a day to avoid GitHub API rate limits. | |
termux usage: | |
1. $ pkg in openjdk-17 python; pip install requests beautifulsoup4 | |
2. download https://github.com/revanced/revanced-manager/raw/main/android/app/src/main/jniLibs/arm64-v8a/libaapt2.so | |
move to the scripts directory and rename to 'aapt2' | |
4. $ chmod +x aapt2 | |
5. $ python revanced-script.py | |
todo: | |
get target Youtube version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import requests | |
import json | |
from bs4 import BeautifulSoup | |
import logging | |
from pathlib import Path | |
from datetime import datetime | |
import subprocess | |
import tempfile | |
import itertools | |
logging.basicConfig(level=logging.DEBUG) | |
def download_url(url, output, **kwargs): | |
resp = requests.get(url, **kwargs) | |
resp.raise_for_status() | |
with open(output, "wb") as f: | |
f.write(resp.content) | |
def download_github_asset(owner, repo, filename, output, prerelease=False): | |
url = f"https://api.github.com/repos/{owner}/{repo}/releases" | |
if not prerelease: | |
url += "/latest" | |
resp = requests.get(url) | |
data = json.loads(resp.text) | |
releases = [data] | |
if prerelease: | |
releases = data | |
for release in releases: | |
if prerelease and not release["prerelease"]: | |
continue | |
for asset in release["assets"]: | |
if asset["name"].startswith(filename): | |
url = asset["browser_download_url"] | |
break | |
break | |
download_url(url, output) | |
def download_apkmirror_apk(url, output, override=False): | |
logging.debug(f"{download_apkmirror_apk.__name__}: ({url}, {output}, {override})") | |
if not override and os.path.isfile(output): | |
return | |
apkmirror = "https://www.apkmirror.com" | |
headers = { | |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36" | |
} | |
resp = requests.get(url, headers=headers) | |
resp.raise_for_status() | |
dom = BeautifulSoup(resp.text, features="html.parser") | |
jump = dom.select_one(".downloadButton")["href"] # type: ignore | |
jump = f"{apkmirror}{jump}" | |
# | |
resp = requests.get(jump, headers=headers) | |
resp.raise_for_status() | |
dom = BeautifulSoup(resp.text, features="html.parser") | |
download = dom.select_one("a[rel=nofollow]")["href"] # type: ignore | |
download = f"{apkmirror}{download}" | |
# | |
download_url(download, output, **{"headers": headers}) | |
class ApkMirrorUpdater: | |
def __init__(self) -> None: | |
self.baseUrl = "https://www.apkmirror.com" | |
self.appExists = "/wp-json/apkm/v1/app_exists/" | |
self.user = "api-apkupdater" | |
self.token = "rm5rcfruUjKy04sMpyMPJXW8" | |
self.userAgent = "APKUpdater-v" + "2.0.5" | |
def post(self, apps): | |
from requests.auth import HTTPBasicAuth | |
import requests | |
url = f"{self.baseUrl}{self.appExists}" | |
headers = {"User-Agent": self.userAgent} | |
resp = requests.post( | |
url, | |
auth=HTTPBasicAuth(self.user, self.token), | |
headers=headers, | |
json={"pnames": apps, "exclude": ["alpha", "beta"]}, | |
) | |
resp.raise_for_status() | |
return resp.json() | |
def revanced_patch(apk, out, integration=False, exclude=None): | |
if exclude is None: | |
exclude = [] | |
keystore = list(pwd.glob("*.keystore")) | |
args = ( | |
["java", "-jar", work_dir / "revanced-cli.jar"] | |
+ ["--clean"] | |
+ ["--bundle", patches] | |
+ (["--merge", integrations] if integration else []) | |
+ (["--keystore", keystore[0]] if keystore else []) | |
+ ["--apk", apk] | |
+ ["--out", out] | |
+ list(itertools.chain(*[("--exclude", x) for x in exclude])) | |
+ (["--custom-aapt2-binary", "aapt2"] if os.getenv("TERMUX_VERSION") else []) | |
) | |
logging.debug(f"execute: {' '.join([str(x) for x in args])}") | |
subprocess.call(args) | |
def yt(ver): | |
apk = work_dir / f"youtube-{ver}.apk" | |
out = out_dir / f"revanced-{ver}.apk" | |
logging.info("Downloading Youtube") | |
_ytVer = ver.replace(".", "-") | |
download_apkmirror_apk( | |
f"https://www.apkmirror.com/apk/google-inc/youtube/youtube-{_ytVer}-release/youtube-{_ytVer}-android-apk-download/", | |
apk, | |
) | |
logging.info("Patching Youtube") | |
revanced_patch(apk, out, integration=True) | |
def yt_music(ver=None): | |
url = None | |
if ver: | |
_ver = ver.replace(".", "-") | |
url = f"https://www.apkmirror.com/apk/google-inc/youtube-music/youtube-music-{_ver}-release/youtube-music-{_ver}-4-android-apk-download/" | |
else: | |
logging.info("Get latest YT Music") | |
updater = ApkMirrorUpdater() | |
data = updater.post(["com.google.android.apps.youtube.music"])["data"] | |
if not data: | |
raise Exception("No YT Music APK found on ApkMirror") | |
data = data[0] | |
ver = data["release"]["version"] | |
logging.info(f"Found YT Music {ver}") | |
for x in data["apks"]: | |
if "arm64-v8a" in x["arches"]: | |
url = updater.baseUrl + x["link"] | |
break | |
apk = work_dir / f"ytmusic-{ver}.apk" | |
patched = out_dir / f"revanced-music-{ver}.apk" | |
logging.info("Download YT Music") | |
download_apkmirror_apk(url, apk) | |
logging.info("Patching YT Music") | |
revanced_patch(apk, patched) | |
# Get the path of the current working directory | |
pwd = Path(os.path.dirname(os.path.abspath(__file__))) | |
work_dir = Path(tempfile.gettempdir()) / f"revanced-script" | |
work_dir.mkdir(parents=False, exist_ok=True) | |
os.chdir(work_dir) | |
logging.info(f"work_dir: {work_dir}") | |
out_dir = Path.home() / "Downloads" | |
out_dir = out_dir if out_dir.exists() else pwd | |
logging.info(f"ouput_dir: {out_dir}") | |
cli = work_dir / "revanced-cli.jar" | |
patches = work_dir / "revanced-patches.jar" | |
integrations = work_dir / "revanced-integrations.jar" | |
if not os.path.isfile(patches) or datetime.fromtimestamp(os.path.getmtime(patches)).date() != datetime.today().date(): | |
logging.info("update revanced") | |
download_github_asset("revanced", "revanced-cli", "revanced-cli", cli) | |
download_github_asset("revanced", "revanced-patches", "revanced-patches", patches, prerelease=True) | |
download_github_asset("revanced", "revanced-integrations", "revanced-integrations", integrations, prerelease=True) | |
yt("18.08.37") | |
yt_music() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment