diff options
Diffstat (limited to 'betterdiscordctl')
-rwxr-xr-x | betterdiscordctl | 661 |
1 files changed, 0 insertions, 661 deletions
diff --git a/betterdiscordctl b/betterdiscordctl deleted file mode 100755 index 00d9a19..0000000 --- a/betterdiscordctl +++ /dev/null @@ -1,661 +0,0 @@ -#!/usr/bin/env bash - -set -ueo pipefail -shopt -s dotglob extglob nullglob - -# Constants -VERSION=1.7.0 -SOURCE=$(readlink -f "${BASH_SOURCE[0]}") -DISABLE_UPGRADE= - -# Options -cmd=status -verbosity=0 -scan=(/opt /usr/share /usr/lib64) -flavors=('' canary ptb) -discord= -modules= -bd_repo='https://github.com/rauenzi/BetterDiscordApp' -bd_repo_branch=injector -bd= -copy_bd= -snap= -flatpak= -upgrade_url='https://github.com/bb010g/betterdiscordctl/raw/master/betterdiscordctl' - -# Variables -flavor= -core= -xdg_config=${XDG_CONFIG_HOME:-$HOME/.config} -data=${XDG_DATA_HOME:-$HOME/.local/share}/betterdiscordctl -snap_bin=snap -flatpak_bin=flatpak - -show_help() { - cat << EOF -Usage: ${0##*/} [COMMAND] [OPTION...] - -Options: - -V, --version Display version info and exit - -h, --help Display this help message and exit - -v, --verbose Increase verbosity - -s, --scan=DIRECTORIES Colon-separated list of directories to scan for - a Discord installation - (default '/opt:/usr/share') - -f, --flavors=FLAVORS Colon-separated list of Discord flavors - (default ':canary:ptb') - -d, --discord=DIRECTORY Use the specified Discord directory - (requires --modules) - -m, --modules=DIRECTORY Use the specified Discord modules directory - -r, --bd-repo=REPOSITORY Use the specified Git repo for BetterDiscord - --bd-repo-branch=BRANCH Use the specified Git branch for BetterDiscord - (default 'stable16') - -b, --betterdiscord=DIRECTORY Use the specified BetterDiscord directory - -c, --copy-bd Copy BD directory instead of symlinking - --snap[=COMMAND] Use the Snap version of Discord (optionally - using the specified snap command) - --flatpak[=COMMAND] Use the Flatpak version of Discord (optionally - using the specified flatpak command) - --upgrade-url=URL Custom URL to upgrade betterdiscordctl with - -Commands: - status (default) Show the current Discord patch state. - install Install BetterDiscord. - reinstall Reinstall BetterDiscord. - update Update BetterDiscord. - uninstall Uninstall BetterDiscord. - upgrade Update betterdiscordctl. -EOF -} - -verbose() { - if (( verbosity >= $1 )); then - shift - printf '%s\n' "$1" >&2 - fi -} - -die() { - while [ $# -gt 0 ]; do - printf '%s\n' "$1" >&2 - shift - done - exit 1 -} - -die_with_help() { - die "$@" 'Use "--help" for more information.' -} - -die_non_empty() { - die_with_help "ERROR: \"$1\" requires a non-empty option argument." -} - -while :; do - if [[ -z ${1+x} ]]; then break; fi - case $1 in - status|install|reinstall|update|uninstall|upgrade) - cmd=$1 - ;; - -V|--version) - printf 'betterdiscordctl %s\n' "$VERSION" >&2 - exit - ;; - -h|-\?|--help) - show_help; exit - ;; - -v|--verbose) - ((++verbosity)) - ;; - -s|--scan) - if [[ ${2+x} ]]; then IFS=':' read -ra scan <<< "$2"; shift - else die_non_empty '--scan'; fi - ;; - --scan=?*) - IFS=':' read -ra scan <<< "${1#*=}" - ;; - --scan=) - die_non_empty '--scan' - ;; - -f|--flavors) - if [[ ${2+x} ]]; then IFS=':' read -ra flavors <<< "$2"; shift - else die_non_empty '--flavors'; fi - ;; - --flavors=?*) - IFS=':' read -ra flavors <<< "${1#*=}" - ;; - --flavors=) - die_non_empty '--flavors' - ;; - -d|--discord) - if [[ ${2+x} ]]; then discord=$2; shift - else die_non_empty '--discord'; fi - ;; - --discord=?*) - discord=${1#*=} - ;; - --discord=) - die_non_empty '--discord' - ;; - -m|--modules) - if [[ ${2+x} ]]; then modules=$2; shift - else die_non_empty '--modules'; fi - ;; - --modules=?*) - modules=${1#*=} - ;; - --modules=) - die_non_empty '--modules' - ;; - --bd-repo-branch) - if [[ ${2+x} ]]; then bd_repo_branch=$2; shift - else die_non_empty '--bd-repo-branch'; fi - ;; - --bd-repo-branch=?*) - bd_repo_branch=${1#*=} - ;; - --bd-repo-branch=) - die_non_empty '--bd-repo-branch' - ;; - -r|--bd-repo) - if [[ ${2+x} ]]; then bd_repo=$2; shift - else die_non_empty '--bd-repo'; fi - ;; - --bd-repo=?*) - bd_repo=${1#*=} - ;; - --bd-repo=) - die_non_empty '--bd-repo' - ;; - -b|--betterdiscord) - if [[ ${2+x} ]]; then bd=$2; shift - else die_non_empty '--betterdiscord'; fi - ;; - --betterdiscord=?*) - bd=${1#*=} - ;; - --betterdiscord=) - die_non_empty '--betterdiscord' - ;; - -c|--copy-bd) - copy_bd=yes - ;; - --snap) - snap=yes - copy_bd=yes - ;; - --snap=?*) - snap=yes - copy_bd=yes - snap_bin=${1#*=} - ;; - --snap=) - die_non_empty '--snap' - ;; - --flatpak) - flatpak=yes - copy_bd=yes - ;; - --flatpak=?*) - flatpak=yes - copy_bd=yes - flatpak_bin=${1#*=} - ;; - --flatpak=) - die_non_empty '--flatpak' - ;; - --upgrade-url) - if [[ ${2+x} ]]; then upgrade_url=$2; shift - else die_non_empty '--upgrade-url'; fi - ;; - --upgrade-url=?*) - upgrade_url=${1#*=} - ;; - --upgrade-url=) - die_non_empty '--upgrade-url' - ;; - --) - shift - break - ;; - -?*) - printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2 - ;; - *) - break - esac - shift -done - -mkdir -p "$data" -[[ -f $data/bd_map ]] || touch "$data/bd_map" - -# Commands - -bdc_status() { - index_mod=no - linked_dir=no - linked_repo=no - if [[ -d $core/injector ]]; then - if [[ -h $core/injector ]]; then - linked_dir=$(readlink "$core/injector") - if pushd "$core/injector" >/dev/null; then - linked_repo=$(git remote get-url origin 2>/dev/null || printf 'no\n') - popd >/dev/null - else - linked_dir="(broken link) $linked_dir" - fi - fi - fi - if [[ ! -f $core/index.js ]]; then - index_mod='(missing) no' - else - grep -q 'injector' "$core/index.js" && index_mod=yes - fi - - printf 'Discord: %s -Modules: %s -Index modified: %s -Linked injector directory: %s -Linked injector repository: %s\n' \ - "$discord" "$modules" "$index_mod" "$linked_dir" "$linked_repo" -} - -bdc_install() { - [[ -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 - - bd_patch - bd_injector - - printf 'Installed. (Restart Discord if necessary.)\n' >&2 -} - -bdc_reinstall() { - [[ -d $core/injector ]] || die 'Not installed.' - - bdc_kill - - verbose 1 'V: Removing old injector folder.' - rm -rf "$core/injector" - - bd_patch - bd_injector - - printf 'Reinstalled.\n' >&2 -} - -bdc_update() { - [[ -d $core/injector ]] || die 'Not installed.' - - if ! pushd "$core/injector" >/dev/null; then - if [[ -h $core/injector ]]; then - die 'ERROR: BetterDiscord injector symbolic link is broken.' - else - die 'ERROR: BetterDiscord injector location is not a directory.' - fi - fi - if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then - printf 'Updating Git repository...\n' >&2 - git fetch origin "$bd_repo_branch" - git reset --hard FETCH_HEAD - else - printf 'WARN: No Git repository found.\n' >&2 - fi - popd >/dev/null -} - -bdc_uninstall() { - [[ -d $core/injector ]] || die 'Not installed.' - - bdc_kill - bd_unpatch - - # Remove managed BD repo if applicable - bd_n=$(bd_map_get_dir "$discord" | bd_map_entry_n) - bd_map_remove "$discord" - if [[ -z $(bd_map_get_n "$bd_n") ]]; then - verbose 2 "VV: Removing $data/bd/$bd_n" - rm -rf "$data/bd/$bd_n" - fi - - printf 'Uninstalled.\n' >&2 -} - -bdc_upgrade() { - if [[ $DISABLE_UPGRADE ]]; then - die 'ERROR: Upgrading has been disabled.' \ - 'If you installed this from a package, its maintainer should keep it up to date.' - fi - - github_version=$(curl -NLSs "$upgrade_url" | sed -n 's/^VERSION=//p') - if [[ ${PIPESTATUS[0]} -ne 0 ]]; then - die "ERROR: GitHub couldn't be reached to check the version." - fi - verbose 2 "VV: Script location: $SOURCE" - verbose 2 "VV: Upgrade URL: $upgrade_url" - verbose 1 "V: Local version: $VERSION" - verbose 1 "V: GitHub version: $github_version" - semver_diff=$(Semver::compare "$github_version" "$VERSION") - if [[ $semver_diff -eq 1 ]]; then - printf 'Downloading betterdiscordctl...\n' >&2 - if curl -LSso "$SOURCE" "$upgrade_url"; then - printf 'Successfully updated betterdiscordctl.\n' >&2 - else - die 'ERROR: Failed to update betterdiscordctl.' \ - 'You may want to rerun this command with sudo.' - fi - else - if [[ $semver_diff -eq 0 ]]; then - printf 'betterdiscordctl is already the latest version (%s).\n' "$VERSION" >&2 - else - printf 'Local version (%s) is higher than GitHub version (%s).\n' "$VERSION" "$github_version" >&2 - fi - fi -} - -# Implementation functions - -bdc_main() { - if [[ -z $discord ]]; then - if [[ $snap ]]; then bdc_snap - elif [[ $flatpak ]]; then bdc_flatpak - else bdc_scan; fi - else - flavor=$flavors - # --discord and --modules - [[ -z $modules ]] && die_with_help 'ERROR: "--discord" requires "--modules" to also be set.' - [[ -d $discord ]] || die 'ERROR: Discord installation not found.' - [[ -d $modules ]] || die 'ERROR: Discord modules directory not found.' - fi - [[ -d $discord ]] || die 'ERROR: Discord installation not found. Try specifying it with "--discord".' - core=$modules/discord_desktop_core - [[ -d $core ]] || die "ERROR: Directory 'discord_desktop_core' not found in $(readlink -f "$modules")" -} - -bdc_scan() { - for scandir in "${scan[@]}"; do - verbose 2 "VV: Scanning $scandir" - for flavor in "${flavors[@]}"; do - verbose 2 "VV: Trying flavor '$flavor'" - shopt -s nocaseglob - for discord in "$scandir"/discord?(-)"$flavor"; do - shopt -u nocaseglob - if [[ -d $discord ]]; then - verbose 1 "V: Using Discord at $discord" - discord_config=$xdg_config/discord${flavor,,} - if [[ ! -d $discord_config ]]; then - printf 'WARN: Config directory not found for Discord %s (%s, %s).\n' \ - "$flavor" "$discord" "$discord_config" >&2 - continue 2 - fi - if [[ -z $modules ]]; then - bdc_find_modules - else - # --modules - [[ -d $modules ]] || die 'ERROR: Discord modules directory not found.' - fi - break 3 - fi - done - done - done -} - -bdc_find_modules() { - declare -a all_modules - all_modules=("$discord_config/"+([0-9]).+([0-9]).+([0-9])/modules) - ((${#all_modules[@]})) || die 'ERROR: Discord modules directory not found.' - modules=${all_modules[-1]} - verbose 1 "V: Found modules in $modules" -} - -bdc_snap() { - # shellcheck disable=SC2016 - # Expansion should happen inside snap's shell. - snap_location=$("$snap_bin" run --shell discord <<< $'printf -- \'%s\n\' "$SNAP" 1>&3' 3>&1) - discord=${snap_location:?}/usr/share/discord - verbose 2 "VV: Checking $discord" - if [[ -d $discord ]]; then - verbose 1 "V: Using Discord at $discord" - # shellcheck disable=SC2016 - # Expansion should happen inside snap's shell. - xdg_config=$("$snap_bin" run --shell discord <<< $'printf -- \'%s/.config\n\' "$SNAP_USER_DATA" 1>&3' 3>&1) - discord_config=$xdg_config/discord - bdc_find_modules - else - die 'ERROR: Discord installation not found.' - fi -} - -bdc_flatpak() { - flatpak_version=$("$flatpak_bin" --version | sed -n 's/Flatpak //p') - if [[ $(Semver::compare "$flatpak_version" '1.0.0') -eq -1 ]]; then - die 'ERROR: You are using an unsupported version of Flatpak.' \ - 'See https://github.com/bb010g/betterdiscordctl/issues/45' - fi - # flatpak sucks and doesn't use stderr for warnings. - # https://github.com/flatpak/flatpak/blob/13e449b/app/flatpak-main.c#L259-L286 - # This really should be better for directories with newlines, but... - # We're just going to grab the last line and hope for the best. - flatpak_location=$("$flatpak_bin" info --show-location com.discordapp.Discord) - flatpak_location=${flatpak_location##*$'\n'} - if [[ -d ${flatpak_location:?}/files/discord ]]; then - discord=$flatpak_location/files/discord - else - discord=$flatpak_location/files/extra - fi - verbose 2 "VV: Checking $discord" - if [[ -d $discord ]]; then - verbose 1 "V: Using Discord at $discord" - # shellcheck disable=SC2016 - # Expansion should happen inside flatpak's shell. - flatpak_config=$("$flatpak_bin" run --command=sh com.discordapp.Discord -c $'printf -- \'%s\n\' "$XDG_CONFIG_HOME"') - discord_config=${flatpak_config:-$HOME/.var/app/com.discordapp.Discord/config}/discord - if [[ ! -d $discord_config ]]; then - printf 'WARN: Config directory not found for Discord (%s, %s).\n' "$discord" "$discord_config" >&2 - fi - bdc_find_modules - else - die 'ERROR: Discord installation not found.' - fi -} - -bdc_kill() { - declare process_name=Discord - [[ $flavor ]] && process_name+=" $flavor" - printf 'Killing %s processes...\n' "$process_name" >&2 - pkill -exi -KILL "discord-?$flavor" || printf 'No active processes found.\n' >&2 -} - -bd_injector() { - if [[ -z $bd ]]; then - bd=$data/bd/$(bd_map_add "$discord" "$bd_repo") - if [[ ! -d $bd ]]; then - printf 'Cloning %s...\n' "$bd_repo" >&2 - git clone "$bd_repo" -b "$bd_repo_branch" --depth=1 --single-branch "$bd" - fi - fi - - if [[ $copy_bd ]]; then - verbose 1 'V: Copying BetterDiscord injector...' - cp -r "$bd" "$core/injector" - else - verbose 1 'V: Linking BetterDiscord injector...' - ln -s "$bd" "$core/injector" - fi -} - -bd_patch() { - if ! grep -q 'injector' "$core/index.js"; then - verbose 1 'V: Injecting into index.js...' - sed -i "$core/index.js" \ - -e "1i require('./injector');" \ - -e "s/core'/core.asar'/" - fi -} - -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" -} - -bd_map_entry_n() { - sed 's/^.*\t\t.*\t\(.*\)$/\1/' "$@" -} - -bd_map_fresh() { - verbose 2 'VV: Generating fresh bd_map number...' - bd_map_entry_n "$data/bd_map" | sort | awk \ - 'BEGIN {max=-1} NF != 0 {if ($1>max+1) {exit}; max=$1} END {print max+1}' -} - -bd_map_add() { - entry=$(bd_map_get_repo "$2") - if [[ $entry ]]; then - num=$(head -n1 <<< "$entry" | bd_map_entry_n) - else - num=$(bd_map_fresh) - fi - printf '%s\t\t%s\t%s\n' "$1" "$2" "$num" >> "$data/bd_map" - printf '%s\n' "$num" -} - -bd_map_get_dir() { - grep -F "$1"$'\t\t' "$data/bd_map" -} - -bd_map_get_repo() { - grep -F $'\t\t'"$1"$'\t' "$data/bd_map" -} - -bd_map_get_n() { - grep $'\t'"$1\$" "$data/bd_map" -} - -bd_map_remove() { - sed -i "$data/bd_map" -e "\\%$1\\t\\t%d" -} - -# Included from https://github.com/bb010g/Semver.sh , under the MIT License. - -Semver::validate() { - # shellcheck disable=SC2064 - trap "$(shopt -p extglob)" RETURN - shopt -s extglob - - declare normal=${1%%[+-]*} - declare extra=${1:${#normal}} - - declare major=${normal%%.*} - if [[ $major != +([0-9]) ]]; then echo "Semver::validate: invalid major: $major" >&2; return 1; fi - normal=${normal:${#major}+1} - declare minor=${normal%%.*} - if [[ $minor != +([0-9]) ]]; then echo "Semver::validate: invalid minor: $minor" >&2; return 1; fi - declare patch=${normal:${#minor}+1} - if [[ $patch != +([0-9]) ]]; then echo "Semver::validate: invalid patch: $patch" >&2; return 1; fi - - declare -r ident="+([0-9A-Za-z-])" - declare pre=${extra%%+*} - declare pre_len=${#pre} - if [[ $pre_len -gt 0 ]]; then - pre=${pre#-} - if [[ $pre != $ident*(.$ident) ]]; then echo "Semver::validate: invalid pre-release: $pre" >&2; return 1; fi - fi - declare build=${extra:pre_len} - if [[ ${#build} -gt 0 ]]; then - build=${build#+} - if [[ $build != $ident*(.$ident) ]]; then echo "Semver::validate: invalid build metadata: $build" >&2; return 1; fi - fi - - if [[ $2 ]]; then - echo "$2=(${major@Q} ${minor@Q} ${patch@Q} ${pre@Q} ${build@Q})" - else - echo "$1" - fi -} - -Semver::compare() { - declare -a x y - eval "$(Semver::validate "$1" x)" - eval "$(Semver::validate "$2" y)" - - declare x_i y_i i - for i in 0 1 2; do - x_i=${x[i]}; y_i=${y[i]} - if [[ $x_i -eq $y_i ]]; then continue; fi - if [[ $x_i -gt $y_i ]]; then echo 1; return; fi - if [[ $x_i -lt $y_i ]]; then echo -1; return; fi - done - - x_i=${x[3]}; y_i=${y[3]} - if [[ -z $x_i && $y_i ]]; then echo 1; return; fi - if [[ $x_i && -z $y_i ]]; then echo -1; return; fi - - declare -a x_pre; declare x_len - declare -a y_pre; declare y_len - IFS=. read -ra x_pre <<< "$x_i"; x_len=${#x_pre[@]} - IFS=. read -ra y_pre <<< "$y_i"; y_len=${#y_pre[@]} - - if (( x_len > y_len )); then echo 1; return; fi - if (( x_len < y_len )); then echo -1; return; fi - - for (( i=0; i < x_len; i++ )); do - x_i=${x_pre[i]}; y_i=${y_pre[i]} - if [[ $x_i = "$y_i" ]]; then continue; fi - - declare num_x num_y - num_x=$([[ $x_i = +([0-9]) ]] && echo "$x_i") - num_y=$([[ $y_i = +([0-9]) ]] && echo "$y_i") - if [[ $num_x && $num_y ]]; then - if [[ $x_i -gt $y_i ]]; then echo 1; return; fi - if [[ $x_i -lt $y_i ]]; then echo -1; return; fi - else - if [[ $num_y ]]; then echo 1; return; fi - if [[ $num_x ]]; then echo -1; return; fi - if [[ $x_i > $y_i ]]; then echo 1; return; fi - if [[ $x_i < $y_i ]]; then echo -1; return; fi - fi - done - - echo 0 -} - -# Run command - -case "$cmd" in - status) - bdc_main - bdc_status - ;; - install) - bdc_main - bdc_install - ;; - reinstall) - bdc_main - bdc_reinstall - ;; - update) - bdc_main - bdc_update - ;; - uninstall) - bdc_main - bdc_uninstall - ;; - upgrade) - bdc_upgrade - ;; - *) - die "ERROR: Unknown command: $cmd" - ;; -esac |