first commit
This commit is contained in:
commit
0b149cec60
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
discord/
|
||||
settings.json
|
||||
*.jar
|
||||
*.apk
|
||||
|
||||
!uber-apk-signer.jar
|
||||
54
README.md
Normal file
54
README.md
Normal file
@ -0,0 +1,54 @@
|
||||
# discord-patcher
|
||||
|
||||
This patches the discord.apk for use with different backends/implementations. Edit settings.json to customise options.
|
||||
|
||||
# How to use this tool
|
||||
|
||||
- copy `example.settings.json` to `settings.json`
|
||||
- edit `settings.json` as needed
|
||||
- run `pip install -r requirements.txt` to install python dependencies
|
||||
- download uber apk signer and place it in the folder, rename it to `uber-apk-signer.jar`
|
||||
- download apktool and place it in the folder, rename it to `apktool.jar`
|
||||
- run `python patcher.py` and wait for it to complete. it can take a while.
|
||||
|
||||
The URL for the discord APK is set as the last discord stable version using
|
||||
Java source code.
|
||||
|
||||
This tool does not work with the React Native APK, likely because it uses Hermes
|
||||
bytecode, whereas we're patching smali code (decompiled .dex files).
|
||||
|
||||
Icon replacement does not work currently.
|
||||
|
||||
Package renaming also does not work.
|
||||
|
||||
## Config
|
||||
|
||||
`secure` - if `https`/`wss` is used instead of `http`/`ws`.
|
||||
|
||||
`base_url` - The base URL, this is used for API routes like `/api/`.
|
||||
|
||||
`gateway_url` - The gateway URL, this is used for the gateway connection (via websockets).
|
||||
|
||||
`cdn_url` - The CDN url, for uploaded files, images, etc.
|
||||
|
||||
`invite_url` - The invite URL, for guild invites.
|
||||
|
||||
`package_name` - The package name you want the app to be under, so you can install it alongside your existing discord installation. This may take longer to compile and decompile, but it's recommended.
|
||||
|
||||
NOTE: This is broken and will be installed under `com.discord` no matter what the config is set to.
|
||||
|
||||
`original_package_name` - The original package name for the APK you're decompiling. dont touch this.
|
||||
|
||||
`new_package_name` - the new package name for replacement.
|
||||
|
||||
`old_app_name` - the old app name string, dont touch this.
|
||||
|
||||
`new_app_name` - the new app name
|
||||
|
||||
`download_url` - The download url of the apk to decompile, it's recommended to leave this alone.
|
||||
|
||||
`debug` - The option to enable or disable debugging options built into the discord apk. It's recommended to leave this alone.
|
||||
|
||||
# Contributions
|
||||
Thanks to `Puyodead1` for fixing the script after months of neglect :p
|
||||
|
||||
BIN
assets/icon.png
Normal file
BIN
assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 233 KiB |
13
example.settings.json
Normal file
13
example.settings.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"secure": true,
|
||||
"base_url": "staging.fosscord.com",
|
||||
"gateway_url": "staging.fosscord.com",
|
||||
"cdn_url": "staging.fosscord.com",
|
||||
"invite_url": "staging.fosscord.com/invite",
|
||||
"original_package_name": "com.discord",
|
||||
"new_package_name": "com.fosscord",
|
||||
"old_app_name": "@string/discord",
|
||||
"new_app_name": "Fosscord",
|
||||
"download_url": "https://aliucord.com/download/discord?v=126021",
|
||||
"debug": true
|
||||
}
|
||||
154
patcher.py
Normal file
154
patcher.py
Normal file
@ -0,0 +1,154 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import typing
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
from json import load as jload
|
||||
from os import chdir, path, system, unlink, walk
|
||||
import urllib.request
|
||||
|
||||
|
||||
verbose = True
|
||||
stdout = subprocess.PIPE if verbose else subprocess.DEVNULL
|
||||
stderr = subprocess.STDOUT if verbose else subprocess.DEVNULL
|
||||
|
||||
with open('settings.json') as f:
|
||||
config = jload(f)
|
||||
|
||||
if not os.path.isfile("discord.apk"):
|
||||
print("[Download] Downloading Discord APK...")
|
||||
|
||||
code = system(f'curl -L {config["download_url"]} -o discord.apk')
|
||||
if code != 0:
|
||||
print("[Download] Failed to download APK!")
|
||||
raise SystemExit(code)
|
||||
|
||||
'''
|
||||
apk_url = config["download_url"]
|
||||
|
||||
while True:
|
||||
try:
|
||||
req = urllib.request.urlopen(apk_url)
|
||||
print(req.read())
|
||||
req.close()
|
||||
except Exception as e:
|
||||
if e.code == 403:
|
||||
apk_url = e.geturl()
|
||||
continue
|
||||
print(e)
|
||||
raise SystemExit("[Download] Failed to download APK!")
|
||||
'''
|
||||
print("[Download] APK Downloaded")
|
||||
else:
|
||||
print("[Download] APK already downloaded")
|
||||
|
||||
|
||||
|
||||
print("[Decompile] Decompiling APK, this may take a minute...")
|
||||
r = subprocess.Popen('java -jar apktool.jar d -f discord.apk', shell=True, text=True, stdin=subprocess.PIPE, stdout=stdout, stderr=stderr)
|
||||
r.stdin.write('\r\n' if os.name=='nt' else '\n')
|
||||
r.communicate()
|
||||
chdir('discord')
|
||||
|
||||
# Things that need some renaming to actually work correctly should be edited and reviewed here every update
|
||||
bugfixes = []
|
||||
|
||||
protocol = ('http://', 'ws://')
|
||||
if config['secure']:
|
||||
protocol = ('https://', 'wss://')
|
||||
|
||||
# Basic replacements throughout the code to replace discord routes with fosscord routes
|
||||
# NOTE: Order of replacements is VERY important and will probably have to do stupid stuff to make it customisable
|
||||
replacements = [
|
||||
('https://cdn.discordapp.com', protocol[0]+config['cdn_url']), # cdn.discord.com to cdn url
|
||||
('https://media.discordapp.net', protocol[0]+config['cdn_url']), # discord media proxy to cdn url
|
||||
('https://gateway.discord.gg', protocol[1]+config['gateway_url']), # gateway.discord.com to gateway url
|
||||
('https://discord.com', protocol[0]+config['base_url']), # discord.com to the base url
|
||||
('https://discordapp.com', protocol[0]+config['base_url']), # Extra change just in case discordapp is still used in the code somewhere
|
||||
('https://discord.gg', protocol[0]+config['invite_url']), # discord.gg to the invite url
|
||||
('https://discord.new/', protocol[0]+config['base_url']+'/template') # discord.new to template url
|
||||
]
|
||||
|
||||
if config.get('debug'):
|
||||
replacements.append(("DEBUG:Z = false", "DEBUG:Z = true")) # Enables debug if it's true in the config
|
||||
|
||||
def patchfile(file):
|
||||
code = system("patch -p1 --no-backup-if-mismatch -i ../patches/"+file)
|
||||
if code != 0:
|
||||
print(f"[PatchFile] Failed to apply patchfile {file}")
|
||||
return
|
||||
if verbose:
|
||||
print(f"[PatchFile] Applied patchfile {file}")
|
||||
|
||||
def patch(folder):
|
||||
for root, _, files in walk(path.join('.', folder)):
|
||||
for file in files:
|
||||
fpath = path.join(root, file)
|
||||
try:
|
||||
with open(fpath) as f:
|
||||
data = tmp = f.read()
|
||||
for bugfix in bugfixes:
|
||||
data = data.replace(*bugfix)
|
||||
for replacement in replacements:
|
||||
data = data.replace(*replacement)
|
||||
if tmp != data:
|
||||
with open(fpath, 'w+') as f:
|
||||
f.write(data)
|
||||
if verbose:
|
||||
print(f"[Patch] Applied patches to `{fpath}`")
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
print("[Patcher] Patching...")
|
||||
patch('smali')
|
||||
patch('smali_classes2')
|
||||
patch('smali_classes3')
|
||||
|
||||
print("[Patcher] Patching AndroidManifest.xml...")
|
||||
with open('AndroidManifest.xml') as f:
|
||||
manifest = f.read()
|
||||
# manifest = manifest.replace(config['original_package_name'], config['new_package_name'])
|
||||
if config["old_app_name"] != config["new_app_name"]:
|
||||
manifest = manifest.replace(config['old_app_name'], config['new_app_name'])
|
||||
if verbose:
|
||||
print("[Patcher] Patched AndroidManifest.xml")
|
||||
|
||||
with open('AndroidManifest.xml', 'w') as f:
|
||||
f.write(manifest)
|
||||
|
||||
print("[Patcher] Patching complete")
|
||||
chdir('..')
|
||||
|
||||
'''
|
||||
print("[Icon] Replacing icon...")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-hdpi/ic_logo_round.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-hdpi/ic_logo_square.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xhdpi/ic_logo_round.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xhdpi/ic_logo_square.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xxhdpi/ic_logo_round.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xxhdpi/ic_logo_square.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xxhdpi/logo.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xxxhdpi/ic_logo_round.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xxxhdpi/ic_logo_square.png")
|
||||
shutil.copyfile("assets/icon.png", "discord/res/mipmap-xxxhdpi/logo.png")
|
||||
'''
|
||||
|
||||
print("[Build] Rebuilding APK...")
|
||||
r = subprocess.Popen('apktool b discord/ -o fosscord.unsigned.apk', shell=True, text=True, stdin=subprocess.PIPE, stdout=stdout, stderr=stderr)
|
||||
r.stdin.write('\r\n' if os.name=='nt' else '\n')
|
||||
r.communicate()
|
||||
print("[Build] APK rebuilt")
|
||||
|
||||
print("[Sign] Signing APK...")
|
||||
r = subprocess.Popen('java -jar uber-apk-signer.jar --apks fosscord.unsigned.apk -o .', shell=True, text=True, stdout=stdout, stderr=stderr)
|
||||
r.communicate()
|
||||
print("[Sign] APK signed")
|
||||
|
||||
'''
|
||||
print("[Clean] Cleaning up...")
|
||||
shutil.rmtree("discord")
|
||||
unlink("fosscord.unsigned.apk")
|
||||
'''
|
||||
|
||||
print("All done!")
|
||||
34
patches/nozlib.patch
Normal file
34
patches/nozlib.patch
Normal file
@ -0,0 +1,34 @@
|
||||
diff -crB from/smali/com/discord/gateway/GatewaySocket.smali to/smali/com/discord/gateway/GatewaySocket.smali
|
||||
*** from/smali/com/discord/gateway/GatewaySocket.smali 2021-08-04 19:45:39.263375300 +0100
|
||||
--- to/smali/com/discord/gateway/GatewaySocket.smali 2021-08-04 23:26:38.221788200 +0100
|
||||
***************
|
||||
*** 1410,1416 ****
|
||||
|
||||
invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
|
||||
! const-string p1, "/?encoding=json&v=9&compress=zlib-stream"
|
||||
|
||||
invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
|
||||
--- 1410,1416 ----
|
||||
|
||||
invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
|
||||
! const-string p1, "/?encoding=json&v=9"
|
||||
|
||||
invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
|
||||
diff -crB from/smali/com/discord/gateway/io/OutgoingPayload$Identify.smali to/smali/com/discord/gateway/io/OutgoingPayload$Identify.smali
|
||||
*** from/smali/com/discord/gateway/io/OutgoingPayload$Identify.smali 2021-08-04 19:45:39.360374800 +0100
|
||||
--- to/smali/com/discord/gateway/io/OutgoingPayload$Identify.smali 2021-08-04 23:28:01.288223200 +0100
|
||||
***************
|
||||
*** 115,120 ****
|
||||
--- 115,122 ----
|
||||
|
||||
iput p2, p0, Lcom/discord/gateway/io/OutgoingPayload$Identify;->largeThreshold:I
|
||||
|
||||
+ const/4 p3, 0x0
|
||||
+
|
||||
iput-boolean p3, p0, Lcom/discord/gateway/io/OutgoingPayload$Identify;->compress:Z
|
||||
|
||||
iput-wide p4, p0, Lcom/discord/gateway/io/OutgoingPayload$Identify;->capabilities:J
|
||||
BIN
uber-apk-signer.jar
Normal file
BIN
uber-apk-signer.jar
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user