-
Notifications
You must be signed in to change notification settings - Fork 1
/
discord-appimage.sh
executable file
·413 lines (403 loc) · 21 KB
/
discord-appimage.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
#!/bin/bash -x
# Author: Syretia
# Name: discord-appimage
# License: MIT
# Description: Builds an AppImage of Discord and keeps it up to date
# Dependencies (only required for building from scratch): ar (binutils), curl
# function to display messages
discord_msg() {
msg_type="$2"
if command -v fltk-dialog > /dev/null; then
fltk-dialog --title="Discord AppImage" --close-label="OK" --center --"$msg_type" --text="$1" --width=500
elif command -v xmessage > /dev/null; then
case "$msg_type" in
error|message) xmessage -buttons OK:0 -center -geometry 500x150 "$1";;
question) xmessage -buttons Yes:0,No:1 -center -geometry 500x150 "$1";;
esac
else
echo "$1"
fi
}
# function to handle exits
discord_error() {
# cleanup leftover files
rm -rf "$HOME"/.cache/"$version_lower"-appimage
# kill progress bar if running
if [[ -n "$progress_pid" ]]; then
kill -SIGTERM "$progress_pid"
fi
# show error
discord_msg "$1" "error"
# exit
exit "$2"
}
# function to find latest debs from Debian's site for building AppImage
discord_dldeps() {
deb_name="$1"
# find latest deb url using grep and head -n 1
latest_deb_url="$(curl -skL "https://packages.debian.org/bullseye/amd64/$deb_name/download" | \
grep '<li>*..*amd64\.deb' | \
cut -f2 -d'"' | \
head -n 1)"
# try again if not found
if [[ -z "$latest_deb_url" ]]; then
echo "Error finding download url for '$deb_name'. Trying again..."
latest_deb_url="$(curl -skL "https://packages.debian.org/bullseye/amd64/$deb_name/download" | \
grep '<li>*..*amd64\.deb' | \
cut -f2 -d'"' | \
head -n 1)"
fi
# exit if not still found
if [[ -z "$latest_deb_url" ]]; then
discord_error "Error getting download URL for '$deb_name'" "1"
return
fi
# download latest deb, try again if fails first time
curl -skL "$latest_deb_url" -o "$HOME"/.cache/"$version_lower"-appimage/debs/"$deb_name".deb || \
curl -skL "$latest_deb_url" -o "$HOME"/.cache/"$version_lower"-appimage/debs/"$deb_name".deb || \
discord_error "Error downloading '$deb_name' from '$latest_deb_url'" "1"
}
# function to extract debs and move them to AppDir folder
discord_extractdebs() {
# mv deb to temp dir so contents can be extracted there
mv "$HOME"/.cache/"$version_lower"-appimage/debs/"$1" "$HOME"/.cache/"$version_lower"-appimage/debs/temp/"$1"
# cd to temp so 'ar' will extract files there
cd "$HOME"/.cache/"$version_lower"-appimage/debs/temp
# extract files from deb
ar x "$HOME"/.cache/"$version_lower"-appimage/debs/temp/"$1" || \
discord_error "Error using 'ar' to extract '$1'" "1"
# extract files from the data tar to AppDir
tar -xf "$HOME"/.cache/"$version_lower"-appimage/debs/temp/data.tar.* -C "$HOME"/.cache/"$version_lower"-appimage/AppDir/ || \
discord_error "Error using 'tar' to extract data tarball from '$1'" "1"
# remove leftovers
rm -rf "$HOME"/.cache/"$version_lower"-appimage/debs/temp/*
# make sure permissions are correct on all extracted files
chmod -R 755 ~/.cache/"$version_lower"-appimage
}
# function to download and extract dependencies to AppRun dir for building AppImage
discord_setup() {
# create necessary directories
mkdir -p "$HOME"/.cache/"$version_lower"-appimage/debs/temp
mkdir -p "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin
# download discord-appimage.sh script to AppDir bin
curl -skL "https://github.com/simoniz0r/Discord-AppImage/raw/master/discord-appimage.sh" \
-o "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin/discord-runner || \
discord_error "Error downloading discord-appimage.sh" "1"
chmod +x "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin/discord-runner
# download fltk-dialog (used for displaying messages)
curl -skL "https://github.com/simoniz0r/Discord-AppImage/raw/master/fltk-dialog" \
-o "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin/fltk-dialog || \
discord_error "Error downloading fltk-dialog" "1"
# make executable
chmod +x "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin/fltk-dialog
# if $discord_build_full set to true, download and extract Discord deb
if [[ "$discord_build_full" == "true" ]]; then
# download Discord deb
curl -skL "$version_url" -o "$HOME"/.cache/"$version_lower"-appimage/debs/discord.deb || \
discord_error "Error downloading $version_upper deb file" "1"
# extract discord deb
discord_extractdebs "discord.deb"
# copy discord.desktop and discord.png to AppDir
cp "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/share/"$version_lower"/"$version_lower".desktop \
"$HOME"/.cache/"$version_lower"-appimage/AppDir/"$version_lower".desktop
cp "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/share/"$version_lower"/discord.png \
"$HOME"/.cache/"$version_lower"-appimage/AppDir/"$version_lower".png
else
# else setup dummy .desktop file and icon because appimagetool needs them
echo "[Desktop Entry]" > "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'Name=Discord AppImage Builder' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'Comment=Builds Discord AppImages.' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'GenericName=Internet Messenger' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'Exec=./usr/bin/discord-runner' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'Icon=discord' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'Type=Application' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'StartupNotify=false' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'Categories=Network;' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
echo 'Keywords=discord;' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.desktop
touch "$HOME"/.cache/"$version_lower"-appimage/AppDir/discord.png
fi
# download curl binary
curl -skL "https://github.com/moparisthebest/static-curl/releases/latest/download/curl-amd64" \
-o "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin/curl || \
discord_error "Error downloading curl" "1"
# make executable
chmod +x "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin/curl
# download and extract Discord's deps
if [[ "$discord_build_full" == "true" ]]; then
deps=(binutils binutils-x86-64-linux-gnu libbinutils libctf-nobfd0 libnotify4 libxss1 libxtst6 libayatana-appindicator1 libatomic1)
else
deps=(binutils binutils-x86-64-linux-gnu libbinutils libctf-nobfd0)
fi
for dep in "${deps[@]}"; do
discord_dldeps "$dep"
discord_extractdebs "$dep.deb"
done
}
# function to build AppImage
discord_buildappimage() {
if [[ -z "$save_dir" ]]; then
# pick dir to save AppImage to
discord_msg "Please choose the directory to save the $version_upper AppImage to..." "message"
cd "$HOME"
export save_dir="$(fltk-dialog --title="Discord AppImage" --center --directory)"
fi
# exit if no dir or dir not writable
if [[ -z "$save_dir" ]]; then
discord_error "No directory chosen" "1"
fi
if [[ "$discord_build_full" == "true" ]]; then
# show progress bar while building AppImage
fltk-dialog --title="Discord AppImage" \
--center \
--width=400 \
--progress \
--pulsate \
--no-cancel \
--no-escape \
--undecorated \
--skip-taskbar \
--text="Building $version_upper AppImage. Please wait..." &
export progress_pid="$!"
sleep 0.5
fi
# create AppDir
mkdir -p "$HOME"/.cache/"$version_lower"-appimage/AppDir
# setup AppRun
echo '#!/bin/bash -x' > "$HOME"/.cache/"$version_lower"-appimage/AppDir/AppRun
echo 'export RUNNING_DIR="$(dirname "$(readlink -f "$0")")"' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/AppRun
echo 'export PATH="$RUNNING_DIR"/usr/bin/:"$PATH"' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/AppRun
echo 'export LD_LIBRARY_PATH="$RUNNING_DIR"/usr/lib/:"$RUNNING_DIR"/usr/lib/x86_64-linux-gnu:"${LD_LIBRARY_PATH}"' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/AppRun
echo 'discord-runner "$@"' >> "$HOME"/.cache/"$version_lower"-appimage/AppDir/AppRun
# make executable
chmod +x "$HOME"/.cache/"$version_lower"-appimage/AppDir/AppRun
# download and extract discord and dependencies to AppDir
discord_setup
# write version_lower to .build_version file
echo "$version_lower" > "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/bin/.build_version
if [[ "$discord_build_full" == "true" ]]; then
# run Discord's postinst script before creating AppImage
chmod +x "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/share/"$version_lower"/postinst.sh
"$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/share/"$version_lower"/postinst.sh || \
discord_error "Error running 'postinst.sh' script from $version_upper" "1"
fi
# download appimagetool
curl -skL "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" \
-o "$HOME"/.cache/"$version_lower"-appimage/appimagetool || \
discord_error "Error downloading 'appimagetool'" "1"
# make executable
chmod +x "$HOME"/.cache/"$version_lower"-appimage/appimagetool
# build AppImage using appimagetool
ARCH="x86_64" "$HOME"/.cache/"$version_lower"-appimage/appimagetool \
"$HOME"/.cache/"$version_lower"-appimage/AppDir \
"$HOME"/.cache/"$version_lower"-appimage/"$version_lower".AppImage || \
discord_error "Error using 'appimagetool' to build AppImage for $version_upper" "1"
# check if save dir is writeable
if [[ -w "$save_dir" ]]; then
# create save_dir
mkdir -p "$save_dir" || discord_error "Error creating directory '$save_dir'" "1"
# mv to save_dir
mv "$HOME"/.cache/"$version_lower"-appimage/"$version_lower".AppImage "$save_dir"/"$version_lower" || \
discord_error "Error moving $version_upper AppImage to '$save_dir'" "1"
# try to use pkexec if not writable
elif command -v pkexec &> /dev/null; then
# create save_dir and move AppImage to save_dir
pkexec bash -c "mkdir -p \"$save_dir\" && \
mv \"$HOME\"/.cache/\"$version_lower\"-appimage/\"$version_lower\".AppImage \"$save_dir\"/\"$version_lower\"" || \
discord_error "Error moving $version_upper AppImage to '$save_dir'" "1"
else
sudo_pass="$(fltk-dialog --title="Discord AppImage" \
--close-label="OK" \
--center \
--password \
--text="Authentication is needed to move the $version_upper AppImage to '$save_dir'")"
echo "$sudo_pass" | sudo -S mkdir -p "$save_dir" || discord_error "Error creating directory '$save_dir'" "1"
echo "$sudo_pass" | sudo -S mv "$HOME"/.cache/"$version_lower"-appimage/"$version_lower".AppImage "$save_dir"/"$version_lower" || \
discord_error "Error moving $version_upper AppImage to '$save_dir'" "1"
fi
# kill progress bar
if [[ -n "$progress_pid" ]]; then
kill -SIGTERM "$progress_pid"
fi
# if being ran from distributable AppImage, ask to create menu entry
if [[ "$discord_build_full" == "true" && ! -d "$running_dir/../share/$version_lower" ]]; then
discord_msg "Finished building AppImage for $version_upper version '$latest_ver' to '$save_dir/$version_lower'.\n\nWould you like to create a menu entry for $version_upper?\n\n" "question"
if [[ "$?" == "0" ]]; then
# copy desktop file and icon to ~/.local
mkdir -p "$HOME"/.local/share/applications
mkdir -p "$HOME"/.local/share/icons/hicolor/256x256/apps
rm -rf "$HOME"/.local/share/applications/"$version_lower".desktop
rm -rf "$HOME"/.local/share/icons/hicolor/256x256/apps/"$version_lower".png
cp "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/share/"$version_lower"/"$version_lower".desktop \
"$HOME"/.local/share/applications/"$version_lower".desktop || \
discord_error "Error copying '$version_lower.desktop' to '$HOME/.local/share/applications/$version_lower.desktop'" "1"
cp "$HOME"/.cache/"$version_lower"-appimage/AppDir/usr/share/"$version_lower"/discord.png \
"$HOME"/.local/share/icons/hicolor/256x256/apps/"$version_lower".png || \
discord_error "Error copying 'discord.png' to '$HOME/.local/share/icons/hicolor/256x256/apps/$version_lower.png'" "1"
# fix Exec and Icon lines in .desktop file
sed -i "s%^Exec=.*%Exec=$save_dir/$version_lower%g" \
"$HOME"/.local/share/applications/"$version_lower".desktop
sed -i "s%^Icon=.*%Icon=$HOME/.local/share/icons/hicolor/256x256/apps/$version_lower.png%g" \
"$HOME"/.local/share/applications/"$version_lower".desktop
discord_msg "$version_upper desktop file and icon have been copied to '$HOME/.local/share'.\nYou can run '$save_dir/$version_lower uninstall' if you would like to remove them later.\n$version_upper will now start. This AppImage is no longer required and can be removed." "message"
else
discord_msg "$version_upper will now start. This AppImage is no longer required and can be removed." "message"
fi
else
discord_msg "Finished building AppImage for $version_upper version '$latest_ver'." "message"
fi
rm -rf "$HOME"/.cache/"$version_lower"-appimage
}
# function to check for update and apply update if available
discord_update() {
# get latest version by checking header on download url
latest_headers="$(curl -skIX HEAD "$version_url")"
latest_ver="$(echo "$latest_headers" | grep -im1 '^location:' | cut -f6 -d'/')"
if [[ -z "$latest_ver" ]]; then
discord_error "Error getting latest $version_upper version information" "1"
fi
# skip version check if $discord_build_full set to true and just build AppImage
if [[ "$discord_build_full" != "true" ]]; then
# get current version from ../share/"$version_lower"/resources/build_info.json
current_ver="$(grep '"version":' "$running_dir"/../share/"$version_lower"/resources/build_info.json | cut -f4 -d'"')"
if [[ -z "$current_ver" ]]; then
discord_error "Error getting current $version_upper version" "1"
fi
echo "Current version: $current_ver"
echo "Latest version: $latest_ver"
# check if versions match and return if they do
if [[ "$current_ver" == "$latest_ver" ]]; then
# up to date, run Discord
echo "$version_upper is up to date."
# run with --disable-gpu-sandbox to work around bug with Electron and glibc 2.34
"$running_dir"/"$version_lower" "$@"
# while loop that sleeps so that internal update process works
while true; do
sleep 30
# break if Discord is not running
if ! pgrep -f "$usr_dir/share/$version_lower/Discord" > /dev/null; then
break
fi
done
exit 0
fi
# versions did not match, so build new AppImage
discord_msg "New $version_upper version '$latest_ver' is available.\nUpdate now?" "question"
if [[ "$?" != "0" ]]; then
discord_error "$version_upper was not updated" "0"
fi
# set $discord_build_full to true so Discord deb will be downloaded
export discord_build_full="true"
else
discord_msg "Would you like to build $version_upper AppImage for version '$latest_ver'?" "question"
if [[ "$?" != "0" ]]; then
discord_error "$version_upper AppImage was not built." "0"
fi
fi
# detect previous save_dir from .desktop file
if [[ -f "$HOME/.local/share/applications/$version_lower.desktop" ]]; then
desktop_exec_path="$(grep -m1 '^Exec=' "$HOME"/.local/share/applications/"$version_lower".desktop | cut -f2 -d'=' | sed 's%\s-.*%%g')"
# if Exec value starts with '/' and basename is version_lower, use readelf to check if is AppImage
if [[ "$(echo "$desktop_exec_path" | cut -c1)" == "/" && "$(basename "$desktop_exec_path")" == "$version_lower" ]]; then
# use readelf to check comment for AppImage and ask to use that path as save_dir
if readelf -Wp .comment "$desktop_exec_path" | grep -q 'AppImage'; then
discord_msg "Existing $version_upper AppImage detected.\nWould you like to save $version_upper AppImage version $latest_ver to '$desktop_exec_path'?\nThis will overwrite the existing $version_upper AppImage." "question"
if [[ "$?" == "0" ]]; then
export save_dir="$(dirname "$desktop_exec_path")"
desktop_exec="$(grep -m1 '^Exec=' "$HOME"/.local/share/applications/"$version_lower".desktop | cut -f2- -d'=')"
fi
fi
fi
fi
# build AppImage
discord_buildappimage
# run new AppImage, fork it to background, and exit
cd "$HOME"
if [[ -n "$desktop_exec" ]]; then
$desktop_exec "$@" & disown
else
"$save_dir"/"$version_lower" "$@" & disown
fi
exit 0
}
# get dir script is running from
export running_dir="$(dirname "$(readlink -f "$0")")"
export usr_dir="$(dirname "$running_dir")"
export discord_build_full="false"
# get Discord version by checking for directories or input when building from distributable AppImage
# Discord Stable
if [[ -d "$running_dir/../share/discord" ]]; then
export version_lower="discord"
export version_upper="Discord"
export version_url="https://discord.com/api/download?format=deb&platform=linux"
# Discord Insiders
elif [[ -d "$running_dir/../share/discord-ptb" ]]; then
export version_lower="discord-ptb"
export version_upper="Discord PTB"
export version_url="https://discord.com/api/download/ptb?format=deb&platform=linux"
elif [[ -d "$running_dir/../share/discord-canary" ]]; then
export version_lower="discord-canary"
export version_upper="Discord Canary"
export version_url="https://discord.com/api/download/canary?format=deb&platform=linux"
else
if [[ "$1" != "build-distrib" ]]; then
export discord_build_full="true"
# full AppImage has not been built, detect which version to build
build_version="$(cat "$running_dir"/.build_version)"
case "$build_version" in
discord) # Discord Stable
export version_lower="discord"
export version_upper="Discord"
export version_url="https://discord.com/api/download?format=deb&platform=linux"
;;
discord-ptb) # Discord PTB
export version_lower="discord-ptb"
export version_upper="Discord PTB"
export version_url="https://discord.com/api/download/ptb?format=deb&platform=linux"
;;
discord-canary) # Discord Insiders
export version_lower="discord-canary"
export version_upper="Discord Canary"
export version_url="https://discord.com/api/download/canary?format=deb&platform=linux"
;;
*) exit 0;;
esac
fi
fi
# check arguments
case "$1" in
build-distrib) # build AppImage for distribution that doesn't actually contain Discord
export latest_ver="Distributable AppImage"
case "$2" in
*ptb) # Discord PTB
export version_lower="discord-ptb"
export version_upper="Discord PTB"
export version_url="https://discord.com/api/download/ptb?format=deb&platform=linux"
;;
*canary) # Discord Canary
export version_lower="discord-canary"
export version_upper="Discord Canary"
export version_url="https://discord.com/api/download/canary?format=deb&platform=linux"
;;
*) # Discord Stable
export version_lower="discord"
export version_upper="Discord"
export version_url="https://discord.com/api/download?format=deb&platform=linux"
;;
esac
if [[ -z "$3" ]]; then
export save_dir="$PWD"
else
if [[ ! -d "$3" ]]; then
discord_error "'$3' is not a directory" "1"
fi
export save_dir="$3"
fi
discord_buildappimage
;;
uninstall) # remove desktop file and icon from ~/.local
rm -rf "$HOME"/.local/share/applications/"$version_lower".desktop
rm -rf "$HOME"/.local/share/icons/hicolor/256x256/apps/"$version_lower".png
discord_msg "$version_upper desktop file and icon have been removed from '$HOME/.local/share'" "message"
;;
*) discord_update "$@";; # check for update and run Discord
esac