671 lines
21 KiB
Bash
Executable File
671 lines
21 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -ueo pipefail
|
|
shopt -s dotglob extglob nullglob
|
|
|
|
# Constants
|
|
VERSION=2.0.1
|
|
SOURCE=$(readlink -f "${BASH_SOURCE[0]}")
|
|
DISABLE_SELF_UPGRADE=
|
|
|
|
# Options
|
|
cmd=
|
|
verbosity=0
|
|
d_flavors=('' canary ptb development)
|
|
d_modules=
|
|
bd_remote=github
|
|
bd_remote_dir=
|
|
bd_remote_url=
|
|
bd_remote_github_owner=BetterDiscord
|
|
bd_remote_github_repo=BetterDiscord
|
|
bd_remote_github_release=latest
|
|
bd_remote_asar=betterdiscord.asar
|
|
d_install=traditional
|
|
flatpak_bin=flatpak
|
|
snap_bin=snap
|
|
self_upgrade_url='https://github.com/bb010g/betterdiscordctl/raw/master/betterdiscordctl'
|
|
|
|
# Variables
|
|
d_flavor=
|
|
d_core=
|
|
xdg_config=
|
|
bdc_data=${XDG_DATA_HOME:-$HOME/.local/share}/betterdiscordctl
|
|
d_config=
|
|
bd_config=
|
|
bd_asar=
|
|
bd_asar_escaped=
|
|
bd_asar_name=
|
|
|
|
show_help() {
|
|
cat << EOF
|
|
Usage: ${0##*/} [-f d_flavors] \\
|
|
[-D <bd_r_dir>|-U <bd_r_url>|-H <bd_r_github>] \\
|
|
[-i (traditional|flatpak|snap)] <command>
|
|
|
|
Manage BetterDiscord installations on Linux.
|
|
|
|
Options:
|
|
-V, --version display version info and exit
|
|
-h, --help display this help message and exit
|
|
-v, --verbose increase verbosity
|
|
-q, --quiet decrease verbosity
|
|
-f, --d-flavors <d_flavors> discover Discord installations with the
|
|
colon-separated list of suffixes <d_flavors>.
|
|
Defaults to ':canary:ptb:development'. Flavors
|
|
must be lowercase. Stable is flavor '', as
|
|
it's unsuffixed. Flavors shouldn't include
|
|
spaces.
|
|
-m, --d-modules <d_modules> use Discord modules in directory <d_modules>.
|
|
Defaults to discovery. Discord's user-specific
|
|
storage directory should contain <d_modules>.
|
|
-D, --bd-remote-dir reference BetterDiscord files at directory
|
|
<bd_r_dir> <bd_r_dir>. Overrides earlier --bd-remote-url
|
|
or --bd-remote-github. An empty string keeps a
|
|
previous value.
|
|
-U, --bd-remote-url download BetterDiscord files at base URL
|
|
<bd_r_url> <bd_r_url>. Overrides earlier --bd-remote-dir
|
|
or --bd-remote-github. An empty string keeps a
|
|
previous value. Works like --bd-remote-dir
|
|
with files downloaded into BetterDiscord's
|
|
data directory.
|
|
-H, --bd-remote-github download BetterDiscord files at GitHub
|
|
<bd_r_github> repository release <bd_r_github>, of form
|
|
[~<owner>][/<repo>][#<release>]. Defaults to
|
|
'~BetterDiscord/BetterDiscord#latest'. Overrides
|
|
earlier --bd-remote-dir or --bd-remote-github.
|
|
An omitted part keeps a previous value.
|
|
<owner> and <repo> must not contain '~', '/',
|
|
or '#'. Works like --bd-remote-url with a
|
|
GitHub repository release download base URL.
|
|
--bd-remote-asar <bd_r_asar> finds "betterdiscord.asar" at path <bd_r_asar>
|
|
relative to remote. Defaults to
|
|
'betterdiscord.asar'.
|
|
-i, --d-install traditional use a traditional Discord install. Default.
|
|
-i, --d-install flatpak use a Discord Flatpak app
|
|
-i, --d-install snap use a Discord Snap app
|
|
--flatpak-bin <flatpak> invoke Flatpak executable <flatpak>. Defaults
|
|
to 'flatpak'.
|
|
--snap-bin <snap> invoke Snap executable <snap>. Defaults to
|
|
'snap'.
|
|
--self-upgrade-url query <self_upgrade_url> for self-upgrades
|
|
<self_upgrade_url>
|
|
|
|
Commands:
|
|
status show the current Discord patch state
|
|
install install BetterDiscord
|
|
reinstall reinstall BetterDiscord
|
|
uninstall uninstall BetterDiscord
|
|
self-upgrade upgrade this program
|
|
EOF
|
|
}
|
|
|
|
verbose() {
|
|
if (( verbosity >= $1 )); then
|
|
shift
|
|
>&2 printf '%s\n' "$1"
|
|
fi
|
|
}
|
|
|
|
die() {
|
|
while (( $# > 0 )); do
|
|
>&2 printf '%s\n' "$1"
|
|
shift
|
|
done
|
|
exit 1
|
|
}
|
|
|
|
die_with_help() {
|
|
die "$@" "Use \`${0##*/} --help\` for more information."
|
|
}
|
|
|
|
die_option() {
|
|
die_with_help "ERROR: \"$1\" requires an option argument."
|
|
}
|
|
|
|
die_non_empty_option() {
|
|
die_with_help "ERROR: \"$1\" requires a non-empty option argument."
|
|
}
|
|
|
|
die_non_empty_option_part() {
|
|
die_with_help "ERROR: \"$1\" requires a non-empty $2 option argument part."
|
|
}
|
|
|
|
# arg parsing: top-level: options
|
|
while :; do
|
|
if [[ -z ${1+x} ]]; then break; fi
|
|
case $1 in
|
|
-V|--version)
|
|
>&2 printf 'betterdiscordctl %s\n' "$VERSION"
|
|
exit
|
|
;;
|
|
-h|-\?|--help)
|
|
show_help; exit
|
|
;;
|
|
-v|--verbose)
|
|
((verbosity++)) || :
|
|
;;
|
|
-q|--quiet)
|
|
((verbosity--)) || :
|
|
;;
|
|
-f|--d-flavors)
|
|
if [[ ${2+x} ]]; then
|
|
if [[ $2 != "${2,,}" ]]; then
|
|
die_with_help "ERROR: Discord flavors list must be lowercase: $2"
|
|
else
|
|
IFS=':' read -ra d_flavors <<< "$2:"; shift
|
|
fi
|
|
else die_option "$1"; fi
|
|
;;
|
|
-m|--d-modules)
|
|
if [[ ${2:+x} ]]; then d_modules=$2; shift
|
|
else die_non_empty_option "$1"; fi
|
|
;;
|
|
-D|--bd-remote-dir)
|
|
bd_remote=dir
|
|
if [[ ${2+x} ]]; then [[ ${2:+x} ]] && bd_remote_dir=$2; shift
|
|
else die_option "$1"; fi
|
|
;;
|
|
-U|--bd-remote-url)
|
|
bd_remote=url
|
|
if [[ ${2+x} ]]; then [[ ${2:+x} ]] && bd_remote_url=$2; shift
|
|
else die_option "$1"; fi
|
|
;;
|
|
-H|--bd-remote-github)
|
|
bd_remote=github
|
|
if [[ ${2+x} ]]; then
|
|
if [[ ! $2 =~ (~?[^~/#]*)(/?[^~/#]*)(#?.*) ]]; then
|
|
die_with_help "ERROR: \"$1\" requires a valid option argument."
|
|
fi
|
|
if [[ ${BASH_REMATCH[1]} ]]; then
|
|
[[ ${BASH_REMATCH[2]} != '~' ]] || die_non_empty_option_part "$1" '<owner>'
|
|
bd_remote_github_owner=${BASH_REMATCH[1]:1}
|
|
fi
|
|
if [[ ${BASH_REMATCH[2]} ]]; then
|
|
[[ ${BASH_REMATCH[2]} != '/' ]] || die_non_empty_option_part "$1" '<repo>'
|
|
bd_remote_github_repo=${BASH_REMATCH[2]:1}
|
|
fi
|
|
if [[ ${BASH_REMATCH[3]} ]]; then
|
|
[[ ${BASH_REMATCH[3]} != '#' ]] || die_non_empty_option_part "$1" '<release>'
|
|
bd_remote_github_release=${BASH_REMATCH[3]:1}
|
|
fi
|
|
shift
|
|
else die_option "$1"; fi
|
|
;;
|
|
--bd-remote-asar)
|
|
if [[ ${2:+x} ]]; then bd_remote_asar=$2; shift
|
|
else die_non_empty_option "$1"; fi
|
|
;;
|
|
-i|--d-install)
|
|
if [[ ${2:+x} ]]; then case "$2" in
|
|
traditional|flatpak|snap) d_install=$2 ;;
|
|
*) die_with_help "ERROR: Unknown top-level $1 value: $2" ;;
|
|
esac; shift; else die_non_empty_option "$1"; fi
|
|
;;
|
|
--flatpak-bin)
|
|
if [[ ${2:+x} ]]; then flatpak_bin=$2; shift
|
|
else die_non_empty_option "$1"; fi
|
|
;;
|
|
--snap-bin)
|
|
if [[ ${2:+x} ]]; then snap_bin=$2; shift
|
|
else die_non_empty_option "$1"; fi
|
|
;;
|
|
--self-upgrade-url)
|
|
if [[ ${2:+x} ]]; then self_upgrade_url=$2; shift
|
|
else die_non_empty_option "$1"; fi
|
|
;;
|
|
# footer
|
|
-*=*) die "ERROR: Keyed options must not be separated by equals: $1" ;;
|
|
--) shift; break ;;
|
|
-?|--*) die_with_help "ERROR: Unknown top-level option: $1" ;;
|
|
-??*) die "ERROR: Switches must not be ran together: $1" ;;
|
|
*) break
|
|
esac
|
|
shift
|
|
done
|
|
# arg parsing: top-level: arguments
|
|
while :; do
|
|
if [[ -z ${1+x} ]]; then break; fi
|
|
case "$1" in
|
|
status|install|reinstall|uninstall|self-upgrade)
|
|
cmd=$1
|
|
shift
|
|
break
|
|
;;
|
|
*) die_with_help "ERROR: Unknown top-level argument: $1"
|
|
esac
|
|
shift
|
|
done
|
|
# arg parsing: top-level: validation
|
|
case "$bd_remote" in
|
|
github)
|
|
[[ $bd_remote_github_owner ]] || die_non_empty_option_part '--bd-remote-github' '<owner>'
|
|
[[ $bd_remote_github_repo ]] || die_non_empty_option_part '--bd-remote-github' '<repo>'
|
|
[[ $bd_remote_github_release ]] || die_non_empty_option_part '--bd-remote-github' '<release>'
|
|
;;
|
|
url)
|
|
[[ $bd_remote_url ]] || die_non_empty_option '--bd-remote-url'
|
|
;;
|
|
dir)
|
|
[[ $bd_remote_dir ]] || die_non_empty_option '--bd-remote-dir'
|
|
;;
|
|
esac
|
|
# arg parsing: top-level: command dispatch
|
|
case "$cmd" in
|
|
status|install|reinstall|uninstall|self-upgrade)
|
|
# arg parsing: (status|install|reinstall|uninstall|self-upgrade): options
|
|
while :; do
|
|
if [[ -z ${1+x} ]]; then break; fi
|
|
case "$1" in
|
|
# footer
|
|
-*=*) die "ERROR: Keyed options must not be separated by equals: $1" ;;
|
|
--) shift; break ;;
|
|
-?|--*) die_with_help "ERROR: Unknown |$cmd| option: $1" ;;
|
|
-??*) die "ERROR: Switches must not be ran together: $1" ;;
|
|
esac
|
|
shift
|
|
done
|
|
# arg parsing: (status|install|reinstall|uninstall|self-upgrade): arguments
|
|
if [[ -n ${1+x} ]]; then
|
|
die_with_help "ERROR: Unknown |$cmd| argument: $1"
|
|
fi
|
|
;;
|
|
'')
|
|
die_with_help "ERROR: Specify a non-empty command."
|
|
;;
|
|
*) die "ERROR: [arg parsing: top-level: command dispatch] Unknown command: $cmd" ;;
|
|
esac
|
|
|
|
# currently unused
|
|
# mkdir -p "$bdc_data"
|
|
|
|
# Commands
|
|
|
|
bdc_status() {
|
|
declare asar_install bd_remote_status index_mod
|
|
asar_install=no
|
|
index_mod=no
|
|
verbose 2 "VV: BetterDiscord asar installation: $bd_asar"
|
|
if [[ -h $bd_asar && ! -f $bd_asar ]]; then
|
|
asar_install='(broken link) no'
|
|
elif [[ -f $bd_asar ]]; then
|
|
asar_install='(symbolic link) yes'
|
|
elif [[ -d $bd_config ]]; then
|
|
asar_install='(missing) no'
|
|
fi
|
|
if grep -Fq "$bd_asar_escaped" "$d_core/index.js"; then
|
|
index_mod=yes
|
|
elif grep -Fq "$bd_asar_name" "$d_core/index.js"; then
|
|
index_mod=noncompliant
|
|
elif grep -Fq 'betterdiscord.asar' "$d_core/index.js"; then
|
|
index_mod=noncompliant
|
|
fi
|
|
|
|
bd_remote_status="$bd_remote"
|
|
case "$bd_remote" in
|
|
github)
|
|
bd_remote_status+="
|
|
BetterDiscord remote GitHub: ~$bd_remote_github_owner/$bd_remote_github_repo#$bd_remote_github_release"
|
|
;;
|
|
url)
|
|
bd_remote_status+="
|
|
BetterDiscord remote URL: $bd_remote_url"
|
|
;;
|
|
dir)
|
|
bd_remote_status+="
|
|
BetterDiscord remote directory: $bd_remote_dir"
|
|
;;
|
|
esac
|
|
|
|
printf 'Discord install: %s
|
|
Discord flavor: %s
|
|
Discord modules: %s
|
|
BetterDiscord directory: %s
|
|
BetterDiscord asar installed: %s
|
|
Discord "index.js" injected: %s
|
|
BetterDiscord remote: %s
|
|
' "$d_install" "$d_flavor" "$d_modules" "$bd_config" "$asar_install" \
|
|
"$index_mod" "$bd_remote_status"
|
|
}
|
|
|
|
bdc_install() {
|
|
grep -Fq "$bd_asar_escaped" "$d_core/index.js" && die 'ERROR: Already installed.'
|
|
bdc_clean_legacy
|
|
|
|
bd_remote_install
|
|
bd_install
|
|
|
|
>&2 printf 'Installed. (Restart Discord if necessary.)\n'
|
|
}
|
|
|
|
bdc_reinstall() {
|
|
grep -Fq "$bd_asar_name" "$d_core/index.js" || die 'ERROR: Not installed.'
|
|
bdc_clean_legacy
|
|
|
|
bdc_kill
|
|
|
|
bd_remote_install
|
|
bd_install
|
|
|
|
>&2 printf 'Reinstalled.\n'
|
|
}
|
|
|
|
bdc_uninstall() {
|
|
grep -Fq "$bd_asar_name" "$d_core/index.js" || die 'ERROR: Not installed.'
|
|
bdc_clean_legacy
|
|
|
|
bdc_kill
|
|
bd_uninstall
|
|
|
|
>&2 printf 'Uninstalled.\n'
|
|
}
|
|
|
|
bdc_self_upgrade() {
|
|
if [[ $DISABLE_SELF_UPGRADE ]]; then
|
|
die 'ERROR: Self-upgrading has been disabled.' \
|
|
'If you installed this from a package, its maintainer should keep it up to date.'
|
|
fi
|
|
|
|
declare self_upgrade_version semver_diff
|
|
self_upgrade_version=$(curl -NLSs "$self_upgrade_url" | sed -n 's/^VERSION=//p')
|
|
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
|
|
die "ERROR: The remote script URL couldn't be reached to check the version."
|
|
fi
|
|
verbose 2 "VV: Local script location: $SOURCE"
|
|
verbose 2 "VV: Remote script URL: $self_upgrade_url"
|
|
verbose 1 "V: Local version: $VERSION"
|
|
verbose 1 "V: Remote version: $self_upgrade_version"
|
|
semver_diff=$(Semver::compare "$self_upgrade_version" "$VERSION")
|
|
if [[ $semver_diff -eq 1 ]]; then
|
|
>&2 printf 'Downloading betterdiscordctl...\n'
|
|
if curl -LSso "$SOURCE" "$self_upgrade_url"; then
|
|
>&2 printf 'Successfully self-upgraded betterdiscordctl.\n'
|
|
else
|
|
die 'ERROR: Failed to self-upgrade betterdiscordctl.' \
|
|
"You may want to rerun this command with \`sudo\`."
|
|
fi
|
|
else
|
|
if [[ $semver_diff -eq 0 ]]; then
|
|
>&2 printf 'betterdiscordctl is already the latest version (%s).\n' \
|
|
"$VERSION"
|
|
else
|
|
>&2 printf 'Local version (%s) is higher than remote version (%s).\n' \
|
|
"$VERSION" "$self_upgrade_version"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Implementation functions
|
|
|
|
bdc_main() {
|
|
xdg_discover_config
|
|
bdc_discover
|
|
d_core=$d_modules/discord_desktop_core
|
|
[[ -d $d_core ]] || die "ERROR: Directory 'discord_desktop_core' not found in: $d_modules"
|
|
bd_remote_init
|
|
bd_asar=$bd_config/data/$bd_asar_name
|
|
bd_asar_escaped=${bd_asar/\\/\\\\}
|
|
}
|
|
|
|
xdg_discover_config() {
|
|
case "$d_install" in
|
|
traditional)
|
|
xdg_config=${XDG_CONFIG_HOME:-$HOME/.config}
|
|
;;
|
|
snap)
|
|
# 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)
|
|
;;
|
|
flatpak)
|
|
# shellcheck disable=SC2016
|
|
# Expansion should happen inside flatpak's shell.
|
|
xdg_config=$("$flatpak_bin" run --command=sh com.discordapp.Discord \
|
|
-c $'printf -- \'%s\n\' "$XDG_CONFIG_HOME"')
|
|
xdg_config=${xdg_config:-$HOME/.var/app/com.discordapp.Discord/config}
|
|
;;
|
|
*) die "ERROR: [xdg_discover_config] Unknown Discord install variant: $d_install" ;;
|
|
esac
|
|
[[ $xdg_config ]] || >&2 printf "WARN: XDG user config directory (\$XDG_CONFIG_HOME) not found.\n"
|
|
}
|
|
|
|
bdc_discover() {
|
|
d_discover_config
|
|
bd_discover_config
|
|
bdc_find_modules
|
|
}
|
|
|
|
bdc_find_modules() {
|
|
if [[ $d_modules ]]; then
|
|
[[ -d $d_modules ]] || die "ERROR: Discord modules directory not found: $d_modules"
|
|
d_flavor=${d_modules%/*/modules}
|
|
d_flavor=${d_flavor##*/discord}
|
|
else
|
|
[[ -d $d_config ]] || die "ERROR: Discord $d_flavor config directory not found: $d_config"
|
|
declare -a all_d_modules
|
|
all_d_modules=("$d_config/"+([0-9]).+([0-9]).+([0-9])/modules)
|
|
((${#all_d_modules[@]})) || die 'ERROR: Discord modules directory not found.' \
|
|
'Try specifying it with --d-modules.'
|
|
d_modules=${all_d_modules[-1]}
|
|
verbose 1 "V: Found modules in $d_modules"
|
|
fi
|
|
}
|
|
|
|
bdc_kill() {
|
|
>&2 printf 'Killing Discord %s processes...\n' "$d_flavor"
|
|
pkill -exi -KILL "discord${d_flavor:0:8}" || >&2 printf 'No active processes found.\n'
|
|
}
|
|
|
|
d_discover_config() {
|
|
[[ $xdg_config ]] || die "ERROR: XDG user config directory (\$XDG_CONFIG_HOME) not found."
|
|
case "$d_install" in
|
|
traditional)
|
|
for d_flavor in "${d_flavors[@]}"; do
|
|
verbose 2 "VV: Trying flavor '$d_flavor'"
|
|
d_config=$xdg_config/discord${d_flavor,,}
|
|
if [[ -d $d_config ]]; then
|
|
break
|
|
fi
|
|
>&2 printf 'WARN: Discord %s config directory not found (%s).\n' \
|
|
"$d_flavor" "$d_config"
|
|
done
|
|
;;
|
|
snap|flatpak)
|
|
d_config=$xdg_config/discord
|
|
if [[ ! -d $d_config ]]; then
|
|
>&2 printf 'WARN: Discord %s config directory not found (%s).\n' \
|
|
"$d_install" "$d_config"
|
|
fi
|
|
;;
|
|
*) die "ERROR: [d_discover_config] Unknown Discord install variant: $d_install" ;;
|
|
esac
|
|
}
|
|
|
|
bd_discover_config() {
|
|
[[ $xdg_config ]] || die "ERROR: XDG user config directory (\$XDG_CONFIG_HOME) not found."
|
|
case "$d_install" in
|
|
traditional|snap|flatpak)
|
|
bd_config=$xdg_config/BetterDiscord
|
|
;;
|
|
*) die "ERROR: [bd_discover_config] Unknown Discord install variant: $d_install" ;;
|
|
esac
|
|
}
|
|
|
|
# TODO: Integrate $bd_remote into main & install
|
|
|
|
bd_remote_init() {
|
|
case "$bd_remote" in
|
|
github) bd_remote_init_github ;;
|
|
url) bd_remote_init_url ;;
|
|
dir) bd_remote_init_dir ;;
|
|
*) die "ERROR: [bd remote init] Unknown remote type: $bd_remote" ;;
|
|
esac
|
|
verbose 2 "VV: BetterDiscord remote asar path: $bd_remote_asar"
|
|
bd_asar_name=${bd_remote_asar##*/}
|
|
}
|
|
bd_remote_init_github() {
|
|
bd_remote_url=https://github.com/$bd_remote_github_owner/$bd_remote_github_repo/releases/$bd_remote_github_release/download
|
|
verbose 2 "VV: BetterDiscord remote GitHub repository owner: $bd_remote_github_owner"
|
|
verbose 2 "VV: BetterDiscord remote GitHub repository name: $bd_remote_github_repo"
|
|
verbose 2 "VV: BetterDiscord remote GitHub repository release: $bd_remote_github_release"
|
|
bd_remote_init_url
|
|
}
|
|
bd_remote_init_url() {
|
|
bd_remote_dir=$bd_config/data
|
|
verbose 2 "VV: BetterDiscord remote URL: $bd_remote_url"
|
|
bd_remote_init_dir
|
|
}
|
|
bd_remote_init_dir() {
|
|
verbose 2 "VV: BetterDiscord remote directory: $bd_remote_dir"
|
|
}
|
|
|
|
bd_remote_install() {
|
|
case "$bd_remote" in
|
|
github) bd_remote_install_github ;;
|
|
url) bd_remote_install_url ;;
|
|
dir) bd_remote_install_dir ;;
|
|
*) die "ERROR: [bd remote install] Unknown remote type: $bd_remote" ;;
|
|
esac
|
|
}
|
|
bd_remote_install_github() {
|
|
verbose 2 "VV: Installing remote BetterDiscord (GitHub)..."
|
|
bd_remote_install_url
|
|
}
|
|
bd_remote_install_url() {
|
|
verbose 2 "VV: Installing remote BetterDiscord (URL)..."
|
|
verbose 1 "V: Downloading BetterDiscord asar..."
|
|
curl -LSso "$bd_remote_dir/$bd_remote_asar" --create-dirs \
|
|
"$bd_remote_url/$bd_remote_asar"
|
|
bd_remote_install_dir
|
|
}
|
|
bd_remote_install_dir() {
|
|
verbose 2 "VV: Installing remote BetterDiscord (directory)..."
|
|
if [[ "$bd_remote_dir/$bd_remote_asar" != "$bd_asar" ]]; then
|
|
verbose 1 "V: Copying BetterDiscord asar..."
|
|
install -Dm 644 "$bd_remote_dir/$bd_remote_asar" "$bd_asar"
|
|
fi
|
|
}
|
|
|
|
bdc_clean_legacy() {
|
|
if [[ -d $d_core/core ]]; then
|
|
>&2 printf 'Removing legacy core directory...\n'
|
|
rm -rf "$d_core/core"
|
|
fi
|
|
if [[ -d $d_core/injector ]]; then
|
|
>&2 printf 'Removing legacy injector directory...\n'
|
|
rm -rf "$d_core/injector"
|
|
fi
|
|
if [[ -d $bdc_data ]]; then
|
|
if [[ -f "$bdc_data/bd_map" || -d "$bdc_data/bd" ]]; then
|
|
>&2 printf 'Removing legacy machine-specific data...\n'
|
|
rm -rf "$bdc_data/bd_map" "$bdc_data/bd"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
bd_install() {
|
|
verbose 1 'V: Injecting into index.js...'
|
|
printf $'require("%s");
|
|
module.exports = require(\'./core.asar\');
|
|
' "$bd_asar_escaped" > "$d_core/index.js"
|
|
}
|
|
|
|
bd_uninstall() {
|
|
verbose 1 'V: Removing BetterDiscord injection...'
|
|
printf $'module.exports = require(\'./core.asar\');
|
|
' > "$d_core/index.js"
|
|
}
|
|
|
|
# Included from https://github.com/bb010g/Semver.sh , under the MIT License.
|
|
|
|
Semver::validate() {
|
|
[[ $1 =~ ^([^+-.]*)\.?([^+-.]*)\.?([^+-]*)(-?)([^+]*)(\+?)(.*)$ ]]
|
|
declare -a ver; ver=("${BASH_REMATCH[@]:1}")
|
|
|
|
if [[ ${ver[0]} != +([0-9]) ]]; then printf '%s\n' "Semver::validate: invalid major: ${ver[0]}" >&2; return 1; fi
|
|
if [[ ${ver[1]} != +([0-9]) ]]; then printf '%s\n' "Semver::validate: invalid minor: ${ver[1]}" >&2; return 1; fi
|
|
if [[ ${ver[2]} != +([0-9]) ]]; then printf '%s\n' "Semver::validate: invalid patch: ${ver[2]}" >&2; return 1; fi
|
|
|
|
if [[ ${ver[3]} == '-' && ${ver[4]} != +([0-9A-Za-z-])*(.+([0-9A-Za-z-])) ]]; then
|
|
printf '%s\n' "Semver::validate: invalid pre-release: ${ver[4]}" >&2; return 1
|
|
fi
|
|
if [[ ${ver[5]} == '+' && ${ver[6]} != +([0-9A-Za-z-])*(.+([0-9A-Za-z-])) ]]; then
|
|
printf '%s\n' "Semver::validate: invalid build metadata: ${ver[6]}" >&2; return 1
|
|
fi
|
|
|
|
if [[ -n $2 ]]; then
|
|
printf '%s\n' "$2=(${ver[0]@Q} ${ver[1]@Q} ${ver[2]@Q} ${ver[4]@Q} ${ver[6]@Q})"
|
|
else
|
|
printf '%s\n' "$1"
|
|
fi
|
|
}
|
|
|
|
Semver::compare() {
|
|
declare -a xs ys
|
|
eval "$(Semver::validate "$1" xs)"
|
|
eval "$(Semver::validate "$2" ys)"
|
|
|
|
declare i x y
|
|
for i in 0 1 2; do
|
|
x=${xs[i]}; y=${ys[i]}
|
|
if [[ $x -eq $y ]]; then continue; fi
|
|
if [[ $x -gt $y ]]; then echo 1; return; fi
|
|
if [[ $x -lt $y ]]; then echo -1; return; fi
|
|
done
|
|
|
|
x=${xs[3]}; y=${ys[3]}
|
|
if [[ -z $x && -n $y ]]; then echo 1; return; fi
|
|
if [[ -n $x && -z $y ]]; 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."; x_len=${#x_pre[@]}
|
|
IFS=. read -ra y_pre <<< "$y."; 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=${x_pre[i]}; y=${y_pre[i]}
|
|
if [[ $x == "$y" ]]; then continue; fi
|
|
|
|
if [[ $x == +([0-9]) ]]; then
|
|
if [[ $y == +([0-9]) ]]; then
|
|
if [[ $x -gt $y ]]; then echo 1; return; fi
|
|
if [[ $x -lt $y ]]; then echo -1; return; fi
|
|
else echo -1; return; fi
|
|
elif [[ $y == +([0-9]) ]]; then echo 1; return
|
|
else
|
|
if [[ $x > $y ]]; then echo 1; return; fi
|
|
if [[ $x < $y ]]; 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
|
|
;;
|
|
uninstall)
|
|
bdc_main
|
|
bdc_uninstall
|
|
;;
|
|
self-upgrade)
|
|
bdc_self_upgrade
|
|
;;
|
|
*) die "ERROR: Unknown command (in command dispatch): $cmd" ;;
|
|
esac
|