forked from distok/cutthecord
parent
25c8a5b2d4
commit
8f698e4899
5 changed files with 301 additions and 3 deletions
1
ctcci/.gitignore
vendored
Normal file
1
ctcci/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
ctcconfig.py
|
203
ctcci/ctcci.py
Normal file
203
ctcci/ctcci.py
Normal file
|
@ -0,0 +1,203 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import json
|
||||
import subprocess
|
||||
from ctcconfig import *
|
||||
|
||||
print("Welcome to CutTheCord CI :)")
|
||||
|
||||
BRANCH = sys.argv[1]
|
||||
PATCHES = sys.argv[2:]
|
||||
FORCE = False
|
||||
DEFAULT_PATCHES = ["necessary", "branding", "customversion"]
|
||||
OPTIONAL_PATCHES = ["necessary", "blobs"]
|
||||
|
||||
|
||||
def patch(patch_file, workdir, patch_name=""):
|
||||
if not os.path.exists(patch_file):
|
||||
# Allow missing optional patches
|
||||
if patch_name in OPTIONAL_PATCHES:
|
||||
return
|
||||
|
||||
raise FileNotFoundError(f"No patches with name \"{patch_file}\" :(")
|
||||
|
||||
subprocess.run(f"patch -p1 --no-backup-if-mismatch -i {patch_file}",
|
||||
shell=True, check=True, cwd=workdir)
|
||||
|
||||
|
||||
# Wipe and recreate the working folder
|
||||
if os.path.exists(WORK_APK_PATH):
|
||||
shutil.rmtree(WORK_APK_PATH)
|
||||
|
||||
os.makedirs(WORK_FOLDER, exist_ok=True)
|
||||
|
||||
# Get the version of the APK from distok state file
|
||||
with open(STATE_FILE) as f:
|
||||
STATE = json.load(f)
|
||||
VERSION = STATE["android"][PACKAGE_ID]["version"]
|
||||
|
||||
BASE_APK_PATH = os.path.join(WORK_FOLDER, f"discord-base-{VERSION}")
|
||||
|
||||
# Prepare names of input and output APKs
|
||||
INPUT_FILE = os.path.join(DISTOK_FOLDER, "android",
|
||||
f"{PACKAGE_ID}-{VERSION}.apk")
|
||||
# OUTPUT_FILE = os.path.join(RESULT_FOLDER,
|
||||
# f"cutthecord-{VERSION}-{'_'.join(PATCHES)}.apk")
|
||||
OUTPUT_FILE = os.path.join(RESULT_FOLDER,
|
||||
f"cutthecord-{VERSION}-{BRANCH}.apk")
|
||||
|
||||
# Add necessary patches to the list of patches that will be applied
|
||||
# Important to have this after the output file name generation
|
||||
# otherwise it'll include it, which is not wanted
|
||||
PATCHES += DEFAULT_PATCHES
|
||||
|
||||
print(f"Branch: {BRANCH}, output name: {OUTPUT_FILE}")
|
||||
|
||||
# Check if the version is already patched, if it is exit
|
||||
if not FORCE and os.path.exists(OUTPUT_FILE):
|
||||
print("This version is already patched, bye!")
|
||||
sys.exit(1)
|
||||
|
||||
# Update cutthecord
|
||||
subprocess.run("git pull", shell=True, cwd=REPO_FOLDER)
|
||||
|
||||
# Extract the APK if it's not already extracted to base cache
|
||||
if not os.path.exists(BASE_APK_PATH):
|
||||
subprocess.run(f"{APKTOOL_BIN} d {INPUT_FILE} -o {BASE_APK_PATH} -f",
|
||||
shell=True,
|
||||
cwd=WORK_FOLDER)
|
||||
|
||||
# Copy the base cache to work on it
|
||||
shutil.copytree(BASE_APK_PATH, WORK_APK_PATH)
|
||||
|
||||
# Go through patches and apply every single one of them
|
||||
for patch_name in PATCHES:
|
||||
# Apply custom emoji patches
|
||||
if patch_name in ["mutant", "blobs"]:
|
||||
print(f"Applying {patch_name} emoji patch")
|
||||
patch_script = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, "emojireplace.py")
|
||||
subprocess.run(f"{PYTHON_BIN} {patch_script}",
|
||||
shell=True,
|
||||
cwd=WORK_APK_PATH)
|
||||
|
||||
# Apply custom emoji patches
|
||||
elif patch_name == "customtheme":
|
||||
print(f"Applying splash patch")
|
||||
splash = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, "asset_loading.png")
|
||||
patch_script = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, "fixsplash.sh")
|
||||
|
||||
subprocess.run(f"bash {patch_script} {splash}",
|
||||
shell=True,
|
||||
cwd=WORK_APK_PATH)
|
||||
|
||||
patch_file = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, f"{VERSION}.patch")
|
||||
|
||||
# Apply custom version patches
|
||||
if patch_name == "customversion":
|
||||
print(f"Applying custom version")
|
||||
patch_script = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, "addpatch.py")
|
||||
|
||||
subprocess.run(f"{PYTHON_BIN} {patch_script} {patch_file} "
|
||||
f"{' '.join(PATCHES)}",
|
||||
shell=True,
|
||||
cwd=WORK_APK_PATH)
|
||||
|
||||
patch(patch_file.replace(".patch", "-custom.patch"), WORK_APK_PATH)
|
||||
# Apply branding patches
|
||||
elif patch_name == "branding":
|
||||
print(f"Applying branding icon patch")
|
||||
if BRANCH in ICONS:
|
||||
shutil.copyfile(ICONS[BRANCH],
|
||||
os.path.join(WORK_APK_PATH, "res",
|
||||
"mipmap-xxxhdpi", "logo_debug.png"))
|
||||
elif "default" in ICONS:
|
||||
shutil.copyfile(ICONS["default"],
|
||||
os.path.join(WORK_APK_PATH, "res",
|
||||
"mipmap-xxxhdpi", "logo_debug.png"))
|
||||
|
||||
patch_script = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, "customicon.sh")
|
||||
|
||||
subprocess.run(f"bash {patch_script}", shell=True, cwd=WORK_APK_PATH)
|
||||
|
||||
patch_script = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, "addpatch.py")
|
||||
|
||||
# Hell code
|
||||
app_name = APP_NAMES.get(BRANCH, APP_NAMES.get("default", "CutTheCord"))
|
||||
|
||||
subprocess.run(f"{PYTHON_BIN} {patch_script} "
|
||||
f"{patch_file} {app_name} {BRANCH}",
|
||||
shell=True,
|
||||
cwd=WORK_APK_PATH)
|
||||
|
||||
patch(patch_file.replace(".patch", "-custom.patch"), WORK_APK_PATH)
|
||||
elif patch_name in ["bettertm", "bettertmlight"]:
|
||||
print(f"Applying bettertm emoji patch")
|
||||
patch_dir = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name)
|
||||
patch_script = os.path.join(REPO_FOLDER, "patches",
|
||||
patch_name, "bettertm.sh")
|
||||
subprocess.run(f"bash {patch_script} {patch_dir}",
|
||||
shell=True,
|
||||
cwd=WORK_APK_PATH)
|
||||
# Apply custom ringtone
|
||||
elif patch_name == "customring":
|
||||
print(f"Applying custom ringtone")
|
||||
if BRANCH in RINGTONES:
|
||||
CUSTOM_RINGTONE = RINGTONES[BRANCH]
|
||||
else:
|
||||
CUSTOM_RINGTONE = RINGTONES["default"]
|
||||
|
||||
shutil.copyfile(CUSTOM_RINGTONE,
|
||||
os.path.join(WORK_APK_PATH, "res",
|
||||
"raw", "call_ringing.mp3"))
|
||||
# Apply custom fonts
|
||||
elif patch_name == "customfont":
|
||||
print(f"Applying custom font")
|
||||
if BRANCH in FONTS:
|
||||
fonts = FONTS[BRANCH]
|
||||
else:
|
||||
fonts = FONTS["default"]
|
||||
|
||||
for font in fonts:
|
||||
shutil.copyfile(fonts[font],
|
||||
os.path.join(WORK_APK_PATH, "res",
|
||||
"font", font))
|
||||
# Apply any other patches
|
||||
else:
|
||||
patch(patch_file, WORK_APK_PATH, patch_name)
|
||||
|
||||
# Pack the APK
|
||||
subprocess.run(f"{APKTOOL_BIN} b discord",
|
||||
shell=True,
|
||||
cwd=WORK_FOLDER)
|
||||
|
||||
APK_PATH = os.path.join(WORK_FOLDER, "discord",
|
||||
"dist", f"{PACKAGE_ID}-{VERSION}.apk")
|
||||
|
||||
# Sign the APK
|
||||
subprocess.run(f"jarsigner -storepass {KEYSTORE_PASS} -keystore "
|
||||
f"{KEYSTORE_FILE} {APK_PATH} {KEYSTORE_ALIAS}",
|
||||
shell=True,
|
||||
cwd=WORK_FOLDER)
|
||||
|
||||
# Copy the result file
|
||||
shutil.copyfile(APK_PATH, OUTPUT_FILE)
|
||||
|
||||
if DO_FDROID:
|
||||
# Do fdroid magic
|
||||
subprocess.run(f"fdroid update -c",
|
||||
shell=True,
|
||||
cwd=FDROID_FOLDER)
|
||||
|
||||
# Wipe caches
|
||||
shutil.rmtree(WORK_APK_PATH)
|
||||
print("CutTheCord CI has fulfilled its purpose.")
|
71
ctcci/ctcconfig.example.py
Normal file
71
ctcci/ctcconfig.example.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
import os
|
||||
|
||||
APKTOOL_BIN = "java -jar /home/ave/apktool-cli-all.jar" # use latest
|
||||
|
||||
# Set to false if you're going to use a local state.json file
|
||||
# state.json has information about the latest discord version
|
||||
LOCAL_STATE = False
|
||||
STATE_FILE = "/home/ave/distok/state.json"
|
||||
|
||||
# APKs must be placed under $DISTOK_FOLDER/android/$PACKAGE_ID-$VERSION_NUMBER.apk
|
||||
# Example: /home/ave/distok/android/com.discord-909.apk
|
||||
DISTOK_FOLDER = "/home/ave/distok"
|
||||
|
||||
# Set if F-Droid repo should be automatically updated or not
|
||||
# If set to False, you can leave FDROID_FOLDER empty
|
||||
DO_FDROID = True
|
||||
FDROID_FOLDER = "/var/www/fdroid/seabear"
|
||||
|
||||
# This is where APKs will be placed
|
||||
RESULT_FOLDER = FDROID_FOLDER + "/repo"
|
||||
|
||||
# Repo for CutTheCord (https://gitdab.com/distok/cutthecord)
|
||||
REPO_FOLDER = "/home/ave/distokrepos/cutthecord"
|
||||
|
||||
# Keystore file, alias and pass. Required.
|
||||
KEYSTORE_FILE = "/home/ave/oof.keystore"
|
||||
KEYSTORE_ALIAS = "distok"
|
||||
KEYSTORE_PASS = "redacted"
|
||||
|
||||
# Set this to the python version you want to use. Needs to be 3.6+.
|
||||
PYTHON_BIN = "python3.6"
|
||||
|
||||
# Folder where the apk will be extracted to, patched in, and packed back on
|
||||
# You're not recommended to touch WORK_APK_PATH.
|
||||
WORK_FOLDER = "/tmp/cutthecord"
|
||||
WORK_APK_PATH = os.path.join(WORK_FOLDER, "discord")
|
||||
|
||||
# Package ID for discord. You should probably not touch this.
|
||||
PACKAGE_ID = "com.discord"
|
||||
|
||||
# Set to force if you want builds to be done
|
||||
# even if there's already a build for this version
|
||||
FORCE = False
|
||||
|
||||
# Custom ringtones, default = applied to all the ones not explicitly stated
|
||||
RINGTONES = {"ave": "/home/ave/sans.mp3",
|
||||
"default": "/home/ave/removeskype.mp3"}
|
||||
|
||||
# Custom icons, default = applied to all the ones not explicitly stated
|
||||
ICONS = {"ave": "/home/ave/ctclogoave.png",
|
||||
"default": "/home/ave/ctclogo.png"}
|
||||
|
||||
# Custom app names, default = applied to all the ones not explicitly stated
|
||||
# Needs to be one word, __ gets replaced with space
|
||||
APP_NAMES = {"ave": "CutTheCord__Ave",
|
||||
"litecord": "Litecord",
|
||||
"test": "CTC__Testing",
|
||||
"default": "CutTheCord"}
|
||||
|
||||
# Custom fonts, default = applied to all the ones not explicitly stated
|
||||
FONTS = {"ellie": {"whitney_bold.ttf": "/home/ave/fonts/GoogleSans-Bold.ttf",
|
||||
"whitney_semibold.ttf": "/home/ave/fonts/GoogleSans-Medium.ttf",
|
||||
"whitney_medium.ttf": "/home/ave/fonts/GoogleSans-Regular.ttf"},
|
||||
"dyslexic": {"whitney_bold.ttf": "/home/ave/fonts/OpenDyslexic3-Bold.ttf",
|
||||
"whitney_semibold.ttf": "/home/ave/fonts/OpenDyslexic3-Bold.ttf",
|
||||
"whitney_medium.ttf": "/home/ave/fonts/OpenDyslexic3-Regular.ttf"},
|
||||
"murm": {"whitney_bold.ttf": "/home/ave/fonts/comicbd.ttf",
|
||||
"whitney_semibold.ttf": "/home/ave/fonts/comicbd.ttf",
|
||||
"whitney_medium.ttf": "/home/ave/fonts/comic.ttf"},
|
||||
"ave": {"sourcecodepro_semibold.ttf": "/home/ave/fonts/comic.ttf"},
|
||||
"default": {}}
|
1
ctcci/requirements.txt
Normal file
1
ctcci/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
requests
|
Loading…
Add table
Add a link
Reference in a new issue