Commit 50eb9f99 authored by Rob Nelson's avatar Rob Nelson
Browse files

bbdctl no longer needed, all handled in Python.

parent 23b9e48c
*.py[oic]
__pycache__
accounts.yml
jails
Discord
tmp
scripts
/jails/
/Discord/
/tmp/
/scripts/
*.tgz
bddctl
.cache
src
node_modules
/.cache/
/src/
/node_modules/
/.venv/
/bandaged_betterdiscord/
repos:
- hooks:
- entry: /usr/bin/python3.6 .selid-hooks/check-identity
- entry: /home/nexis/discordjail/.venv/bin/python3.6 .selid-hooks/check-identity
id: select-identity+check-identity
language: system
name: Select Identity - check-identity
......
import os, stat, re, json, pathlib
import os, stat, re, json, pathlib, tempfile, shutil, pygit2
from typing import Dict
from buildtools import os_utils, log
from discordjail.addons.framework import Addon, Addons
from discordjail.http import download_file_to
from buildtools.pygit2_callbacks import RemoteProgressCallbacks
from typing import List
BBD_INSTALL_DIR = os.path.abspath(os.path.join('.', 'bandaged_betterdiscord'))
BBD_REPO_URL = 'https://github.com/rauenzi/BetterDiscordApp/'
BBD_REPO_BRANCH = 'injector'
BDDCTL_URL = 'https://raw.githubusercontent.com/bb010g/betterdiscordctl/master/betterdiscordctl'
......@@ -75,6 +81,10 @@ class BandagedBetterDiscordAddon(Addon):
self.plugins_dir: str = ''
self.themes_dir: str = ''
self.injector_path: str = ''
self.index_path: str = ''
self.core_dir: str = ''
self.plugins: Dict[str, BBDPlugin] = {}
self.themes: Dict[str, BBDPlugin] = {}
......@@ -90,6 +100,145 @@ class BandagedBetterDiscordAddon(Addon):
self.themes[k] = t = BBDTheme()
t.deserialize(k, v)
def bdc_install(self):
# We perform idiot checks in preexec().
#[[ -d $core/injector ]] && die 'ERROR: Already installed.'
'''
# Clean up legacy cruft
if [[ -d $core/core ]]; then
printf 'Removing legacy core directory...\n' >&2
rm -rf "$core/core"
fi
'''
core_core_dir = os.path.join(self.core_dir, 'core')
if os.path.isdir(core_core_dir):
with log.info('Removing legacy core directory...'):
shutil.rmtree(core_core_dir)
self.bd_patch()
self.bd_injector()
def bdc_uninstall(self):
self.bd_unpatch()
log.info('Unpatched.')
def check_bbd_install(self):
repo = None
cb = RemoteProgressCallbacks()
if not os.path.isdir(BBD_INSTALL_DIR):
cb.startup()
repo = pygit2.clone_repository(BBD_REPO_URL, BBD_INSTALL_DIR, checkout_branch=BBD_REPO_BRANCH, callbacks=cb)
cb.shutdown()
else:
repo = pygit2.Repository(BBD_INSTALL_DIR)
origin = repo.remotes['origin']
cb.startup()
origin.fetch(prune=pygit2.GIT_FETCH_PRUNE, callbacks=cb)
cb.shutdown()
repo.reset(repo.revparse_single('FETCH_HEAD').oid, pygit2.GIT_RESET_HARD)
if repo.head.shorthand != BBD_REPO_BRANCH:
log.warning('Incorrect branch %r. Checking out %r...', repo.head.shorthand, BBD_REPO_BRANCH)
branch = repo.branches.remote['origin/'+BBD_REPO_BRANCH]
ref = repo.lookup_reference(branch.name)
repo.checkout(ref)
return repo
def bdc_update(self) -> bool:
if not os.path.isdir(self.injector_path):
log.error('BBD Injector is missing.')
return False
if not os.path.islink(self.injector_path):
log.error('BBD Injector is not a symlink.')
return False
resolved = pathlib.Path(self.injector_path).resolve()
if resolved != pathlib.Path(BBD_INSTALL_DIR):
log.error('BBD Injector symlinked to %r instead of %r.', resolved, BBD_INSTALL_DIR)
return False
self.check_bbd_install()
return True
def bd_injector(self):
self.check_bbd_install()
if not os.path.isdir(self.injector_path):
os.symlink(BBD_INSTALL_DIR, self.injector_path)
def bd_patch(self):
# if ! grep -q 'injector' "$core/index.js"; then
found = False
with open(self.index_path, 'r') as f:
if 'injector' in f.read():
found=True
if not found:
'''
sed -i "$core/index.js" \
-e "1i require('./injector');" \
-e "s/core'/core.asar'/"
'''
log.info('Patching %s...', self.index_path)
reg_asar = re.compile(r"core'")
with tempfile.NamedTemporaryFile(mode='w', delete=False) as tf:
with open(self.index_path, 'r') as f:
i = 1
for line in f:
if i == 1:
tf.write("require('./injector');\n")
line = reg_asar.sub("core.asar'", line)
tf.write(line)
i+=1
shutil.copystat(self.index_path, tf.name)
shutil.move(tf.name, self.index_path)
def bd_unpatch(self):
'''
bd_unpatch() {
verbose 1 'V: Removing BetterDiscord injection...'
sed -i "$core/index.js" \
-e '/injector/d' \
-e "s/core'/core.asar'/"
rm -rf "$core/injector"
}
'''
found = False
with open(self.index_path, 'r') as f:
if 'injector' in f.read():
found=True
if found:
log.info('Removing BBD injector from %s...', self.index_path)
reg_asar = re.compile(r"core\.asar'")
with tempfile.NamedTemporaryFile(mode='w', delete=False) as tf:
with open(self.index_path, 'r') as f:
for line in f:
if 'injector' in line:
continue
line = reg_asar.sub("core'", line)
tf.write(line)
shutil.copystat(self.index_path, tf.name)
shutil.move(tf.name, self.index_path)
if os.path.isdir(self.injector_path):
log.info('Removing %s...', self.injector_path)
if os.path.islink(self.injector_path):
os.unlink(self.injector_path)
else:
shutil.rmtree(self.injector_path)
def do_cmd(self, cmdlist: List[str]) -> None:
for cmd in cmdlist:
if cmd == 'install':
self.bdc_install()
elif cmd == 'update':
self.bdc_update()
elif cmd == 'uninstall':
self.bdc_uninstall()
else:
log.error('Invalid command %r', cmd)
def preexec(self):
assert self.discord.homedir != ''
......@@ -97,59 +246,72 @@ class BandagedBetterDiscordAddon(Addon):
assert self.discord.modulesdir != ''
self.bbdctl_path = os.path.join(self.discord.homedir, 'bddctl')
self.bbdctl_local = os.path.join(self.discord.homedir, '.local', 'share', 'betterdiscordctl')
self.discord_dir = self.discord.discorddir
self.config_dir = os.path.join(self.discord.homedir, '.config', 'discord')
self.modules_dir = self.discord.modulesdir
self.plugins_dir = os.path.join(self.discord.homedir, '.config', 'BetterDiscord', 'plugins')
self.themes_dir = os.path.join(self.discord.homedir, '.config', 'BetterDiscord', 'themes')
os_utils.ensureDirExists(os.path.dirname(self.bbdctl_path), noisy=True)
#download_file_to(BDDCTL_URL, self.bbdctl_path)
with log.info(f'Setting {self.bbdctl_path} +x (+S_IEXEC)...'):
st = os.stat(self.bbdctl_path)
os.chmod(self.bbdctl_path, st.st_mode|stat.S_IEXEC)
opts = ['-d', self.discord_dir]
opts += ['-m', self.modules_dir]
injpath = os.path.join(self.modules_dir, 'discord_desktop_core', 'injector')
#os_utils.ensureDirExists(os.path.dirname(self.bbdctl_path), noisy=True)
#with log.info(f'Setting {self.bbdctl_path} +x (+S_IEXEC)...'):
# st = os.stat(self.bbdctl_path)
# os.chmod(self.bbdctl_path, st.st_mode|stat.S_IEXEC)
#opts = ['-d', self.discord_dir]
#opts += ['-m', self.modules_dir]
if os.path.isfile(self.bbdctl_path):
log.info('Removing %s...', self.bbdctl_path)
os.remove(self.bbdctl_path)
if os.path.isfile(self.bbdctl_local):
log.info('Removing %s...', self.bbdctl_local)
shutil.rmtree(self.bbdctl_local)
self.core_dir = os.path.join(self.modules_dir, 'discord_desktop_core')
self.injector_path = os.path.join(self.core_dir, 'injector')
# injpath = /home/nexis/discordjail/jails/N3X15/home/.config/discord/0.0.9/modules/discord_desktop_core/injector
# Core: /home/nexis/discordjail/jails/N3X15/home/.config/discord/0.0.9/modules/discord_desktop_core
idxpath = os.path.join(self.modules_dir, 'discord_desktop_core', 'index.js')
self.index_path = os.path.join(self.core_dir, 'index.js')
injhealth = 'OK'
injbad = False
idxhealth = 'OK'
bddctl_op = []
if not os.path.isdir(injpath):
if not os.path.isdir(self.injector_path):
injhealth = 'MISSING'
injbad = True
bddctl_op = ['install']
else:
realinjpath = pathlib.Path(injpath).resolve()
realinjpath = pathlib.Path(self.injector_path).resolve()
if not os.path.isdir(realinjpath):
injhealth = "BROKEN"
bddctl_op = ['uninstall', 'install']
injhealth += f' ({realinjpath})'
if not os.path.isfile(idxpath):
if not os.path.isfile(self.index_path):
idxhealth = 'MISSING'
injbad = True
bddctl_op = ['uninstall', 'install']
else:
with open(idxpath, 'r') as f:
with open(self.index_path, 'r') as f:
if 'injector' not in f.read():
idxhealth = 'UNPATCHED'
injbad = True
bddctl_op = ['uninstall', 'install']
with log.info('BDD Status:'):
log.info('Modules path: %s', self.modules_dir)
log.info('Injector: %s - %s', injpath, injhealth)
log.info('index.js: %s - %s', idxpath, idxhealth)
log.info('Injector: %s - %s', self.injector_path, injhealth)
log.info('index.js: %s - %s', self.index_path, idxhealth)
if len(bddctl_op)>0:
with log.info('Injector broken, attempting repair...'):
for op in bddctl_op:
os_utils.cmd([self.bbdctl_path, op]+opts, show_output=True, echo=True, critical=False)
if not os_utils.cmd([self.bbdctl_path, 'update']+opts, show_output=True, echo=True, critical=False):
self.do_cmd(bddctl_op)
#for op in bddctl_op:
# os_utils.cmd([self.bbdctl_path, op]+opts, show_output=True, echo=True, critical=False)
#if not os_utils.cmd([self.bbdctl_path, 'update']+opts, show_output=True, echo=True, critical=False):
if not self.bdc_update():
with log.info('Update failed, attempting reinstall...'):
os_utils.cmd([self.bbdctl_path, 'install']+opts, show_output=True, echo=True, critical=False)
os_utils.cmd([self.bbdctl_path, 'update']+opts, show_output=True, echo=True, critical=False)
#os_utils.cmd([self.bbdctl_path, 'install']+opts, show_output=True, echo=True, critical=False)
self.bdc_uninstall()
#os_utils.cmd([self.bbdctl_path, 'update']+opts, show_output=True, echo=True, critical=False)
self.bdc_install()
os_utils.ensureDirExists(os.path.dirname(self.plugins_dir), noisy=True)
if not os.path.isdir(self.plugins_dir):
......
......@@ -226,7 +226,8 @@ class Discord(object):
while True:
cmd=async_cmd([self.binpath, '--multi-instance'], env=env, stdout=self.handlestdout, stderr=self.handlestderr)
self.exit_reason = ExitReason.NONE
cmd = async_cmd([self.binpath, '--multi-instance'], env=env, stdout=self.handlestdout, stderr=self.handlestderr)
cmd.WaitUntilDone()
if self.exit_reason == ExitReason.NONE:
break
......
{
"version": 1,
"packages": {}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment