From 7bf4eccc6a4d00a659dd58f098680b57ff99429d Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Tue, 8 Aug 2023 23:33:09 -0500 Subject: [PATCH 01/17] new: Downloading works --- .gitignore | 3 ++ APKPure_dl.py | 102 +++++++++++++++++++++++++++++++++++++++ ReVancedBuilder.py | 117 +++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 ++ 4 files changed, 226 insertions(+) create mode 100644 APKPure_dl.py create mode 100755 ReVancedBuilder.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 096edb2..2228d0b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ build/ .editorconfig patches.txt .vscode/ +.directory +.venv/ +__pycache__/ diff --git a/APKPure_dl.py b/APKPure_dl.py new file mode 100644 index 0000000..590b74f --- /dev/null +++ b/APKPure_dl.py @@ -0,0 +1,102 @@ +import sys +import json +from packaging.version import Version +import requests as req +from bs4 import BeautifulSoup as bs + +# Determine the best version available to download +def apkpure_best_match(apk, appname, version, session): + res = session.get(f"https://apkpure.com/{appname}/{apk}/versions") + res.raise_for_status() + data = bs(res.text, 'html.parser') + try: + vers_list = [Version(x['data-dt-version']) for x in data.css.select(f"a[data-dt-apkid^=\"b/APK/\"]")] + except: + sys.exit(f" There was some error getting list of versions of {apk}...") + + if version != '0': + vers_list = filter(lambda x: x <= Version(version), vers_list) + + return max(vers_list) + +# Download an apk from APKPure.com +def apkpure_dl(apk, appname, version, hard_version, session, present_vers): + if not hard_version: + version = apkpure_best_match(apk, appname, version, session) + + try: + if present_vers[apk] == version: + print(f"Recommended version {version} of {apk} is already present.") + return + except KeyError: + pass + print(f" Downloading {apk} version {version}...") + + # Get the version code + res = session.get(f"https://apkpure.com/{appname}/{apk}/versions") + res.raise_for_status() + data = bs(res.text, 'html.parser') + try: + ver_code = data.css.select(f"a[data-dt-version=\"{version}\"][data-dt-apkid^=\"b/APK/\"]")[0]['data-dt-versioncode'] + except: + sys.exit(f" There was some error while downloading {apk}...") + + res = session.get(f"https://d.apkpure.com/b/APK/{apk}?versionCode={ver_code}", stream=True) + res.raise_for_status() + with open(apk, 'wb') as f: + for chunk in res.iter_content(chunk_size=8192): + f.write(chunk) + print(" Done!") + + + +# Download apk files, if needed +def get_apks(present_vers, build_config): + print('Downloading required apk files from APKPure...') + + # Get latest patches using the ReVanced API + try: + patches = req.get('https://releases.revanced.app/patches').json() + except req.exceptions.RequestException as e: + sys.exit(e) + + session = req.Session() + session.headers.update({'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/116.0'}) + + for app in build_config: + # Check if we need to build an app + if not build_config[app].getboolean('build'): + continue + print(f"Checking {app}...") + + try: + apk = build_config[app]['apk'] + apkpure_appname = build_config[app]['apkpure_appname'] + except: + sys.exit(f"Invalid config for {app} in build_config.toml!") + + try: + required_ver = build_config[app]['version'] + required_ver[0] + hard_version = True + print(f"Using version {required_ver} of {app} from ") + except: + hard_version = False + compatible_vers = [] + for patch in patches: + for pkg in patch['compatiblePackages']: + if pkg['name'] == apk: + try: + compatible_vers.append(pkg['versions'][-1]) + except IndexError: + pass + + if not compatible_vers: + required_ver = Version('0') + else: + required_ver = min(map(lambda x: Version(x), compatible_vers)) + + apkpure_dl(apk, apkpure_appname, str(required_ver), hard_version, session, present_vers) + + present_vers.update({apk: str(required_ver)}) + return present_vers \ No newline at end of file diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py new file mode 100755 index 0000000..ab96b93 --- /dev/null +++ b/ReVancedBuilder.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 + +import sys +import os +import configparser as cp +import requests as req +import json +from packaging.version import Version +from APKPure_dl import * + +# Update the ReVanced tools, if needed +def update_tools(): + for item in ['revanced-cli', 'revanced-integrations', 'revanced-patches']: + *_, tool = filter(lambda x: x['repository'] == 'revanced/'+item, tools) # Get the last result + latest_ver = Version(tool['version']) + + try: + present_ver = Version(present_vers[item]) + except KeyError: + present_ver = Version('0') + + if present_ver < latest_ver: + global up_to_date + up_to_date = False + print(f"{item} has an update ({str(present_ver)} -> {str(latest_ver)})") + output_file = item.split('-')[1]+os.path.splitext(tool['name'])[1] + if flag != 'checkonly': + print(f"Downloading {output_file}...") + res = req.get(tool['browser_download_url'], stream=True) + res.raise_for_status() + with open(output_file, 'wb') as f: + for chunk in res.iter_content(chunk_size=8192): + f.write(chunk) + present_vers.update({item: str(latest_ver)}) + print("Done!") + +# Update microG, if needed +def update_microg(): + try: + data = req.get('https://api.github.com/repos/inotia00/VancedMicroG/releases/latest').json()['tag_name'] + latest_ver = Version(data) + except req.exceptions.RequestException as e: + sys.exit(e) + + try: + present_ver = Version(present_vers['VancedMicroG']) + except KeyError: + present_ver = Version('0') + + if present_ver < latest_ver: + global up_to_date + up_to_date = False + print(f"Vanced microG has an update ({str(present_ver)} -> {str(latest_ver)})") + if flag != 'checkonly': + print(f"Downloading microg.apk...") + res = req.get('https://github.com/inotia00/VancedMicroG/releases/latest/download/microg.apk', stream=True) + res.raise_for_status() + with open('microg.apk', 'wb') as f: + for chunk in res.iter_content(chunk_size=8192): + f.write(chunk) + present_vers.update({'VancedMicroG': str(latest_ver)}) + print("Done!") + +# Read configs +try: + os.chdir(sys.argv[1]) +except IndexError: + sys.exit('Please provide a working directory as argument!') +except FileNotFoundError: + sys.exit('Invalid working directory provided!') + +try: + flag = sys.argv[2] +except: + flag = None + +try: + build_config=cp.ConfigParser() + build_config.read_file(open('build_config.toml', 'r')) +except FileNotFoundError: + sys.exit('No build config provided, exiting. Please look at the GitHub page for more information:\n https://github.com/SinTan1729/ReVancedBuilder') + +notification_config = cp.ConfigParser() +notification_config.read('notification_config.toml') + +# Pull the latest information using the ReVanced API +try: + tools = req.get('https://releases.revanced.app/tools').json()['tools'] +except req.exceptions.RequestException as e: + sys.exit(e) + +global present_vers +try: + with open('versions.json', 'r') as f: + present_vers = json.load(f) +except: + # We'll treat empty as 0 later + present_vers = json.loads('{}') + +global up_to_date +up_to_date = True + +if flag != 'buildonly': + update_tools() + update_microg() + # if not up_to_date: + present_vers = get_apks(present_vers, build_config) + +# if (flag != 'checkonly' and not up_to_date) or flag == 'force': +# build_apps() + +# Update version numbers in the versions.json file +if up_to_date: + print('There\'s nothing to do.') +elif flag != 'checkonly': + with open('versions.json', 'w') as f: + json.dump(present_vers, f, indent=4) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d8c6174 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +requests +semver +packaging +bs4 \ No newline at end of file From 4c29f61e39a4abbbea4d24f1c50845286052cb59 Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Wed, 9 Aug 2023 02:17:29 -0500 Subject: [PATCH 02/17] new: Build works (mostly) --- APKPure_dl.py | 38 ++++++++++++---------- JAVABuilder.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++ ReVancedBuilder.py | 29 +++++++++++------ 3 files changed, 118 insertions(+), 27 deletions(-) create mode 100644 JAVABuilder.py diff --git a/APKPure_dl.py b/APKPure_dl.py index 590b74f..ba44ebb 100644 --- a/APKPure_dl.py +++ b/APKPure_dl.py @@ -1,3 +1,4 @@ +import os import sys import json from packaging.version import Version @@ -5,27 +6,32 @@ import requests as req from bs4 import BeautifulSoup as bs # Determine the best version available to download -def apkpure_best_match(apk, appname, version, session): - res = session.get(f"https://apkpure.com/{appname}/{apk}/versions") - res.raise_for_status() - data = bs(res.text, 'html.parser') +def apkpure_best_match(version, soup): try: - vers_list = [Version(x['data-dt-version']) for x in data.css.select(f"a[data-dt-apkid^=\"b/APK/\"]")] + vers_list = [Version(x['data-dt-version']) for x in soup.css.select(f"a[data-dt-apkid^=\"b/APK/\"]")] except: sys.exit(f" There was some error getting list of versions of {apk}...") if version != '0': vers_list = filter(lambda x: x <= Version(version), vers_list) - return max(vers_list) + return str(max(vers_list)) # Download an apk from APKPure.com -def apkpure_dl(apk, appname, version, hard_version, session, present_vers): +def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag): + res = session.get(f"https://apkpure.com/{appname}/{apk}/versions") + res.raise_for_status() + soup = bs(res.text, 'html.parser') + if not hard_version: - version = apkpure_best_match(apk, appname, version, session) + version = apkpure_best_match(version, soup) + + if flag == 'checkonly' and present_vers[apk] != version: + print(f"{apk} has an update ({present_vers[apk]} -> {version})") + return try: - if present_vers[apk] == version: + if present_vers[apk] == version and flag != 'force' and os.path.isfile(apk): print(f"Recommended version {version} of {apk} is already present.") return except KeyError: @@ -33,17 +39,14 @@ def apkpure_dl(apk, appname, version, hard_version, session, present_vers): print(f" Downloading {apk} version {version}...") # Get the version code - res = session.get(f"https://apkpure.com/{appname}/{apk}/versions") - res.raise_for_status() - data = bs(res.text, 'html.parser') try: - ver_code = data.css.select(f"a[data-dt-version=\"{version}\"][data-dt-apkid^=\"b/APK/\"]")[0]['data-dt-versioncode'] + ver_code = soup.css.select(f"a[data-dt-version=\"{version}\"][data-dt-apkid^=\"b/APK/\"]")[0]['data-dt-versioncode'] except: sys.exit(f" There was some error while downloading {apk}...") res = session.get(f"https://d.apkpure.com/b/APK/{apk}?versionCode={ver_code}", stream=True) res.raise_for_status() - with open(apk, 'wb') as f: + with open(apk+'.apk', 'wb') as f: for chunk in res.iter_content(chunk_size=8192): f.write(chunk) print(" Done!") @@ -51,7 +54,7 @@ def apkpure_dl(apk, appname, version, hard_version, session, present_vers): # Download apk files, if needed -def get_apks(present_vers, build_config): +def get_apks(present_vers, build_config, flag): print('Downloading required apk files from APKPure...') # Get latest patches using the ReVanced API @@ -67,14 +70,15 @@ def get_apks(present_vers, build_config): # Check if we need to build an app if not build_config[app].getboolean('build'): continue - print(f"Checking {app}...") try: apk = build_config[app]['apk'] + pretty_name = build_config[app]['pretty_name'] apkpure_appname = build_config[app]['apkpure_appname'] except: sys.exit(f"Invalid config for {app} in build_config.toml!") + print(f"Checking {pretty_name}...") try: required_ver = build_config[app]['version'] required_ver[0] @@ -96,7 +100,7 @@ def get_apks(present_vers, build_config): else: required_ver = min(map(lambda x: Version(x), compatible_vers)) - apkpure_dl(apk, apkpure_appname, str(required_ver), hard_version, session, present_vers) + apkpure_dl(apk, apkpure_appname, str(required_ver), hard_version, session, present_vers, flag) present_vers.update({apk: str(required_ver)}) return present_vers \ No newline at end of file diff --git a/JAVABuilder.py b/JAVABuilder.py new file mode 100644 index 0000000..ce0b82b --- /dev/null +++ b/JAVABuilder.py @@ -0,0 +1,78 @@ +import os +import sys +import configparser as cp +import json +import subprocess + +# Build the revanced apps +def build_apps(build_config, flag): + chosen_patches = cp.ConfigParser() + chosen_patches.read('chosen_patches.toml') + + try: + included_patches = json.loads(chosen_patches['patches']['included']) + except: + included_patches = [] + try: + excluded_patches = json.loads(chosen_patches['patches']['excluded']) + except Exception as e: + excluded_patches = [] + + for app in build_config: + # Check if we need to build an app + if not build_config[app].getboolean('build'): + continue + + # Build the command to be run + cmd = 'java -jar revanced-cli.jar -m revanced-integrations.apk -b revanced-patches.jar' + + try: + root = build_config[app].getboolean('root') + except: + root = False + + if root: + cmd += ' --mount -e microg-support' + + for item in included_patches: + cmd += f" -i {item}" + for item in excluded_patches: + cmd += f" -e {item}" + + if flag == 'experimental': + cmd += ' --experimental' + + try: + keystore = build_config[app]['keystore'] + if not root: + cmd += f" --keystore {keystore}" + except: + pass + + try: + apk = build_config[app]['apk'] + pretty_name = build_config[app]['pretty_name'] + apkpure_appname = build_config[app]['apkpure_appname'] + output_name = build_config[app]['output_name'] + except: + sys.exit(f"Invalid config for {app} in build_config.toml!") + + cmd += f" -a {apk}.apk -o {output_name}.apk" + + if root: + print(f"Building {pretty_name} (root)...") + else: + print(f"Building {pretty_name} (nonroot)...") + + # if os.system(cmd) != 0: + # sys.exit('There was an error while building!') + try: + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, text=True) + except Exception as e: + sys.exit(f"There was an error while building! {e.output}") + + try: + os.rename(output_name+'.apk', output_name+'.apk') # TODO: Add timestamp here + except FileNotFoundError: + sys.exit(f"There was an error while building {pretty_name}!") + \ No newline at end of file diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index ab96b93..a36f7e8 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -7,6 +7,15 @@ import requests as req import json from packaging.version import Version from APKPure_dl import * +from JAVABuilder import * + +# TODO: Logging +# TODO: Timestamp +# TODO: Notifications +# TODO: Notification for errors (maybe by writing custom exit function? Exit function should also cleanup output files. printerr?) +# TODO: Moving files in proper locations +# TODO: Run post_script (preferably in any language) +# TODO: README # Update the ReVanced tools, if needed def update_tools(): @@ -19,11 +28,11 @@ def update_tools(): except KeyError: present_ver = Version('0') - if present_ver < latest_ver: + output_file = item+os.path.splitext(tool['name'])[1] + if flag == 'force' or not os.path.isfile(output_file) or present_ver < latest_ver: global up_to_date up_to_date = False print(f"{item} has an update ({str(present_ver)} -> {str(latest_ver)})") - output_file = item.split('-')[1]+os.path.splitext(tool['name'])[1] if flag != 'checkonly': print(f"Downloading {output_file}...") res = req.get(tool['browser_download_url'], stream=True) @@ -47,12 +56,12 @@ def update_microg(): except KeyError: present_ver = Version('0') - if present_ver < latest_ver: + if flag == 'force' or not os.path.isfile('microg.apk') or present_ver < latest_ver: global up_to_date up_to_date = False print(f"Vanced microG has an update ({str(present_ver)} -> {str(latest_ver)})") if flag != 'checkonly': - print(f"Downloading microg.apk...") + print(f"Downloading vanced-microg.apk...") res = req.get('https://github.com/inotia00/VancedMicroG/releases/latest/download/microg.apk', stream=True) res.raise_for_status() with open('microg.apk', 'wb') as f: @@ -103,15 +112,15 @@ up_to_date = True if flag != 'buildonly': update_tools() update_microg() - # if not up_to_date: - present_vers = get_apks(present_vers, build_config) + if not up_to_date or flag == 'force': + present_vers = get_apks(present_vers, build_config, flag) -# if (flag != 'checkonly' and not up_to_date) or flag == 'force': -# build_apps() +if (flag != 'checkonly' and not up_to_date) or flag in ['force', 'buildonly']: + build_apps(build_config, flag) # Update version numbers in the versions.json file -if up_to_date: +if up_to_date and flag != 'buildonly': print('There\'s nothing to do.') -elif flag != 'checkonly': +elif flag not in ['checkonly', 'buildonly']: with open('versions.json', 'w') as f: json.dump(present_vers, f, indent=4) From a9fe4bf64640f03fd2f96a019f99d6b0ca3d2a43 Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Wed, 9 Aug 2023 14:25:32 -0500 Subject: [PATCH 03/17] new: Properly move apps and clean older versions --- ReVancedBuilder.py | 47 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index a36f7e8..254ca87 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -8,9 +8,9 @@ import json from packaging.version import Version from APKPure_dl import * from JAVABuilder import * +from datetime import datetime # TODO: Logging -# TODO: Timestamp # TODO: Notifications # TODO: Notification for errors (maybe by writing custom exit function? Exit function should also cleanup output files. printerr?) # TODO: Moving files in proper locations @@ -70,6 +70,48 @@ def update_microg(): present_vers.update({'VancedMicroG': str(latest_ver)}) print("Done!") +# Move apps to proper location +def move_apps(): + try: + os.mkdir('archive') + except FileExistsError: + pass + + for app in build_config: + if not build_config[app].getboolean('build'): + continue + name = build_config[app]['output_name'] + final_name = f"{name}_{timestamp}.apk" + + try: + os.rename(name+'.apk', 'archive/'+final_name) + except FileNotFoundError: + pass + # sys.exit('There was an error moving the final apk files!') + + files = [] + dir = os.scandir('archive') + for f in dir: + if name in f.name: + files.append(f) + files.sort(key=lambda f: f.stat().st_ctime) + files.reverse() + for f in files[3:]: + os.remove(f) + print('Deleted old build '+f.name) + dir.close() + + + +# ------------------------------ +# The main function starts here +# ------------------------------ + +# Get a timestamp +time = datetime.now() +timestamp = time.strftime('%Y%m%d%H%M%S') +print(f"Started building ReVanced apps at {time.strftime('%d %B, %Y %H:%M:%S')}") + # Read configs try: os.chdir(sys.argv[1]) @@ -89,6 +131,8 @@ try: except FileNotFoundError: sys.exit('No build config provided, exiting. Please look at the GitHub page for more information:\n https://github.com/SinTan1729/ReVancedBuilder') +move_apps() + notification_config = cp.ConfigParser() notification_config.read('notification_config.toml') @@ -117,6 +161,7 @@ if flag != 'buildonly': if (flag != 'checkonly' and not up_to_date) or flag in ['force', 'buildonly']: build_apps(build_config, flag) + move_apps() # Update version numbers in the versions.json file if up_to_date and flag != 'buildonly': From b5fc2e43d375e12c3273d9c44f1b62941b07c8da Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Wed, 9 Aug 2023 19:12:04 -0500 Subject: [PATCH 04/17] new: Clean up + Notifications (partial) --- APKPure_dl.py | 19 ++++--- Cleanup.py | 42 +++++++++++++++ JAVABuilder.py | 16 +++--- Notifications.py | 77 ++++++++++++++++++++++++++++ ReVancedBuilder.py | 125 +++++++++++++++++++-------------------------- 5 files changed, 193 insertions(+), 86 deletions(-) create mode 100644 Cleanup.py create mode 100644 Notifications.py diff --git a/APKPure_dl.py b/APKPure_dl.py index ba44ebb..439197e 100644 --- a/APKPure_dl.py +++ b/APKPure_dl.py @@ -4,13 +4,14 @@ import json from packaging.version import Version import requests as req from bs4 import BeautifulSoup as bs +from Cleanup import clean_exit # Determine the best version available to download def apkpure_best_match(version, soup): try: vers_list = [Version(x['data-dt-version']) for x in soup.css.select(f"a[data-dt-apkid^=\"b/APK/\"]")] except: - sys.exit(f" There was some error getting list of versions of {apk}...") + clean_exit(f" There was some error getting list of versions of {apk}...", appstate) if version != '0': vers_list = filter(lambda x: x <= Version(version), vers_list) @@ -42,7 +43,7 @@ def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag) try: ver_code = soup.css.select(f"a[data-dt-version=\"{version}\"][data-dt-apkid^=\"b/APK/\"]")[0]['data-dt-versioncode'] except: - sys.exit(f" There was some error while downloading {apk}...") + clean_exit(f" There was some error while downloading {apk}...", appstate) res = session.get(f"https://d.apkpure.com/b/APK/{apk}?versionCode={ver_code}", stream=True) res.raise_for_status() @@ -54,14 +55,18 @@ def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag) # Download apk files, if needed -def get_apks(present_vers, build_config, flag): +def get_apks(appstate): + present_vers = appstate['present_vers'] + build_config = appstate['build_config'] + flag=appstate['flag'] + print('Downloading required apk files from APKPure...') # Get latest patches using the ReVanced API try: patches = req.get('https://releases.revanced.app/patches').json() except req.exceptions.RequestException as e: - sys.exit(e) + clean_exit(e, appstate) session = req.Session() session.headers.update({'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/116.0'}) @@ -76,7 +81,7 @@ def get_apks(present_vers, build_config, flag): pretty_name = build_config[app]['pretty_name'] apkpure_appname = build_config[app]['apkpure_appname'] except: - sys.exit(f"Invalid config for {app} in build_config.toml!") + clean_exit(f"Invalid config for {app} in build_config.toml!", appstate) print(f"Checking {pretty_name}...") try: @@ -103,4 +108,6 @@ def get_apks(present_vers, build_config, flag): apkpure_dl(apk, apkpure_appname, str(required_ver), hard_version, session, present_vers, flag) present_vers.update({apk: str(required_ver)}) - return present_vers \ No newline at end of file + + appstate['present_vers'] = present_vers + return appstate \ No newline at end of file diff --git a/Cleanup.py b/Cleanup.py new file mode 100644 index 0000000..e0d406d --- /dev/null +++ b/Cleanup.py @@ -0,0 +1,42 @@ +import os +import sys +from Notifications import send_notif + +# Move apps to proper location +def move_apps(appstate): + build_config = appstate['build_config'] + + try: + os.mkdir('archive') + except FileExistsError: + pass + + for app in build_config: + if not build_config[app].getboolean('build'): + continue + name = build_config[app]['output_name'] + final_name = f"{name}_{appstate['timestamp']}.apk" + + try: + os.rename(name+'.apk', 'archive/'+final_name) + except FileNotFoundError: + pass + # sys.exit('There was an error moving the final apk files!') + + files = [] + dir = os.scandir('archive') + for f in dir: + if name in f.name: + files.append(f) + files.sort(key=lambda f: f.stat().st_ctime) + files.reverse() + for f in files[3:]: + os.remove(f) + print('Deleted old build '+f.name) + dir.close() + +def clean_exit(msg, appstate, code=1): + send_notif(appstate, error=True) + if msg: + print(msg, file=sys.stderr) + exit(code) \ No newline at end of file diff --git a/JAVABuilder.py b/JAVABuilder.py index ce0b82b..6a6796a 100644 --- a/JAVABuilder.py +++ b/JAVABuilder.py @@ -3,9 +3,13 @@ import sys import configparser as cp import json import subprocess +from Cleanup import clean_exit # Build the revanced apps -def build_apps(build_config, flag): +def build_apps(appstate): + build_config = appstate['build_config'] + flag = appstate['flag'] + chosen_patches = cp.ConfigParser() chosen_patches.read('chosen_patches.toml') @@ -55,7 +59,7 @@ def build_apps(build_config, flag): apkpure_appname = build_config[app]['apkpure_appname'] output_name = build_config[app]['output_name'] except: - sys.exit(f"Invalid config for {app} in build_config.toml!") + clean_exit(f"Invalid config for {app} in build_config.toml!", appstate) cmd += f" -a {apk}.apk -o {output_name}.apk" @@ -64,15 +68,13 @@ def build_apps(build_config, flag): else: print(f"Building {pretty_name} (nonroot)...") - # if os.system(cmd) != 0: - # sys.exit('There was an error while building!') try: - output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, text=True) + output = subprocess.run(cmd, shell=True) except Exception as e: - sys.exit(f"There was an error while building! {e.output}") + clean_exit(f"There was an error while building {pretty_name}!", appstate) try: os.rename(output_name+'.apk', output_name+'.apk') # TODO: Add timestamp here except FileNotFoundError: - sys.exit(f"There was an error while building {pretty_name}!") + clean_exit(f"There was an error while building {pretty_name}!", appstate) \ No newline at end of file diff --git a/Notifications.py b/Notifications.py new file mode 100644 index 0000000..d11cce1 --- /dev/null +++ b/Notifications.py @@ -0,0 +1,77 @@ +import json +import re +import requests as req + +def send_notif(appstate, error=False): + timestamp = appstate['timestamp'] + if error: + msg = f"There was an error during build! Please check the logs.\nTimestamp: {timestamp}" + else: + notification_config = appstate['notification_config'] + build_config = appstate['build_config'] + present_vers = appstate['present_vers'] + flag = appstate['flag'] + + msg = json.dumps(present_vers, indent=0) + msg = re.sub('("|\{|\}|,)', '', msg).strip('\n') + + for app in build_config: + if not build_config[app].getboolean('build'): + continue + msg = msg.replace(build_config[app]['apk'], build_config[app]['pretty_name']) + + msg += '\nTimestamp: ' + timestamp + + config = appstate['notification_config'] + for entry in config: + if not config[entry].getboolean('enabled'): + continue + encoded_title = '⚙⚙⚙ ReVanced Build ⚙⚙⚙'.encode('utf-8') + + match entry: + case 'ntfy': + print('Sending notification through nfty.sh') + try: + url = config[entry]['url'] + topic = config[entry]['topic'] + except: + print('URL or TOPIC not provided!') + continue + headers = {'Icon': 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Revanced-logo-round.svg/240px-Revanced-logo-round.svg.png', + 'Title': encoded_title} + try: + req.post(f"{url}/{topic}", msg, headers=headers) + except Exception as e: + print('Failed!' + str(e)) + + case 'gotify': + print('Sending notification through nfty.sh') + try: + url = config[entry]['url'] + token = config[entry]['token'] + except: + print('URL or TOKEN not provided!') + continue + data = {'Title': encoded_title, 'message': msg, 'priority': '5'} + try: + req.post(f"{url}/message?token={token}", data) + except Exception as e: + print('Failed!' + str(e)) + + case 'telegram': + # TODO: Finish this! + print('Sending notification through telegram') + try: + chat = config[entry]['chat'] + token = config[entry]['token'] + except: + print('CHAT or TOKEN not provided!') + continue + data = {'Title': encoded_title, 'message': msg, 'priority': '5'} + try: + req.post(f"{url}/message?token={token}", data) + except Exception as e: + print('Failed!' + str(e)) + + case _: + print('Don\'t know how to send notifications to ' + entry) diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index 254ca87..6450231 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -9,29 +9,29 @@ from packaging.version import Version from APKPure_dl import * from JAVABuilder import * from datetime import datetime +from Notifications import send_notif +from Cleanup import * # TODO: Logging # TODO: Notifications -# TODO: Notification for errors (maybe by writing custom exit function? Exit function should also cleanup output files. printerr?) -# TODO: Moving files in proper locations # TODO: Run post_script (preferably in any language) # TODO: README +# TODO: PATCHES_GUIDE.md (maybe delete it?) # Update the ReVanced tools, if needed -def update_tools(): +def update_tools(appstate): for item in ['revanced-cli', 'revanced-integrations', 'revanced-patches']: *_, tool = filter(lambda x: x['repository'] == 'revanced/'+item, tools) # Get the last result latest_ver = Version(tool['version']) try: - present_ver = Version(present_vers[item]) + present_ver = Version(appstate['present_vers'][item]) except KeyError: present_ver = Version('0') output_file = item+os.path.splitext(tool['name'])[1] if flag == 'force' or not os.path.isfile(output_file) or present_ver < latest_ver: - global up_to_date - up_to_date = False + appstate['up-to-date'] = False print(f"{item} has an update ({str(present_ver)} -> {str(latest_ver)})") if flag != 'checkonly': print(f"Downloading {output_file}...") @@ -40,25 +40,26 @@ def update_tools(): with open(output_file, 'wb') as f: for chunk in res.iter_content(chunk_size=8192): f.write(chunk) - present_vers.update({item: str(latest_ver)}) + appstate['present_vers'].update({item: str(latest_ver)}) print("Done!") + return appstate + # Update microG, if needed -def update_microg(): +def update_microg(appstate): try: data = req.get('https://api.github.com/repos/inotia00/VancedMicroG/releases/latest').json()['tag_name'] latest_ver = Version(data) except req.exceptions.RequestException as e: - sys.exit(e) + clean_exit(e, appstate) try: - present_ver = Version(present_vers['VancedMicroG']) + present_ver = Version(appstate['present_vers']['VancedMicroG']) except KeyError: present_ver = Version('0') if flag == 'force' or not os.path.isfile('microg.apk') or present_ver < latest_ver: - global up_to_date - up_to_date = False + appstate['up-to-date'] = False print(f"Vanced microG has an update ({str(present_ver)} -> {str(latest_ver)})") if flag != 'checkonly': print(f"Downloading vanced-microg.apk...") @@ -67,105 +68,83 @@ def update_microg(): with open('microg.apk', 'wb') as f: for chunk in res.iter_content(chunk_size=8192): f.write(chunk) - present_vers.update({'VancedMicroG': str(latest_ver)}) + appstate['present_vers'].update({'VancedMicroG': str(latest_ver)}) print("Done!") -# Move apps to proper location -def move_apps(): - try: - os.mkdir('archive') - except FileExistsError: - pass - - for app in build_config: - if not build_config[app].getboolean('build'): - continue - name = build_config[app]['output_name'] - final_name = f"{name}_{timestamp}.apk" - - try: - os.rename(name+'.apk', 'archive/'+final_name) - except FileNotFoundError: - pass - # sys.exit('There was an error moving the final apk files!') - - files = [] - dir = os.scandir('archive') - for f in dir: - if name in f.name: - files.append(f) - files.sort(key=lambda f: f.stat().st_ctime) - files.reverse() - for f in files[3:]: - os.remove(f) - print('Deleted old build '+f.name) - dir.close() - - + return appstate # ------------------------------ # The main function starts here # ------------------------------ +# Create a dict for storing important data +appstate = {} + # Get a timestamp time = datetime.now() -timestamp = time.strftime('%Y%m%d%H%M%S') +appstate['timestamp'] = time.strftime('%Y%m%d%H%M%S') print(f"Started building ReVanced apps at {time.strftime('%d %B, %Y %H:%M:%S')}") +print('----------------------------------------------------------------------') # Read configs try: os.chdir(sys.argv[1]) except IndexError: - sys.exit('Please provide a working directory as argument!') + clean_exit('Please provide a working directory as argument!', appstate) except FileNotFoundError: - sys.exit('Invalid working directory provided!') + clean_exit('Invalid working directory provided!', appstate) try: flag = sys.argv[2] except: flag = None +appstate['flag'] = flag + try: - build_config=cp.ConfigParser() - build_config.read_file(open('build_config.toml', 'r')) + appstate['build_config']=cp.ConfigParser() + appstate['build_config'].read_file(open('build_config.toml', 'r')) except FileNotFoundError: - sys.exit('No build config provided, exiting. Please look at the GitHub page for more information:\n https://github.com/SinTan1729/ReVancedBuilder') + clean_exit('No build config provided, exiting. Please look at the GitHub page for more information:\n https://github.com/SinTan1729/ReVancedBuilder', appstate) -move_apps() - -notification_config = cp.ConfigParser() -notification_config.read('notification_config.toml') +appstate['notification_config'] = cp.ConfigParser() +appstate['notification_config'].read('notification_config.toml') # Pull the latest information using the ReVanced API try: tools = req.get('https://releases.revanced.app/tools').json()['tools'] except req.exceptions.RequestException as e: - sys.exit(e) + clean_exit(e, appstate) -global present_vers try: with open('versions.json', 'r') as f: - present_vers = json.load(f) + appstate['present_vers'] = json.load(f) except: # We'll treat empty as 0 later - present_vers = json.loads('{}') - -global up_to_date -up_to_date = True + appstate['present_vers'] = json.loads('{}') +appstate['up-to-date'] = True +# send_notif(appstate, error=False) # <,,,,,,,,<,,,,,,,,,,,,, if flag != 'buildonly': - update_tools() - update_microg() - if not up_to_date or flag == 'force': - present_vers = get_apks(present_vers, build_config, flag) + appstate = update_tools(appstate) + appstate = update_microg(appstate) + if not appstate['up-to-date'] or flag == 'force': + appstate = get_apks(appstate) -if (flag != 'checkonly' and not up_to_date) or flag in ['force', 'buildonly']: - build_apps(build_config, flag) - move_apps() +if (flag != 'checkonly' and not appstate['up-to-date']) or flag in ['force', 'buildonly']: + build_apps(appstate) + move_apps(appstate) # Update version numbers in the versions.json file -if up_to_date and flag != 'buildonly': +if appstate['up-to-date'] and flag != 'buildonly': print('There\'s nothing to do.') -elif flag not in ['checkonly', 'buildonly']: - with open('versions.json', 'w') as f: - json.dump(present_vers, f, indent=4) +elif flag != ['checkonly']: + send_notif(appstate) + try: + os.rename('versions.json', 'versions-old.json') + except FileNotFoundError: + pass + + if flag != 'buildonly': + with open('versions.json', 'w') as f: + json.dump(appstate['present_vers'], f, indent=4) From c1451bcc375254e5e8c3ae687da9c39dfc67fd0e Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 13:07:00 -0500 Subject: [PATCH 05/17] feat: Notifications should work --- Cleanup.py | 1 + Notifications.py | 13 ++++++++----- ReVancedBuilder.py | 3 +++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Cleanup.py b/Cleanup.py index e0d406d..94f8aaf 100644 --- a/Cleanup.py +++ b/Cleanup.py @@ -23,6 +23,7 @@ def move_apps(appstate): pass # sys.exit('There was an error moving the final apk files!') + # Do some cleanup, keep only the last 3 build's worth of files and a week worth of logs files = [] dir = os.scandir('archive') for f in dir: diff --git a/Notifications.py b/Notifications.py index d11cce1..5d1c7d7 100644 --- a/Notifications.py +++ b/Notifications.py @@ -1,6 +1,7 @@ import json import re import requests as req +import subprocess def send_notif(appstate, error=False): timestamp = appstate['timestamp'] @@ -21,6 +22,8 @@ def send_notif(appstate, error=False): msg = msg.replace(build_config[app]['apk'], build_config[app]['pretty_name']) msg += '\nTimestamp: ' + timestamp + if appstate['microg_updated']: + msg += '\nVanced microG was updated.' config = appstate['notification_config'] for entry in config: @@ -30,7 +33,7 @@ def send_notif(appstate, error=False): match entry: case 'ntfy': - print('Sending notification through nfty.sh') + print('Sending notification through ntfy.sh...') try: url = config[entry]['url'] topic = config[entry]['topic'] @@ -45,7 +48,7 @@ def send_notif(appstate, error=False): print('Failed!' + str(e)) case 'gotify': - print('Sending notification through nfty.sh') + print('Sending notification through Gotify...') try: url = config[entry]['url'] token = config[entry]['token'] @@ -60,16 +63,16 @@ def send_notif(appstate, error=False): case 'telegram': # TODO: Finish this! - print('Sending notification through telegram') + print('Sending notification through Telegram...') try: chat = config[entry]['chat'] token = config[entry]['token'] except: print('CHAT or TOKEN not provided!') continue - data = {'Title': encoded_title, 'message': msg, 'priority': '5'} + cmd = f"./telegram.sh -t {token} -c {chat} -T {encoded_title} -M \"{msg}\"" try: - req.post(f"{url}/message?token={token}", data) + subprocess.run(cmd, shell=True) except Exception as e: print('Failed!' + str(e)) diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index 6450231..c3ad1f9 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -17,6 +17,7 @@ from Cleanup import * # TODO: Run post_script (preferably in any language) # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) +# TODO: Make it PIP installable # Update the ReVanced tools, if needed def update_tools(appstate): @@ -70,6 +71,7 @@ def update_microg(appstate): f.write(chunk) appstate['present_vers'].update({'VancedMicroG': str(latest_ver)}) print("Done!") + appstate['microg_updated'] = True return appstate @@ -100,6 +102,7 @@ except: flag = None appstate['flag'] = flag +appstate['microg_updated'] = False try: appstate['build_config']=cp.ConfigParser() From c56a97c7338fe0a62341fe0b4db70feef4a8b2f4 Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 14:50:42 -0500 Subject: [PATCH 06/17] feat: Logging works --- Cleanup.py | 41 ++++++++++++++++++++++++++++------------- JAVABuilder.py | 11 ++++++++--- Notifications.py | 10 ++++++++-- ReVancedBuilder.py | 27 ++++++++++++++++++++++----- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/Cleanup.py b/Cleanup.py index 94f8aaf..2fc6484 100644 --- a/Cleanup.py +++ b/Cleanup.py @@ -1,10 +1,12 @@ import os import sys from Notifications import send_notif +import time # Move apps to proper location def move_apps(appstate): build_config = appstate['build_config'] + print = appstate['logger'].info try: os.mkdir('archive') @@ -24,20 +26,33 @@ def move_apps(appstate): # sys.exit('There was an error moving the final apk files!') # Do some cleanup, keep only the last 3 build's worth of files and a week worth of logs - files = [] - dir = os.scandir('archive') - for f in dir: - if name in f.name: - files.append(f) - files.sort(key=lambda f: f.stat().st_ctime) - files.reverse() - for f in files[3:]: - os.remove(f) - print('Deleted old build '+f.name) - dir.close() + with os.scandir('archive') as dir: + files = [] + for f in dir: + if name in f.name: + files.append(f) + files.sort(key=lambda f: f.stat().st_ctime) + files.reverse() + for f in files[3:]: + os.remove(f) + print('Deleted old build '+f.name) + + # Delete logs older than 7 days + with os.scandir('logs') as dir: + now = time.now() + for f in dir: + if f.stat().st_ctime < now - 7 * 86400: + os.remove(f) def clean_exit(msg, appstate, code=1): - send_notif(appstate, error=True) + print = appstate['logger'].info + + try: + appstate['notification_config'] + send_notif(appstate, error=True) + except: + pass + if msg: - print(msg, file=sys.stderr) + print(msg) exit(code) \ No newline at end of file diff --git a/JAVABuilder.py b/JAVABuilder.py index 6a6796a..84456e4 100644 --- a/JAVABuilder.py +++ b/JAVABuilder.py @@ -2,13 +2,14 @@ import os import sys import configparser as cp import json -import subprocess from Cleanup import clean_exit +import subprocess # Build the revanced apps def build_apps(appstate): build_config = appstate['build_config'] flag = appstate['flag'] + print = appstate['logger'].info chosen_patches = cp.ConfigParser() chosen_patches.read('chosen_patches.toml') @@ -69,9 +70,13 @@ def build_apps(appstate): print(f"Building {pretty_name} (nonroot)...") try: - output = subprocess.run(cmd, shell=True) + with subprocess.Popen(cmd, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout as output: + for line in output: + line_utf = line.decode('utf-8').strip('\n') + if line_utf: + print(line_utf) except Exception as e: - clean_exit(f"There was an error while building {pretty_name}!", appstate) + clean_exit(f"There was an error while building {pretty_name}!\n{e}", appstate) try: os.rename(output_name+'.apk', output_name+'.apk') # TODO: Add timestamp here diff --git a/Notifications.py b/Notifications.py index 5d1c7d7..dfee15b 100644 --- a/Notifications.py +++ b/Notifications.py @@ -4,7 +4,9 @@ import requests as req import subprocess def send_notif(appstate, error=False): + print = appstate['logger'].info timestamp = appstate['timestamp'] + if error: msg = f"There was an error during build! Please check the logs.\nTimestamp: {timestamp}" else: @@ -72,9 +74,13 @@ def send_notif(appstate, error=False): continue cmd = f"./telegram.sh -t {token} -c {chat} -T {encoded_title} -M \"{msg}\"" try: - subprocess.run(cmd, shell=True) + with subprocess.Popen(cmd, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout as output: + for line in output: + line_utf = line.decode('utf-8').strip('\n') + if line_utf: + print(line_utf) except Exception as e: - print('Failed!' + str(e)) + clean_exit(f"Failed!\n{e}", appstate) case _: print('Don\'t know how to send notifications to ' + entry) diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index c3ad1f9..e4d5e96 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -11,9 +11,8 @@ from JAVABuilder import * from datetime import datetime from Notifications import send_notif from Cleanup import * +import logging -# TODO: Logging -# TODO: Notifications # TODO: Run post_script (preferably in any language) # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) @@ -85,10 +84,8 @@ appstate = {} # Get a timestamp time = datetime.now() appstate['timestamp'] = time.strftime('%Y%m%d%H%M%S') -print(f"Started building ReVanced apps at {time.strftime('%d %B, %Y %H:%M:%S')}") -print('----------------------------------------------------------------------') -# Read configs +# Read arguments try: os.chdir(sys.argv[1]) except IndexError: @@ -96,14 +93,34 @@ except IndexError: except FileNotFoundError: clean_exit('Invalid working directory provided!', appstate) +# Set up logging +try: + os.mkdir('logs') +except FileExistsError: + pass + +logging.basicConfig(level=logging.INFO, format='%(message)s') +logger = logging.getLogger() +logger.addHandler(logging.FileHandler(f"logs/{appstate['timestamp']}.log", 'w')) +print = logger.info +appstate['logger'] = logger + +# Get the flag try: flag = sys.argv[2] except: flag = None +if flag not in ['buildonly', 'checkonly', 'force', 'experimental']: + clean_exit(f"Unknown flag: {flag}", appstate) + appstate['flag'] = flag appstate['microg_updated'] = False +print(f"Started building ReVanced apps at {time.strftime('%d %B, %Y %H:%M:%S')}") +print('----------------------------------------------------------------------') + +# Read configs try: appstate['build_config']=cp.ConfigParser() appstate['build_config'].read_file(open('build_config.toml', 'r')) From b677e73a7c3ac45576367decea0bb159eaf89c60 Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 14:52:58 -0500 Subject: [PATCH 07/17] feat: Run post_script --- ReVancedBuilder.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index e4d5e96..33c9b47 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -12,11 +12,12 @@ from datetime import datetime from Notifications import send_notif from Cleanup import * import logging +import subprocess # TODO: Run post_script (preferably in any language) # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) -# TODO: Make it PIP installable +# TODO: Lockfile # Update the ReVanced tools, if needed def update_tools(appstate): @@ -168,3 +169,7 @@ elif flag != ['checkonly']: if flag != 'buildonly': with open('versions.json', 'w') as f: json.dump(appstate['present_vers'], f, indent=4) + try: + subprocess.run(f"{appstate['build_config']['post_script']['file']} {timestamp}", shell=True) + except: + pass From 4f145181663d5fa67b7a9213d4b8508cd5b89e9a Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 15:12:22 -0500 Subject: [PATCH 08/17] feat: Lockfile --- Cleanup.py | 3 +++ ReVancedBuilder.py | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Cleanup.py b/Cleanup.py index 2fc6484..be9f8a1 100644 --- a/Cleanup.py +++ b/Cleanup.py @@ -55,4 +55,7 @@ def clean_exit(msg, appstate, code=1): if msg: print(msg) + + # Delete the lockfile + os.remove('lockfile') exit(code) \ No newline at end of file diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index 33c9b47..e915e81 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -14,7 +14,6 @@ from Cleanup import * import logging import subprocess -# TODO: Run post_script (preferably in any language) # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) # TODO: Lockfile @@ -94,6 +93,17 @@ except IndexError: except FileNotFoundError: clean_exit('Invalid working directory provided!', appstate) +# Try to make sure only one instance is running in a given working directory +try: + if os.path.exists('lockfile'): + raise FileExistsError + with open('tmplockfile', 'x') as f: + f.flush() + os.fsync(f.fileno()) + os.replace('tmplockfile', 'lockfile') +except FileExistsError: + sys.exit('Another instance is already running in the same working directory!') + # Set up logging try: os.mkdir('logs') @@ -173,3 +183,6 @@ elif flag != ['checkonly']: subprocess.run(f"{appstate['build_config']['post_script']['file']} {timestamp}", shell=True) except: pass + +# Delete the lockfile +os.remove('lockfile') \ No newline at end of file From ae83b9e652b45358b0a4f62a0aa2f771a6ec1d43 Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 15:20:40 -0500 Subject: [PATCH 09/17] fix: None flag --- ReVancedBuilder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index e915e81..d39bc20 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -16,7 +16,7 @@ import subprocess # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) -# TODO: Lockfile +# TODO: Install using pip # Update the ReVanced tools, if needed def update_tools(appstate): @@ -122,7 +122,7 @@ try: except: flag = None -if flag not in ['buildonly', 'checkonly', 'force', 'experimental']: +if flag not in ['buildonly', 'checkonly', 'force', 'experimental', None]: clean_exit(f"Unknown flag: {flag}", appstate) appstate['flag'] = flag From b07b9faa9a0748ab62fa253da595b5ce6249f9db Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 15:41:42 -0500 Subject: [PATCH 10/17] fix: Misc --- APKPure_dl.py | 2 +- Cleanup.py | 2 +- Notifications.py | 6 ++++++ ReVancedBuilder.py | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/APKPure_dl.py b/APKPure_dl.py index 439197e..069e557 100644 --- a/APKPure_dl.py +++ b/APKPure_dl.py @@ -32,7 +32,7 @@ def apkpure_dl(apk, appname, version, hard_version, session, present_vers, flag) return try: - if present_vers[apk] == version and flag != 'force' and os.path.isfile(apk): + if present_vers[apk] == version and flag != 'force' and os.path.isfile(apk+'.apk'): print(f"Recommended version {version} of {apk} is already present.") return except KeyError: diff --git a/Cleanup.py b/Cleanup.py index be9f8a1..ee661fe 100644 --- a/Cleanup.py +++ b/Cleanup.py @@ -39,7 +39,7 @@ def move_apps(appstate): # Delete logs older than 7 days with os.scandir('logs') as dir: - now = time.now() + now = time.time() for f in dir: if f.stat().st_ctime < now - 7 * 86400: os.remove(f) diff --git a/Notifications.py b/Notifications.py index dfee15b..8375e32 100644 --- a/Notifications.py +++ b/Notifications.py @@ -18,6 +18,12 @@ def send_notif(appstate, error=False): msg = json.dumps(present_vers, indent=0) msg = re.sub('("|\{|\}|,)', '', msg).strip('\n') + msg = msg.replace('revanced-', 'ReVanced ') + msg = msg.replace('cli', 'CLI') + msg = msg.replace('integrations', 'Integrations') + msg = msg.replace('patches', 'Patches') + msg = msg.replace('VancedMicroG', 'Vanced microG') + for app in build_config: if not build_config[app].getboolean('build'): continue diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index d39bc20..92456c5 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -17,6 +17,7 @@ import subprocess # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) # TODO: Install using pip +# TODO: Do not download twice for root and nonroot # Update the ReVanced tools, if needed def update_tools(appstate): From 7ed9a74f8a6a2b3204b0fe6860da45515b5b0807 Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 15:46:27 -0500 Subject: [PATCH 11/17] del: Delete the old shell scripts --- build_revanced.sh | 323 ---------------------------------------------- download_apk.sh | 160 ----------------------- 2 files changed, 483 deletions(-) delete mode 100755 build_revanced.sh delete mode 100755 download_apk.sh diff --git a/build_revanced.sh b/build_revanced.sh deleted file mode 100755 index 13b29dc..0000000 --- a/build_revanced.sh +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/env bash - -# Run only one instance of this script at one time -[ "${BKLOCKER}" != "running" ] && exec env BKLOCKER="running" flock -en "/tmp/revanced-builder.lock" "$0" "$@" || : - -# Get timestamp -timestamp=$(date '+%Y%m%d%H%M%S') - -# Log everything to a logfile inside logs/ -log_file="$1/logs/$timestamp.log" -[ -d "$1" ] && mkdir -p "$1/logs" && exec > >(tee "$log_file") 2>&1 - -# Set working directory and current directory -if [ -d "$1" ]; then - WDIR="$1" -else - echo "Working directory not provided" - exit 1 -fi - -# File containing all patches -patch_file="$WDIR/chosen_patches.txt" - -# Returns if $1 is less than $2 -ver_less_than() { - # Strip letters from version name - ver1=$(echo $1 | sed 's/[a-zA-Z]*//g') - ver2=$(echo $2 | sed 's/[a-zA-Z]*//g') - [ $(echo $ver1$'\n'$ver2 | sort -V | tail -n1) != $ver1 ] && echo true || echo false -} - -# Make sure to work in the script directory -SDIR="$(dirname -- "$(readlink -f -- "$0")")" -cd "$SDIR" - -# Read the settings -if [ -f "$WDIR/build_settings" ]; then - source "$WDIR/build_settings" -else - if [ -f "./build_settings"]; then - cp ./build_settings "$WDIR/build_settings" - source ./build_settings - else - echo "Could not find the build_settings file!" - fi -fi - -# Get line numbers where included & excluded patches start from. -# We rely on the hardcoded messages to get the line numbers using grep -excluded_start="$(grep -n -m1 'EXCLUDE PATCHES' "$patch_file" | cut -d':' -f1)" -included_start="$(grep -n -m1 'INCLUDE PATCHES' "$patch_file" | cut -d':' -f1)" - -# Get everything but hashes from between the EXCLUDE PATCH & INCLUDE PATCH line -# Note: '^[^#[:blank:]]' ignores starting hashes and/or blank characters i.e, whitespace & tab excluding newline -excluded_patches="$(tail -n +$excluded_start $patch_file | head -n "$((included_start - excluded_start))" | grep '^[^#[:blank:]]')" - -# Get everything but hashes starting from INCLUDE PATCH line until EOF -included_patches="$(tail -n +$included_start $patch_file | grep '^[^#[:blank:]]')" - -# Array for storing patches -declare -a patches - -# Required artifacts in the format repository-name_filename -artifacts="revanced/revanced-cli:revanced-cli.jar revanced/revanced-integrations:revanced-integrations.apk revanced/revanced-patches:revanced-patches.jar inotia00/VancedMicroG:microg.apk" - -## Functions - -# Function for populating patches array, using a function here reduces redundancy & satisfies DRY principals -populate_patches() { - # Note: <<< defines a 'here-string'. Meaning, it allows reading from variables just like from a file - while read -r patch; do - patches+=("$1 $patch") - done <<<"$2" -} - -## Main - -# cleanup to fetch new revanced on next run -if [[ "$2" == "clean" ]]; then - rm -f revanced-cli.jar revanced-integrations.apk revanced-patches.jar - exit -fi - -if [[ "$2" == "experimental" ]]; then - EXPERIMENTAL="--experimental" -fi - -# Set flag to determine if a build should happen or not -flag=false -check_flag=false - -# Get inside the working directory -cd "$WDIR" -echo "$(date) | Starting check..." - -if [[ $2 != buildonly ]]; then - # Create a new versions file, if needed - [ -f versions.json ] || echo "{}" >versions.json - cp versions.json versions-new.json - # Fetch all the dependencies - try=0 - while :; do - try=$(($try + 1)) - [ $try -gt 10 ] && echo "API error!" && exit 2 - curl -s -X 'GET' 'https://releases.revanced.app/tools' -H 'accept: application/json' -o latest_versions.json - cat latest_versions.json | jq -e '.error' >/dev/null || break - echo "API failure, trying again. $((10 - $try)) tries left..." - sleep 10 - done - - for artifact in $artifacts; do - #Check for updates - repo=$(echo $artifact | cut -d ':' -f1) - name=$(echo $artifact | cut -d ':' -f2) - basename=$(echo $repo | cut -d '/' -f2) - echo "Checking $basename" - version_present=$(jq -r ".\"$basename\"" versions.json) - [[ "$version_present" == "null" ]] && version_present=0 - data="$(jq -r ".tools[] | select((.repository == \"$repo\") and (.content_type | contains(\"archive\")))" latest_versions.json)" - [[ $name == microg.apk ]] && version=$(curl -s "https://api.github.com/repos/$repo/releases/latest" | jq -r '.tag_name') || version=$(echo "$data" | jq -r '.version') - if [[ $(ver_less_than $version_present $version) == true || ! -f $name || $2 == force ]]; then - if [[ $2 == checkonly ]]; then - echo "[checkonly] $basename has an update ($version_present -> $version)" - check_flag=true - continue - fi - echo "Downloading $name" - [[ $name == microg.apk && -f $name && $2 != force ]] && microg_updated=true - # shellcheck disable=SC2086,SC2046 - [[ $name == microg.apk ]] && download_link="https://github.com/$repo/releases/latest/download/$name" || download_link="$(echo "$data" | jq -r '.browser_download_url')" - curl -sLo "$name" "$download_link" - jq ".\"$basename\" = \"$version\"" versions-new.json >versions-tmp.json && mv versions-tmp.json versions-new.json - echo "Upgraded $basename from $version_present to $version" - flag=true - fi - done - - [[ ! -f com.google.android.youtube.apk || ! -f com.google.android.apps.youtube.music.apk ]] && flag=true - - # Exit if no updates happened - if [[ $flag == false && $2 != force ]]; then - if [[ $check_flag == false ]]; then - echo "Nothing to update" - else - "$SDIR/download_apk.sh" "$WDIR" checkonly - fi - echo "--------------------"$'\n'"--------------------" - exit - fi - - # Download required apk files - "$SDIR/download_apk.sh" "$WDIR" -fi - -# If the variables are NOT empty, call populate_patches with proper arguments -[[ ! -z "$excluded_patches" ]] && populate_patches "-e" "$excluded_patches" -[[ ! -z "$included_patches" ]] && populate_patches "-i" "$included_patches" - -# Variable to flag errors -error=0 - -# Functions for building the APKs - -build_yt_nonroot() { - echo "************************************" - echo "Building YouTube APK" - echo "************************************" - if [ -f "com.google.android.youtube.apk" ]; then - echo "Building Non-root APK" - java -jar revanced-cli.jar -m revanced-integrations.apk -b revanced-patches.jar \ - ${patches[@]} \ - $EXPERIMENTAL \ - -a com.google.android.youtube.apk -o revanced-yt-nonroot.apk - else - echo "Cannot find YouTube APK, skipping build" - fi - echo "" - echo "************************************" - - # Rename files - mv revanced-yt-nonroot.apk YouTube_ReVanced_nonroot_$timestamp.apk || error=1 -} - -build_yt_root() { - echo "************************************" - echo "Building YouTube APK" - echo "************************************" - if [ -f "com.google.android.youtube.apk" ]; then - echo "Building Root APK" - java -jar revanced-cli.jar -m revanced-integrations.apk -b revanced-patches.jar --mount \ - -e microg-support ${patches[@]} \ - $EXPERIMENTAL \ - -a com.google.android.youtube.apk -o revanced-yt-root.apk - else - echo "Cannot find YouTube APK, skipping build" - fi - echo "" - echo "************************************" - - # Rename files - mv revanced-yt-root.apk YouTube_ReVanced_root_$timestamp.apk || error=1 -} - -build_ytm_nonroot() { - echo "Building YouTube Music APK" - echo "************************************" - if [ -f "com.google.android.apps.youtube.music.apk" ]; then - echo "Building Non-root APK" - java -jar revanced-cli.jar -m revanced-integrations.apk -b revanced-patches.jar \ - ${patches[@]} \ - $EXPERIMENTAL \ - -a com.google.android.apps.youtube.music.apk -o revanced-ytm-nonroot.apk - else - echo "Cannot find YouTube Music APK, skipping build" - fi - - # Rename files - mv revanced-ytm-nonroot.apk YouTube_Music_ReVanced_nonroot_$timestamp.apk || error=1 -} - -build_ytm_root() { - echo "Building YouTube Music APK" - echo "************************************" - if [ -f "com.google.android.apps.youtube.music.apk" ]; then - echo "Building Root APK" - java -jar revanced-cli.jar -m revanced-integrations.apk -b revanced-patches.jar --mount \ - -e microg-support ${patches[@]} \ - $EXPERIMENTAL \ - -a com.google.android.apps.youtube.music.apk -o revanced-ytm-root.apk - else - echo "Cannot find YouTube Music APK, skipping build" - fi - - # Rename files - mv revanced-ytm-root.apk YouTube_Music_ReVanced_root_$timestamp.apk || error=1 -} - -telegram_send_msg() { - # telegram.sh uses bot account, but it supports formatted messages - [[ "$TELEGRAM_TOKEN" == "" || "$TELEGRAM_CHAT" == "" ]] && echo "Please provide valid channel address in the settings!" - ./telegram.sh -t "$TELEGRAM_TOKEN" -c "$TELEGRAM_CHAT" -T "⚙⚙⚙ Build Details ⚙⚙⚙" -M "$1"$'\n'"Timestamp: $timestamp"$'\n'"⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯" -} - -gotify_send_msg() { - curl -s -X POST "$GOTIFY_URL/message?token=$GOTIFY_TOKEN" \ - -F "title=⚙⚙⚙ Build Details ⚙⚙⚙" -F "message=$1" -F "priority=5" -} - -ntfy_send_msg() { - curl -s -H "Icon: https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Revanced-logo-round.svg/240px-Revanced-logo-round.svg.png" \ - -H "Title: ⚙⚙⚙ ReVanced Build ⚙⚙⚙" \ - -d "$1" \ - "$NTFY_URL/$NTFY_TOPIC" -} - -# Check the config and build accordingly -$YT_NONROOT && build_yt_nonroot -$YT_ROOT && build_yt_root -$YTM_NONROOT && build_ytm_nonroot -$YTM_ROOT && build_ytm_root - -# Send telegram message about the new build - -if [ $error == 1 ]; then - echo "There was an error while building!" - msg="There was an error during the build process! Please take a look at the logs."$'\n'"Timestamp: $timestamp" - - $TG_NOTIFICATIONS && telegram_send_msg "$msg" - $GOTIFY_NOTIFICATIONS && gotify_send_msg "$msg" - $NTFY_NOTIFICATIONS && ntfy_send_msg "$msg" - - [[ $2 != buildonly ]] && mv versions-new.json versions-fail.json || rm versions-new.json - exit 4 -else - mv versions-new.json versions.json -fi - -if $TG_UPLOAD; then - echo "Uploading to telegram" - # telegram-upload uses personal account, hence bypassing 50 MB max upload limit of bots - [ "$CHANNEL_ADDRESS" == "" ] && echo "Please provide valid channel address in the settings!" - /home/sintan/.local/bin/telegram-upload YouTube_ReVanced_nonroot_$timestamp.apk YouTube_Music_ReVanced_nonroot_$timestamp.apk --to "$CHANNEL_ADDRESS" --caption "" && sent=true -fi - -# Create the message to be sent -msg=$(cat versions.json | tail -n+2 | head -n-1 | cut -c3- | sed "s/\"//g" | sed "s/,//g" | sed "s/com.google.android.apps.youtube.music/YouTube Music/" | - sed "s/com.google.android.youtube/YouTube/" | sed "s/VancedMicroG/Vanced microG/" | sed "s/revanced-/ReVanced /g" | sed "s/patches/Patches/" | - sed "s/cli/CLI/" | sed "s/integrations/Integrations/" | awk 1 ORS=$'\n') # I know, it's a hacky solution - -if $TG_NOTIFICATIONS; then - echo "Sending messages to telegram" - telegram_send_msg "$msg" - [ $microg_updated ] && telegram_send_msg "_An update of microg was published._" -fi - -if $GOTIFY_NOTIFICATIONS; then - echo "Sending messages to Gotify" - MESSAGE="$msg"$'\n'"Timestamp: $timestamp" - gotify_send_msg "$MESSAGE" - [ $microg_updated ] && gotify_send_msg "An update of microg was published." -fi - -if $NTFY_NOTIFICATIONS; then - echo "Sending messages to ntfy.sh" - MESSAGE="$msg"$'\n'"Timestamp: $timestamp" - ntfy_send_msg "$MESSAGE" - [ $microg_updated ] && ntfy_send_msg "An update of microg was published." -fi - -# Do some cleanup, keep only the last 3 build's worth of files and a week worth of logs -mkdir -p archive -mv *ReVanced_*_$timestamp.apk archive/ -find ./archive -maxdepth 1 -type f -printf '%Ts\t%P\n' | - sort -rn | - tail -n +7 | - cut -f2- | - xargs -r -I {} rm "./archive/{}" -find ./logs -mtime +7 -exec rm {} \; - -# Run a custom post script, if available -[ -f post_script.sh ] && ./post_script.sh $timestamp - -echo "Done!"$'\n'"************************************" diff --git a/download_apk.sh b/download_apk.sh deleted file mode 100755 index 70a8b58..0000000 --- a/download_apk.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash - -declare -A apks - -apks["com.google.android.youtube"]=dl_yt -apks["com.google.android.apps.youtube.music"]=dl_ytm - -flag=$2 - -# Read the settings -source "$1/build_settings" - -## Functions - -# Wget user agent -WGET_HEADER="User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0" - -# Wget function -req() { wget -nv -4 -O "$2" --header="$WGET_HEADER" "$1"; } - -# Returns true if $1 is less than $2 -ver_less_than() { - [[ ${1:0:1} == "v" ]] && var1=${1:1} || var1=$1 - [[ ${2:0:1} == "v" ]] && var2=${2:1} || var2=$2 - [[ $(echo $var1$'\n'$var2 | sort -V | tail -n1) != $var1 ]] && echo true || echo false -} - -# APKPure Download function -dl_apkpure() { - version="$1" - app="$2" - apkpure_appname="$3" - $hard_vers && best_match="$version" || best_match="$(apkpure_best_match $version $app $apkpure_appname)" - - # if [[ "$version" == "$best_match" || "$version" == "latest" ]]; then - # echo "Downloading version $best_match from APKPure" - # else - # echo "Unable to get version $version, downloading version $best_match instead" - # fi - - vers_code="$(req https://apkpure.com/$apkpure_appname/$app/versions - | htmlq --attribute data-dt-versioncode 'a[data-dt-version="'$version'"][data-dt-apkid^="b\/APK\/"]')" - url="https://d.apkpure.com/b/APK/$app?versionCode=$vers_code" - - req "$url" "$app.apk" - echo "$url" -} - -# Get the best match even if the desired version isn't there -# OUtputs the latest version with supplied version 0 -apkpure_best_match() { - version="$1" - app="$2" - apkpure_appname="$3" - - vers_list=$(req https://apkpure.com/$apkpure_appname/$app/versions - | htmlq --attribute data-dt-version 'a[data-dt-apkid^="b\/APK\/"]') - if [[ "$version" == "latest" ]]; then - match="$(echo "$vers_list" | head -1)" - elif $(echo "$vers_list" | grep -q "$version"); then - match="$version" - else - match="$(echo "$vers_list"$'\n'"$version" | sort -V | grep -B 1 "$version" | head -1)" - fi - - echo "$match" -} - -# Downloading youtube -dl_yt() { - appname=com.google.android.youtube - $hard_vers || version="$(apkpure_best_match "$version" $appname youtube)" - if [[ ! $(ver_less_than "$version_present" "$version") && -f $appname.apk ]]; then - echo "Version $version is already present" - return - fi - - if [[ $flag == checkonly ]]; then - echo "[checkonly] YouTube has an update ($version_present -> $version)" - return - fi - echo "Downloading YouTube" - - echo "Choosing version $version" - declare -r dl_url=$(dl_apkpure "$version" $appname youtube) - echo "YouTube version: $version" - echo "downloaded from: [APKMirror - YouTube]($dl_url)" - jq ".\"$apk\" = \"$version\"" versions.json >versions-tmp.json && mv versions-tmp.json versions-new.json -} - -# Downloading youtube music -dl_ytm() { - appname=com.google.android.apps.youtube.music - $hard_vers || version="$(apkpure_best_match "$version" $appname youtube-music)" - if [[ ! $(ver_less_than "$version_present" "$version") && -f $appname.apk ]]; then - echo "Version $version is already present" - return - fi - - if [[ $flag == checkonly ]]; then - echo "[checkonly] YouTube Music has an update ($version_present -> $version)" - return - fi - echo "Downloading YouTube Music" - - echo "Choosing version '${version}'" - # declare -r dl_url=$(dl_apkpure "$version" $appname youtube-music) - dl_apkpure "$version" $appname youtube-music - echo "YouTube Music version: $version" - echo "downloaded from: [APKMirror - YouTube Music]($dl_url)" - jq ".\"$apk\" = \"$version\"" versions.json >versions-tmp.json && mv versions-tmp.json versions-new.json -} - -# Get into the build directory - -if [ -d "$1" ]; then - cd "$1" -else - echo "Working directory not provided" - exit -1 -fi - -## Main -try=0 -while :; do - try=$(($try + 1)) - [ $try -gt 10 ] && echo "API error!" && exit 3 - curl -X 'GET' 'https://releases.revanced.app/patches' -H 'accept: application/json' -o patches.json - cat patches.json | jq -e '.error' >/dev/null 2>&1 || break - echo "API failure, trying again. $((10 - $try)) tries left..." - sleep 10 -done - -for apk in "${!apks[@]}"; do - # Skip if app not specified for build - [[ "$apk" == "com.google.android.youtube" && "$YT_NONROOT" == false && "$YT_ROOT" == false ]] && continue - [[ "$apk" == "com.google.android.apps.youtube.music" && "$YTM_NONROOT" == false && "$YTM_ROOT" == false ]] && continue - echo "Checking $apk" - if [[ "$apk" == "com.google.android.youtube" && "$YT_VERSION" != "" ]]; then - version="$YT_VERSION" - echo "Using version $version for $apk given in build_settings" - hard_vers=true - elif [[ "$apk" == "com.google.android.apps.youtube.music" && "$YTM_VERSION" != "" ]]; then - version="$YTM_VERSION" - echo "Using version $version for $apk given in build_settings" - hard_vers=true - else - echo "Figuring out best version for $apk" - supported_vers="$(jq -r '.[].compatiblePackages[] | select(.name == "'$apk'") | .versions | last' patches.json)" - version=0 - for vers in $supported_vers; do - [ $vers != "null" ] && [[ $(ver_less_than $vers $version) == true || $version == 0 ]] && version=$vers - done - hard_vers=false - fi - - version_present=$(jq -r ".\"$apk\"" versions.json) - [[ -z "$version_present" || "$version" == "null" ]] && version_present=0 - [[ "$version" == "0" ]] && version=latest - - [[ "$version_present" != "$version" || ! -f $apk.apk || $2 == force ]] && ${apks[$apk]} || echo "Recommended version ($version_present) of "$apk" is already present" -done From 5957b44444dfae6b5390cbd9f780af3b13ed4e1f Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 15:49:03 -0500 Subject: [PATCH 12/17] new: Add shebang and SPDX headers --- APKPure_dl.py | 5 +++++ Cleanup.py | 5 +++++ JAVABuilder.py | 5 +++++ Notifications.py | 5 +++++ ReVancedBuilder.py | 4 +++- 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/APKPure_dl.py b/APKPure_dl.py index 069e557..e4480c6 100644 --- a/APKPure_dl.py +++ b/APKPure_dl.py @@ -1,3 +1,8 @@ +#!/usr/bin/env python3\ + +# SPDX-FileCopyrightText: 2023 Sayantan Santra +# SPDX-License-Identifier: GPL-3.0-only + import os import sys import json diff --git a/Cleanup.py b/Cleanup.py index ee661fe..2be3d2b 100644 --- a/Cleanup.py +++ b/Cleanup.py @@ -1,3 +1,8 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: 2023 Sayantan Santra +# SPDX-License-Identifier: GPL-3.0-only + import os import sys from Notifications import send_notif diff --git a/JAVABuilder.py b/JAVABuilder.py index 84456e4..e7c91eb 100644 --- a/JAVABuilder.py +++ b/JAVABuilder.py @@ -1,3 +1,8 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: 2023 Sayantan Santra +# SPDX-License-Identifier: GPL-3.0-only + import os import sys import configparser as cp diff --git a/Notifications.py b/Notifications.py index 8375e32..5c26370 100644 --- a/Notifications.py +++ b/Notifications.py @@ -1,3 +1,8 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: 2023 Sayantan Santra +# SPDX-License-Identifier: GPL-3.0-only + import json import re import requests as req diff --git a/ReVancedBuilder.py b/ReVancedBuilder.py index 92456c5..b3c4b5e 100755 --- a/ReVancedBuilder.py +++ b/ReVancedBuilder.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2023 Sayantan Santra +# SPDX-License-Identifier: GPL-3.0-only + import sys import os import configparser as cp @@ -17,7 +20,6 @@ import subprocess # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) # TODO: Install using pip -# TODO: Do not download twice for root and nonroot # Update the ReVanced tools, if needed def update_tools(appstate): From 4c847893b85f0b3ce9b3e44b1048cc17f34e57cf Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 17:57:30 -0500 Subject: [PATCH 13/17] feat: Installable using pipx --- .gitignore | 1 + pyproject.toml | 18 ++++++++++++++++ requirements.txt | 4 ---- .../ReVancedBuilder/APKPure_dl.py | 4 +++- Cleanup.py => src/ReVancedBuilder/Cleanup.py | 5 +++-- .../ReVancedBuilder/JAVABuilder.py | 3 ++- .../ReVancedBuilder/Notifications.py | 0 .../ReVancedBuilder/ReVancedBuilder.py | 21 ++++++++++--------- 8 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 pyproject.toml delete mode 100644 requirements.txt rename APKPure_dl.py => src/ReVancedBuilder/APKPure_dl.py (98%) rename Cleanup.py => src/ReVancedBuilder/Cleanup.py (96%) rename JAVABuilder.py => src/ReVancedBuilder/JAVABuilder.py (98%) rename Notifications.py => src/ReVancedBuilder/Notifications.py (100%) rename ReVancedBuilder.py => src/ReVancedBuilder/ReVancedBuilder.py (94%) diff --git a/.gitignore b/.gitignore index 2228d0b..244f09d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ patches.txt .directory .venv/ __pycache__/ +ReVancedBuilder.egg-info/ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..439366b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,18 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "ReVancedBuilder" +authors = [{ name = "Sayantan Santra", email = "sayantan.santra689@gmail.com" }] +description = "A tool to automatically build latest releases of ReVanced apps" +readme = "README.md" +requires-python = ">=3.10" +keywords = ["revanced", "patch"] +license = { file = "LICENSE" } +classifiers = ["Programming Language :: Python :: 3"] +dependencies = ["requests", "packaging", "bs4"] +version = "1.0" + +[project.scripts] +ReVancedBuilder = "ReVancedBuilder:ReVancedBuilder" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d8c6174..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -requests -semver -packaging -bs4 \ No newline at end of file diff --git a/APKPure_dl.py b/src/ReVancedBuilder/APKPure_dl.py similarity index 98% rename from APKPure_dl.py rename to src/ReVancedBuilder/APKPure_dl.py index e4480c6..598ed45 100644 --- a/APKPure_dl.py +++ b/src/ReVancedBuilder/APKPure_dl.py @@ -6,10 +6,12 @@ import os import sys import json + from packaging.version import Version import requests as req from bs4 import BeautifulSoup as bs -from Cleanup import clean_exit + +from ReVancedBuilder.Cleanup import clean_exit # Determine the best version available to download def apkpure_best_match(version, soup): diff --git a/Cleanup.py b/src/ReVancedBuilder/Cleanup.py similarity index 96% rename from Cleanup.py rename to src/ReVancedBuilder/Cleanup.py index 2be3d2b..3adfb38 100644 --- a/Cleanup.py +++ b/src/ReVancedBuilder/Cleanup.py @@ -5,9 +5,10 @@ import os import sys -from Notifications import send_notif import time +from ReVancedBuilder.Notifications import send_notif + # Move apps to proper location def move_apps(appstate): build_config = appstate['build_config'] @@ -63,4 +64,4 @@ def clean_exit(msg, appstate, code=1): # Delete the lockfile os.remove('lockfile') - exit(code) \ No newline at end of file + sys.exit(code) \ No newline at end of file diff --git a/JAVABuilder.py b/src/ReVancedBuilder/JAVABuilder.py similarity index 98% rename from JAVABuilder.py rename to src/ReVancedBuilder/JAVABuilder.py index e7c91eb..a6021ad 100644 --- a/JAVABuilder.py +++ b/src/ReVancedBuilder/JAVABuilder.py @@ -7,9 +7,10 @@ import os import sys import configparser as cp import json -from Cleanup import clean_exit import subprocess +from ReVancedBuilder.Cleanup import clean_exit + # Build the revanced apps def build_apps(appstate): build_config = appstate['build_config'] diff --git a/Notifications.py b/src/ReVancedBuilder/Notifications.py similarity index 100% rename from Notifications.py rename to src/ReVancedBuilder/Notifications.py diff --git a/ReVancedBuilder.py b/src/ReVancedBuilder/ReVancedBuilder.py similarity index 94% rename from ReVancedBuilder.py rename to src/ReVancedBuilder/ReVancedBuilder.py index b3c4b5e..80b5f16 100755 --- a/ReVancedBuilder.py +++ b/src/ReVancedBuilder/ReVancedBuilder.py @@ -6,20 +6,21 @@ import sys import os import configparser as cp -import requests as req import json -from packaging.version import Version -from APKPure_dl import * -from JAVABuilder import * -from datetime import datetime -from Notifications import send_notif -from Cleanup import * import logging import subprocess +import requests as req +from packaging.version import Version +from datetime import datetime + +from ReVancedBuilder.APKPure_dl import apkpure_best_match, apkpure_dl, get_apks +from ReVancedBuilder.JAVABuilder import build_apps +from ReVancedBuilder.Notifications import send_notif +from ReVancedBuilder.Cleanup import move_apps, clean_exit + # TODO: README # TODO: PATCHES_GUIDE.md (maybe delete it?) -# TODO: Install using pip # Update the ReVanced tools, if needed def update_tools(appstate): @@ -92,9 +93,9 @@ appstate['timestamp'] = time.strftime('%Y%m%d%H%M%S') try: os.chdir(sys.argv[1]) except IndexError: - clean_exit('Please provide a working directory as argument!', appstate) + sys.exit('Please provide a working directory as argument!') except FileNotFoundError: - clean_exit('Invalid working directory provided!', appstate) + sys.exit('Invalid working directory provided!') # Try to make sure only one instance is running in a given working directory try: From d760c511bae80b2dcfe798601e16aa5701204474 Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 18:27:47 -0500 Subject: [PATCH 14/17] fix: pip issue --- src/ReVancedBuilder/ReVancedBuilder.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ReVancedBuilder/ReVancedBuilder.py b/src/ReVancedBuilder/ReVancedBuilder.py index 80b5f16..311bf98 100755 --- a/src/ReVancedBuilder/ReVancedBuilder.py +++ b/src/ReVancedBuilder/ReVancedBuilder.py @@ -189,4 +189,6 @@ elif flag != ['checkonly']: pass # Delete the lockfile -os.remove('lockfile') \ No newline at end of file +os.remove('lockfile') + +sys.exit(0) \ No newline at end of file From 086effe1b1c659b2ee2219aaf9630e43b68bc74b Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 18:29:21 -0500 Subject: [PATCH 15/17] doc: Clean the TODO tags --- src/ReVancedBuilder/JAVABuilder.py | 2 +- src/ReVancedBuilder/Notifications.py | 1 - src/ReVancedBuilder/ReVancedBuilder.py | 5 +---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ReVancedBuilder/JAVABuilder.py b/src/ReVancedBuilder/JAVABuilder.py index a6021ad..f9a18bc 100644 --- a/src/ReVancedBuilder/JAVABuilder.py +++ b/src/ReVancedBuilder/JAVABuilder.py @@ -85,7 +85,7 @@ def build_apps(appstate): clean_exit(f"There was an error while building {pretty_name}!\n{e}", appstate) try: - os.rename(output_name+'.apk', output_name+'.apk') # TODO: Add timestamp here + os.rename(output_name+'.apk', output_name+'.apk') except FileNotFoundError: clean_exit(f"There was an error while building {pretty_name}!", appstate) \ No newline at end of file diff --git a/src/ReVancedBuilder/Notifications.py b/src/ReVancedBuilder/Notifications.py index 5c26370..8d577f2 100644 --- a/src/ReVancedBuilder/Notifications.py +++ b/src/ReVancedBuilder/Notifications.py @@ -75,7 +75,6 @@ def send_notif(appstate, error=False): print('Failed!' + str(e)) case 'telegram': - # TODO: Finish this! print('Sending notification through Telegram...') try: chat = config[entry]['chat'] diff --git a/src/ReVancedBuilder/ReVancedBuilder.py b/src/ReVancedBuilder/ReVancedBuilder.py index 311bf98..868f1c2 100755 --- a/src/ReVancedBuilder/ReVancedBuilder.py +++ b/src/ReVancedBuilder/ReVancedBuilder.py @@ -19,9 +19,6 @@ from ReVancedBuilder.JAVABuilder import build_apps from ReVancedBuilder.Notifications import send_notif from ReVancedBuilder.Cleanup import move_apps, clean_exit -# TODO: README -# TODO: PATCHES_GUIDE.md (maybe delete it?) - # Update the ReVanced tools, if needed def update_tools(appstate): for item in ['revanced-cli', 'revanced-integrations', 'revanced-patches']: @@ -191,4 +188,4 @@ elif flag != ['checkonly']: # Delete the lockfile os.remove('lockfile') -sys.exit(0) \ No newline at end of file +sys.exit(0) From e57d316969649c6188585774553ac1ee2c475c1d Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 18:46:12 -0500 Subject: [PATCH 16/17] new: Added example config files --- build_settings | 45 ----------------------- chosen_patches.txt | 3 -- example_configs/build_config | 51 ++++++++++++++++++++++++++ example_configs/chosen_patches | 4 ++ example_configs/notification_config | 25 +++++++++++++ src/ReVancedBuilder/APKPure_dl.py | 2 +- src/ReVancedBuilder/JAVABuilder.py | 4 +- src/ReVancedBuilder/ReVancedBuilder.py | 4 +- 8 files changed, 85 insertions(+), 53 deletions(-) delete mode 100644 build_settings delete mode 100644 chosen_patches.txt create mode 100644 example_configs/build_config create mode 100644 example_configs/chosen_patches create mode 100644 example_configs/notification_config diff --git a/build_settings b/build_settings deleted file mode 100644 index bb8edb9..0000000 --- a/build_settings +++ /dev/null @@ -1,45 +0,0 @@ -# These are the currently supported apps that can be built -# Make a copy of this to your working directory -# Then change the default values to enable/disable building them -YT_NONROOT=true -YTM_NONROOT=true -YT_ROOT=false -YTM_ROOT=false - -# You can provide versions of apk for the builds -# If anything nonempty is given, automatic version resolution -# will be disabled -# It's your job to make sure that the version is available -# in APKPure -YT_VERSION= -YTM_VERSION= - -# Settings for sending Telegram notification using telegram.sh -# In case you decide to use it, please put valid config in the -# TOKEN and CHAT fields -# Check out README for instructions -TG_NOTIFICATIONS=false -TELEGRAM_TOKEN="" -TELEGRAM_CHAT="" - -# Settings for uploading the files through telegram-upload -# In case you decide to use it, please put valid config in the -# CHANNEL_ADDRESS field -# Check out README for instructions -TG_UPLOAD=false -CHANNEL_ADDRESS="" - -# Settings for sending Gotify notifications -# In case you decide to use it, please put valid config in the -# URL and TOKEN fields -# Check out README for instructions -GOTIFY_NOTIFICATIONS=false -GOTIFY_URL="https://push.example.com" -GOTIFY_TOKEN="" - -# Settings for sending ntfy.sh notifications -# In case you decide to use it, please put valid config in the -# URL and TOPIC fields -NTFY_NOTIFICATIONS=false -NTFY_URL="https://ntfy.sh" -NTFY_TOPIC="" diff --git a/chosen_patches.txt b/chosen_patches.txt deleted file mode 100644 index e7103e5..0000000 --- a/chosen_patches.txt +++ /dev/null @@ -1,3 +0,0 @@ -# EXCLUDE PATCHES FROM BELOW. DO NOT REMOVE THIS LINE - -# INCLUDE PATCHES FROM BELOW. DO NOT REMOVE THIS LINE diff --git a/example_configs/build_config b/example_configs/build_config new file mode 100644 index 0000000..9e75d10 --- /dev/null +++ b/example_configs/build_config @@ -0,0 +1,51 @@ +# List all the applications to be built in their separate sections. +# The version part is optional. If provided, automatic version determination +# will be turned off. In that case, you're responsible for ensuring that the +# version is present in APKPure.com + +[youtube_nonroot] +build = true +pretty_name = YouTube +apk = com.google.android.youtube +apkpure_appname = youtube +root = false +# Timestamp and extension will be added automatically +output_name = YouTube_ReVanced_nonroot +keystore = revanced-yt-nonroot.keystore +# version = version + +[youtube_root] +build = false +pretty_name = YouTube (root) +apk = com.google.android.youtube +apkpure_appname = youtube +root = true +# Timestamp and extension will be added automatically +output_name = YouTube_ReVanced_root +keystore = revanced-yt-root.keystore +# version = "version" + +[youtube_music] +build = true +pretty_name = YouTube Music +apk = com.google.android.apps.youtube.music +apkpure_appname = youtube-music +root = false +# Timestamp and extension will be added automatically +output_name = YouTube_Music_ReVanced_nonroot +keystore = revanced-ytm-nonroot.keystore +version = 6.10.52 + +[youtube_music_root] +build = false +pretty_name = YouTube Music (root) +apk = com.google.android.apps.youtube.music +apkpure_appname = youtube-music +root = true +# Timestamp and extension will be added automatically +output_name = YouTube_Music_ReVanced_root +keystore = revanced-ytm-root.keystore +version = 6.10.52 + +[post_script] +# file = post_script.sh diff --git a/example_configs/chosen_patches b/example_configs/chosen_patches new file mode 100644 index 0000000..c247462 --- /dev/null +++ b/example_configs/chosen_patches @@ -0,0 +1,4 @@ +[patches] +# Both have to be comma separated lists of patches +included = [] +excluded = [] diff --git a/example_configs/notification_config b/example_configs/notification_config new file mode 100644 index 0000000..3770d4a --- /dev/null +++ b/example_configs/notification_config @@ -0,0 +1,25 @@ +[telegram] +# Settings for sending Telegram notification using telegram.sh +# In case you decide to use it, please put valid config in the +# TOKEN and CHAT fields +# Check out README for instructions +# enabled = true +# chat = url +# token = token + +[gotify] +# Settings for sending Gotify notifications +# In case you decide to use it, please put valid config in the +# URL and TOKEN fields +# Check out README for instructions +# enabled = true +# URL = url +# token = token + +[ntfy] +# Settings for sending ntfy.sh notifications +# In case you decide to use it, please put valid config in the +# URL and TOPIC fields +enabled = false +url = url +topic = topic diff --git a/src/ReVancedBuilder/APKPure_dl.py b/src/ReVancedBuilder/APKPure_dl.py index 598ed45..9be5545 100644 --- a/src/ReVancedBuilder/APKPure_dl.py +++ b/src/ReVancedBuilder/APKPure_dl.py @@ -88,7 +88,7 @@ def get_apks(appstate): pretty_name = build_config[app]['pretty_name'] apkpure_appname = build_config[app]['apkpure_appname'] except: - clean_exit(f"Invalid config for {app} in build_config.toml!", appstate) + clean_exit(f"Invalid config for {app} in build_config!", appstate) print(f"Checking {pretty_name}...") try: diff --git a/src/ReVancedBuilder/JAVABuilder.py b/src/ReVancedBuilder/JAVABuilder.py index f9a18bc..fd7531f 100644 --- a/src/ReVancedBuilder/JAVABuilder.py +++ b/src/ReVancedBuilder/JAVABuilder.py @@ -18,7 +18,7 @@ def build_apps(appstate): print = appstate['logger'].info chosen_patches = cp.ConfigParser() - chosen_patches.read('chosen_patches.toml') + chosen_patches.read('chosen_patches') try: included_patches = json.loads(chosen_patches['patches']['included']) @@ -66,7 +66,7 @@ def build_apps(appstate): apkpure_appname = build_config[app]['apkpure_appname'] output_name = build_config[app]['output_name'] except: - clean_exit(f"Invalid config for {app} in build_config.toml!", appstate) + clean_exit(f"Invalid config for {app} in build_config!", appstate) cmd += f" -a {apk}.apk -o {output_name}.apk" diff --git a/src/ReVancedBuilder/ReVancedBuilder.py b/src/ReVancedBuilder/ReVancedBuilder.py index 868f1c2..6a90b71 100755 --- a/src/ReVancedBuilder/ReVancedBuilder.py +++ b/src/ReVancedBuilder/ReVancedBuilder.py @@ -135,12 +135,12 @@ print('----------------------------------------------------------------------') # Read configs try: appstate['build_config']=cp.ConfigParser() - appstate['build_config'].read_file(open('build_config.toml', 'r')) + appstate['build_config'].read_file(open('build_config', 'r')) except FileNotFoundError: clean_exit('No build config provided, exiting. Please look at the GitHub page for more information:\n https://github.com/SinTan1729/ReVancedBuilder', appstate) appstate['notification_config'] = cp.ConfigParser() -appstate['notification_config'].read('notification_config.toml') +appstate['notification_config'].read('notification_config') # Pull the latest information using the ReVanced API try: From 5987dd3dc38c9240404e238a5023067f09af943c Mon Sep 17 00:00:00 2001 From: SinTan1729 Date: Thu, 10 Aug 2023 18:58:44 -0500 Subject: [PATCH 17/17] docs: Update README --- PATCHES_GUIDE.md | 47 ------------------------------------ README.md | 34 +++++++++++++------------- example_configs/build_config | 4 +-- 3 files changed, 19 insertions(+), 66 deletions(-) delete mode 100644 PATCHES_GUIDE.md diff --git a/PATCHES_GUIDE.md b/PATCHES_GUIDE.md deleted file mode 100644 index 1fabc8a..0000000 --- a/PATCHES_GUIDE.md +++ /dev/null @@ -1,47 +0,0 @@ -# Customizing ReVanced Builds - -**Please read the following information before beginning.** - -By default the script will build ReVanced with ALL default* patches. Copy `chosen_patches.txt` inside your provided working directory and edit it to customize your build of ReVanced. - -*Default: All patches except those which have to be ***included*** explicitly, i.e, using the `-i` flag while manually using the ReVanced CLI - -## !IMPORTANT! -1. Each patch name MUST start from a NEWLINE AND there should be only ONE patch PER LINE -2. DO NOT add any other type of symbol or character, it will break the script! You have been warned! -3. Anything starting with a hash (`#`) will be ignored. Also, do not add hash or any other character after a patch's name -4. Both YT Music ReVanced & YT ReVanced are supported -5. DO NOT add `microg-patch` to the list of excluding patches. -6. `patches.txt` contains some predefined lines starting with `#`. DO NOT remove them. - -## Example -Example content of `patches.txt`: - -- Exclude pure black theme and keep `create` button: -``` -amoled -disable-create-button -``` - -- Exclude patches for both Music & YouTube (order doesn't matter) -``` -amoled -exclusive-background-playback -disable-create-button -premium-heading -tasteBuilder-remover -``` - -- Include patches for both Music & YouTube (order doesn't matter) -``` -compact-header -hdr-auto-brightness -autorepeat-by-default -enable-debugging -force-vp9-codec -enable-wide-searchbar -``` - -## List of Available Patches - -Refer to Official ReVanced [list of available patches](https://github.com/revanced/revanced-patches#list-of-available-patches). diff --git a/README.md b/README.md index 04fdf82..e08eafe 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,19 @@ # Revanced Builder -This repo will allow one to build [ReVanced](https://github.com/revanced/) apps automatically and post it to a telegram channel to access and possibly share the builds with friends. It uses [Gotify](https://gotify.net), [ntfy.sh](https://ntfy.sh) or [telegram.sh](https://github.com/fabianonline/telegram.sh) to send messages and [telegram-upload](https://github.com/Nekmo/telegram-upload) to upload files (optionally, disabled out by default). Make sure that `Java >=17` is installed and selected as default. +This repo will allow one to build [ReVanced](https://github.com/revanced/) apps automatically and send notifications and possibly share the builds with friends. It uses [Gotify](https://gotify.net), [ntfy.sh](https://ntfy.sh) or [telegram.sh](https://github.com/fabianonline/telegram.sh) to send messages. Make sure that `Java >=17` is installed and selected as default. +## Installation +Recommended way is to use [`pipx`](https://github.com/pypa/pipx) to install the program. +``` +pipx install git+https://github.com/SinTan1729/ReVancedBuilder +``` ## How to use -Just run `./build_revanced (force/clean/experimental/checkonly/buildonly)`. Might be a good idea to set it up to run periodically. There are a few ways of doing it. +Just run `ReVancedBuilder (force/experimental/checkonly/buildonly)`. + +It might be a good idea to set it up to run periodically. There are a few ways of doing it. 1. Just drop it inside `/etc/cron.daily/`. 1. To make it run at a specific time (6AM in the example) using `cron`, put this in your `crontab`: ``` - 0 6 * * * + 0 6 * * * ``` 1. The exact same thing as in 2 can be achieved using `systemd` timers instead. Create the following files. ``` @@ -22,7 +29,7 @@ Just run `./build_revanced (force/clean/experimental/checkon User= Group= Environment="_JAVA_OPTIONS=-Xmx512m" - ExecStart= + ExecStart= ``` ``` /etc/systemd/system/revanced-builder.timer @@ -42,19 +49,12 @@ Just run `./build_revanced (force/clean/experimental/checkon ``` ## Notes -- The following programs are needed to run this script. Make sure that you have them in your `$PATH`. - ``` - htmlq jq wget java curl - ``` -- To enable build for a particular apk, copy the `build_settings` file to your working directory and modify it to suit your needs. -- The script will download the **automatically selected compatible version** (using compatibility of patches as listed [here](https://github.com/revanced/revanced-patches#list-of-available-patches)) of Youtube on APKPure, **NOT** latest official version on Google Play. +- If you installed it using `pipx`, you can figure out the full location of the program by running `which ReVancedBuilder`. +- This app needs some config files to run. Download all the config files inside `exampl_configs` directory, namely `build_config`, `chosen_patches` (optional), and `notification_config` (optional, needed only if you want to send notifications) and move them to your working directory. Then, you should modify these files to your liking. +- The script will download the **automatically selected compatible version** (unless version is specified in `build_config`) (using compatibility of patches as listed [here](https://github.com/revanced/revanced-patches#list-of-available-patches)) of Youtube on APKPure, **NOT** latest official version on Google Play. - Under **NO CIRCUMSTANCES** any APKs will be uploaded to this repository to avoid DMCA. -- If you enable the Gotify, ntfy or telegram notifications or uploads, make sure to fill up the config options inside the `build_settings` file. For more information about the config, take at look at the repos of `telegram.sh` and `telegram-upload` provided above. -- It can also run a post script (if exists) called `post_script.sh`. The `timestamp` is passed as `$1`. -- In the current configuration, the script only builds YouTube ReVanced and YouTube Music ReVanced (both nonroot), but it's easy to add support for any other ReVanced app. The code for root builds is included but disabled by default. +- If you enable telegram notifications, make sure to fill up the config options inside the `build_config` file. For more information about the config, take at look at the repos of `telegram.sh` and `telegram-upload` provided above. +- It can also run a post script (if exists), specified in the `build_config` file. The `timestamp` is passed as `$1`. +- In the current configuration, the script only builds YouTube ReVanced and YouTube Music ReVanced (both nonroot), but it's easy to add support for any other ReVanced app using the `build_config` file. The config files are self-explanatory. - All the packages are pulled from [APKPure](https://apkpure.com) and GitHub (the `revanced/*` repos). -## Customize your build -If you wish to continue with the default settings, you may skip this step. - -By default this will build ReVanced with ALL available patches. Follow [this guide](PATCHES_GUIDE.md) to exclude/customizing patches for your build. diff --git a/example_configs/build_config b/example_configs/build_config index 9e75d10..e7fa720 100644 --- a/example_configs/build_config +++ b/example_configs/build_config @@ -34,7 +34,7 @@ root = false # Timestamp and extension will be added automatically output_name = YouTube_Music_ReVanced_nonroot keystore = revanced-ytm-nonroot.keystore -version = 6.10.52 +# version = version [youtube_music_root] build = false @@ -45,7 +45,7 @@ root = true # Timestamp and extension will be added automatically output_name = YouTube_Music_ReVanced_root keystore = revanced-ytm-root.keystore -version = 6.10.52 +# version = version [post_script] # file = post_script.sh