-
Notifications
You must be signed in to change notification settings - Fork 10
/
gui
executable file
·501 lines (448 loc) · 18.6 KB
/
gui
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
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
#!/bin/bash
DIRECTORY="$(readlink -f "$(dirname "$0")")"
function error {
echo -e "\e[91m$1\e[39m"
exit 1
}
apt_lock_wait() { #Wait until other apt processes are finished before proceeding
echo -n "Waiting until APT locks are released... "
while sudo fuser /var/lib/dpkg/lock &>/dev/null ; do
sleep 0.5
done
while sudo fuser /var/lib/dpkg/lock-frontend &>/dev/null ; do
sleep 0.5
done
while sudo fuser /var/lib/apt/lists/lock &>/dev/null ; do
sleep 0.5
done
if [ -f /var/log/unattended-upgrades/unattended-upgrades.log ]; then
while sudo fuser /var/log/unattended-upgrades/unattended-upgrades.log &>/dev/null ; do
sleep 0.5
done
fi
echo "Done"
}
check() {
#python
if ! command -v python3 &>/dev/null;then
echo "Installing python3..."
apt_lock_wait
sudo apt install -y python3 || error "Failed to install python3!"
fi
if ! command -v pip3 &>/dev/null;then
echo "Installing pip3..."
apt_lock_wait
sudo apt install -y python3-pip || error "Failed to install python3-pip!"
fi
#youtube-dl
if ! command -v youtube-dl >/dev/null || [ "$(date +%s -d "$(youtube-dl --version | tr '.' '/')")" -lt "$(date +%s -d "2023/03/04")" ];then
echo "Installing youtube-dl..."
if dpkg -l youtube-dl &>/dev/null ;then
sudo apt purge -y youtube-dl
fi
sudo rm -f /usr/bin/youtube-dl #in case youtube-dl is installed to /usr/bin, delete it so pip3 succeeds to uninstall youtube-dl below
sudo pip3 uninstall -y youtube_dl
command -v pip >/dev/null && sudo pip uninstall -y youtube_dl
#overwrite youtube-dl with yt-dlp because it is better maintained
#don't uninstall youtube_dl since other apps may depend on it
sudo pip3 install --upgrade yt-dlp
if [ -z "$(yt-dlp 2>&1)" ];then
error "yt-dlp should be installed now by pip3, but yt-dlp command not found!"
fi
sudo rm -f /usr/local/bin/youtube-dl
sudo ln -s /usr/local/bin/yt-dlp /usr/local/bin/youtube-dl
else
#yt-dlp is newer than 2023/03/04, but still update it on every youtubuddy launch
sudo pip3 install --upgrade yt-dlp &
fi
#vlc
if ! command -v vlc &>/dev/null;then
echo "Installing vlc..."
apt_lock_wait
sudo apt install -y vlc || error "Failed to install vlc!"
fi
#VLC youtube.lua
if [ ! -f ~/.local/share/vlc/lua/playlist/youtube.lua ] || [ "$(sha256sum ~/.local/share/vlc/lua/playlist/youtube.lua | awk '{print $1}')" != "$(wget -qO- https://raw.githubusercontent.com/videolan/vlc/master/share/lua/playlist/youtube.lua | sha256sum | awk '{print $1}')" ];then
echo "Updating VLC youtube.lua..."
mkdir -p ~/.local/share/vlc/lua/playlist
command wget -O ~/.local/share/vlc/lua/playlist/youtube.lua 'https://raw.githubusercontent.com/videolan/vlc/master/share/lua/playlist/youtube.lua'
if [ ! -f ~/.local/share/vlc/lua/playlist/youtube.lua ];then
error "VLC youtube.lua failed to be updated!"
fi
fi
#YAD
if ! command -v yad &>/dev/null;then
echo "Installing YAD..."
apt_lock_wait
sudo apt install -y yad || error "Failed to install yad!"
fi
#jq
if ! command -v jq &>/dev/null;then
echo "Installing jq..."
apt_lock_wait
sudo apt install -y jq || error "Failed to install jq!"
fi
#mogrify
if ! command -v mogrify &>/dev/null;then
echo "Installing imagemagick..."
apt_lock_wait
sudo apt install -y imagemagick || error "Failed to install imagemagick!"
fi
sudo rm -f /usr/share/applications/display-im6.q16.desktop &>/dev/null
mkdir -p "${DIRECTORY}/thumbnails" "${DIRECTORY}/data"
#if username is different (not /home/pi), but dl-location contains /home/pi, delete the file to regenerate it in the subsequent 'if' statement
if [ -f "${DIRECTORY}/data/options/dl-location" ] && [ "$HOME" != '/home/pi' ] && cat "${DIRECTORY}/data/options/dl-location" | grep -q '/home/pi';then
rm -f "${DIRECTORY}/data/options/dl-location"
fi
#regenerate dl-location to use the current home directory
if [ ! -f "${DIRECTORY}/data/options/dl-location" ];then
echo "$HOME/Downloads" > "${DIRECTORY}/data/options/dl-location"
fi
mkdir -p ~/.local/share/applications
echo "[Desktop Entry]
Version=1.0
Name=YouTubuddy
GenericName=YouTube Browser
Comment=Search/Watch/Download YouTube videos without a browser
Exec=$0
Terminal=false
Type=Application
Icon=${DIRECTORY}/icons/logo.png
Categories=Network;WebBrowser;
StartupNotify=true" > ~/.local/share/applications/youtubuddy.desktop
}
if [ "$1" == 'install' ];then
check
exit 0
elif [ ! -e "${DIRECTORY}/data" ] || [ ! -e ~/.local/share/applications/youtubuddy.desktop ];then
check
else
check &
fi
#check for updates and auto-update if the no-update files does not exist
if [ ! -f "${DIRECTORY}/no-update" ];then
cd "$DIRECTORY"
localhash="$(git rev-parse HEAD)"
latesthash="$(git ls-remote https://github.com/Botspot/youtubuddy HEAD | awk '{print $1}')"
cd $HOME
if [ "$localhash" != "$latesthash" ] && [ ! -z "$latesthash" ] && [ ! -z "$localhash" ];then
echo "YouTubuddy is out of date. Downloading new version..."
rm -rf "$DIRECTORY.old" &>/dev/null
mv -f "$DIRECTORY" "$DIRECTORY.old"
git clone "https://github.com/Botspot/youtubuddy" "$DIRECTORY"
cp -af "$DIRECTORY.old/data"/. "$DIRECTORY/data"
rm -rf "$DIRECTORY.old"
bash -c "$0" &
exit 0
fi
fi
format_watch_list() {
if [ ! -f "${DIRECTORY}/data/watchlist" ];then
echo '' > "${DIRECTORY}/data/watchlist"
fi
echo "$(cat "${DIRECTORY}/data/watchlist" | tr -d ' ' | grep . | sort | uniq)" > "${DIRECTORY}/data/watchlist"
}
format_watch_list
#remove old thumbnails
find "${DIRECTORY}/thumbnails"/* -mtime +1 -exec rm {} \; &>/dev/null &
#you can run this script with a search argument to search for.
search="$1"
#main while loop. If search results window is closed, this takes you back to the start.
while true;do
#searching while loop. It stays here until a search is made.
while [ -z "$(echo "$search" | tr -d ' ')" ];do
if [ ! -z "$(cat "${DIRECTORY}/data/watchlist")" ];then
watchlist="--button=Watchlist!${DIRECTORY}/icons/watchlist.png:4"
fi
search="$(yad --image="${DIRECTORY}/icons/logo-long.png" --form --image-on-top \
--title="YouTubuddy: Search" --window-icon="${DIRECTORY}/icons/logo.png" \
--separator='\n' \
--center --height=150 --width=400 \
--field='Search YouTube:' "$(cat "${DIRECTORY}/data/lastsearch" 2>/dev/null)" \
"$add" \
"$watchlist" \
--button=Options!"${DIRECTORY}/icons/tool.png":2 \
--button=!"${DIRECTORY}/icons/search.png":0)"
button=$?
watchlist=no
if [ $button == 0 ];then
#search
if [ -z "$search" ];then
echo "empty search"
search=''
add="--field=Really? Come on. You have to search for something. ;):LBL"
fi
elif [ $button == 4 ];then
#watchlist
search="$(cat "${DIRECTORY}/data/watchlist")"
watchlist=yes
elif [ $button == 2 ];then
search=''
#options
options="${DIRECTORY}/data/options/thumbnail-size
${DIRECTORY}/data/options/multi-select
${DIRECTORY}/data/options/num-results
${DIRECTORY}/data/options/maximized
${DIRECTORY}/data/options/sort-by
${DIRECTORY}/data/options/dl-location
${DIRECTORY}/data/options/ytdl-args
${DIRECTORY}/data/options/vlc-cmd
${DIRECTORY}/data/options/vlc-args"
output="$(yad --image="${DIRECTORY}/icons/logo-short.png" --form --image-on-top \
--title="YouTubuddy: Options" --window-icon="${DIRECTORY}/icons/logo.png" \
--separator='\n' --text="Options" \
--center --height=150 --width=400 \
--field='Thumbnail size:':NUM "$(cat "$(echo "$options" | sed -n 1p)")"!0..5 \
--field='Allow multiple videos to be selected':CHK "$(cat "$(echo "$options" | sed -n 2p)")" \
--field='# of results:':NUM "$(cat "$(echo "$options" | sed -n 3p)")"!10..1000!10 \
--field='Display search results in maximized window':CHK "$(cat "$(echo "$options" | sed -n 4p)")" \
--field='Search by:':CB "$(cat "$(echo "$options" | sed -n 5p)")!$(echo -e "Date\nRelevence" | grep -v $(cat "$(echo "$options" | sed -n 5p)"))" \
--field='Videos saved to:':DIR "$(cat "$(echo "$options" | sed -n 6p)")" \
--field='Youtube-dl args:' "$(cat "$(echo "$options" | sed -n 7p)")" \
--field='VLC command:' "$(cat "$(echo "$options" | sed -n 8p)")" \
--field='VLC args:' "$(cat "$(echo "$options" | sed -n 9p)")" \
--button=Done!"${DIRECTORY}/icons/check.png":0)"
button=$?
if [ $button == 0 ];then
#save settings if check-mark clicked
#remove zero-width spaces from output
output="$(echo "$output" | sed 's///g')"
echo "output: ${output}EOO"
#remove all thumbnails if thumbnail size changed
if [ "$(cat "$(echo "$options" | sed -n 1p)")" != "$(echo "$output" | sed -n 1p)" ];then
echo "Thumbnail size changed. Deleting all thumbnails..."
rm -rf "${DIRECTORY}/thumbnails"/*
fi
#save changes
for i in $(seq $(echo "$options" | wc -l)) ;do
echo "$output" | sed -n ${i}p > "$(echo "$options" | sed -n ${i}p)"
echo "Setting $(echo "$options" | sed -n ${i}p) to $(echo "$output" | sed -n ${i}p)"
done
fi
#end of settings code
else
error "user exited search window"
fi
done
#end of searching while loop
if [ "$watchlist" == 'no' ];then
echo "$search" > "${DIRECTORY}/data/lastsearch"
fi
rm -f "${DIRECTORY}/data/search.json" "${DIRECTORY}/data/lastjson"
if [ "$watchlist" == 'yes' ];then
#watchlist mode
loadtext="Loading your Watchlist..."
windowtitle="YouTubuddy: Watchlist"
#this searches for videos as a background process
PREIFS="$IFS"
IFS=$'\n'
for line in $search ;do
youtube-dl -s --print-json "$line" >> "${DIRECTORY}/data/search.json"
done &
ytdlpid=$!
IFS="$PREIFS"
elif [[ "$search" == *'youtube.com/watch?v='* ]] || [[ "$search" == *youtu.be/* ]];then
#url single-video mode
loadtext="Finding your YouTube URL..."
windowtitle="YouTubuddy: YouTube URL"
#this searches for videos as a background process
youtube-dl -s --print-json "$search" >> "${DIRECTORY}/data/search.json" &
ytdlpid=$!
elif [[ "$search" == *'youtube.com/playlist?list='* ]];then
#playlist-url mode
loadtext="Finding your playlist..."
windowtitle="YouTubuddy: Playlist"
#this searches for videos as a background process
youtube-dl -s --print-json "$search" >> "${DIRECTORY}/data/search.json" &
ytdlpid=$!
elif [[ "$search" == 'http'*'://'* ]];then
#playlist-url mode
loadtext="Finding your URL..."
windowtitle="YouTubuddy: Video URL"
#this searches for videos as a background process
youtube-dl -s --print-json "$search" >> "${DIRECTORY}/data/search.json" &
ytdlpid=$!
else
#search mode
numresults=$(cat "${DIRECTORY}/data/options/num-results")
loadtext="Searching for videos..."
windowtitle="YouTubuddy: Results for "\""$search"\"""
#determine search algorithm
if [ "$(cat ${DIRECTORY}/data/options/sort-by)" == 'Relevence' ];then
searchtype='ytsearch'
elif [ "$(cat ${DIRECTORY}/data/options/sort-by)" == 'Date' ];then
searchtype='ytsearchdate'
else
searchtype='ytsearch'
fi
#this searches for videos as a background process
echo 'search mode'
youtube-dl -s --print-json "${searchtype}${numresults}:${search}" >> "${DIRECTORY}/data/search.json" &
ytdlpid=$!
echo "youtube-dl -s --print-json ${searchtype}${numresults}:${search} >> ${DIRECTORY}/data/search.json &"
fi
#kill youtube-dl background process on exit
trap "kill $ytdlpid" EXIT
#display loading dialog
(echo "# "
sleep 20
echo "# This should not be taking so long."
if ! ps -p $ytdlpid >/dev/null ;then
echo "# youtube-dl is not running!"
else
echo "# youtube-dl is running."
fi
sleep infinity) | yad --progress --pulsate --title="YouTubuddy: Searching" \
--image="${DIRECTORY}/icons/logo-short.png" --image-on-top \
--text="$loadtext" --window-icon="${DIRECTORY}/icons/logo.png" \
--width=400 --height=150 --center --auto-close --auto-kill \
--no-buttons 2>/dev/null &
loader=$!
#waits until the first result is inserted in the file
while [ -z "$(cat "${DIRECTORY}/data/search.json")" ];do
sleep 1
if ! ps -p $ytdlpid >/dev/null ;then
echo "youtube-dl is not running!"
else
echo "youtube-dl is running."
fi
done
kill $loader
#determine the thumbnail size
thumbsize="$(cat ${DIRECTORY}/data/options/thumbnail-size)"
if [ -z "$thumbsize" ];then
thumbsize=3
elif [ "$thumbsize" == 0 ];then
thumbsize=''
else
thumbsize=$((thumbsize-1))
fi
#determine if multi-select is enabled
multiselect="$(cat "${DIRECTORY}/data/options/multi-select")"
#search results while loop. Returns you to the search results after you click a play/download button
while true;do
i=0
output="$(
while true;do
i=$((i+1))
if ps -p $ytdlpid >/dev/null || [ $i -le "$(cat "${DIRECTORY}/data/search.json" | grep . | wc -l | awk '{print $1}')" ]; then
result=''
while [ -z "$result" ];do
result="$(cat "${DIRECTORY}/data/search.json" 2>/dev/null | sed -n "${i}p")"
done
#echo "$result" 1>&2
result="$(echo "$result" | grep -E '"url":|height|upload_date|"webpage_url":|fulltitle|fps|"ext":|duration|like_count' )"
id="$(echo "$result" | jq '.id' | head -n1 | tr -d '"')"
title="$(echo "$result" | jq '.fulltitle' | head -n1 | tr -d '"' | sed 's/&/&/g')"
date="$(echo "$result" | jq '.upload_date' | head -n1 | tr -d '"' | date -d $(cat /dev/stdin) +%Y/%m/%d)"
#get the link to the thumbnail image for the video. Image size is determined by the [3] string. From 0 (smallest) to 4 (largest)
if [ ! -z $thumbsize ];then
imageurl="$(echo "$result" | jq '.thumbnails' | jq ".[$thumbsize].url" | tr -d '"')"
if [ ! -f "${DIRECTORY}/thumbnails/${id}.png" ];then
image="${DIRECTORY}/thumbnails/${id}.webm"
wget "$imageurl" -qO "$image"
mogrify -format png "$image"
rm "$image"
fi
image="${DIRECTORY}/thumbnails/${id}.png"
image="$(echo "$image" | sed 's/&/&/g')"
fi
url="$(echo "$result" | jq '.webpage_url' | tr -d '"')"
urlnice="$(echo "youtu.be/${id}" | sed 's/&/&/g')"
#highest video quality available. For example: "1080p60"
quality="$(echo "$result" | jq '.height' | head -n1)p$(echo "$result" | jq '.fps' | head -n1 | tr -d '"')"
likes="$(echo "$result" | jq '.like_count' | sed -n '1p')"
dislikes="$(echo "$result" | jq '.dislike_count' | sed -n '1p')"
channel="$(echo "$result" | jq '.uploader' | sed -n '1p' | tr -d '"' | sed 's/&/&/g')"
echo -e "FALSE
$url
$urlnice - $channel on $date
$image
$title"
sleep 0.1
else
#if all results are in, stop the file-checking loop.
echo "FALSE
${DIRECTORY}/icons/blank.png
End of results."
exit 0
fi
done | yad --list $([ "$multiselect" == TRUE ] && echo '--checklist') --text="Select some videos!" \
--image="${DIRECTORY}/icons/logo-long.png" --image-on-top --no-headers --no-click \
--title="$windowtitle" --window-icon="${DIRECTORY}/icons/logo.png" \
$([ $(cat ${DIRECTORY}/data/options/maximized) == "FALSE" ] && echo '--center --height=300' || echo '--maximized') \
$([ "$multiselect" == TRUE ] && echo '--column=:CHK' || echo '--column=:HD') \
--column=url:HD --column=tooltip:HD \
$([ ! -z "$thumbsize" ] && echo '--column=:IMG' || echo '--column=:HD') \
--column=title --print-column=2 --tooltip-column=3 --separator=' ' \
"$([ "$watchlist" == 'yes' ] && echo "--button=Remove!${DIRECTORY}/icons/rmwatchlist.png:8" || echo "--button=Watch later!${DIRECTORY}/icons/clock.png:6")" \
--button=URLs!"${DIRECTORY}/icons/link.png":4 \
--button=Play!"${DIRECTORY}/icons/play.png":2 \
--button=Download!"${DIRECTORY}/icons/download.png":0
)"
button=$?
#go back to the starting page if play/download is not clicked
if [ $button -gt 10 ] || [ $button == 1 ];then
search=''
kill $ytdlpid 2>/dev/null
break #exit the search results while loop
fi
#if at least 1 video selected
if [ ! -z "$output" ];then
genarray() {
playlist=()
PREIFS="$IFS"
IFS=$'\n'
for video in $output ;do
playlist+=( "$video" )
done
IFS="$PREIFS"
}
echo "Output: ${output}EOO"
if [ $button == 8 ];then
#remove from watch list
grepval="$(echo "$output" | tr -d ' ' | grep . | tr '\n' '|' | sed 's+https://www.youtube.com/watch?v=++g' | sed 's/.$//')"
echo "grepval: ${grepval}EOG"
echo "$(cat "$DIRECTORY/data/watchlist" | grep -vE "$grepval")" > "$DIRECTORY/data/watchlist"
echo "$(cat "$DIRECTORY/data/search.json" | grep -vE "$grepval")" > "$DIRECTORY/data/search.json"
format_watch_list
if [ -z "$(cat "$DIRECTORY/data/watchlist" )" ];then
search=''
kill $ytdlpid 2>/dev/null
break
#back to search window if no videos remaining in watch list
fi
elif [ $button == 6 ];then
#watch later
echo "$output" >> "$DIRECTORY/data/watchlist"
format_watch_list
elif [ $button == 4 ];then
#URLs
echo "$output" | grep . | yad --text-info \
--center --width=500 --height=250 --title='URLs to copy' \
--window-icon="${DIRECTORY}/icons/logo.png" \
--button=Close:0
elif [ $button == 2 ];then
#play
genarray
$(cat "${DIRECTORY}/data/options/vlc-cmd") ${playlist[*]} $(cat "${DIRECTORY}/data/options/vlc-args")
elif [ $button == 0 ];then
#download
genarray
numvideos=$(echo "$output" | tr ' ' '\n' | grep . | wc -l)
if [ $numvideos == 1 ];then
plural='video'
else
plural='videos'
fi
"${DIRECTORY}/terminal-run" "trap 'echo "\""closing in 10 seconds..."\"" ; sleep 10' EXIT
cd $(cat "${DIRECTORY}/data/options/dl-location")
youtube-dl ${playlist[*]} $(cat "${DIRECTORY}/data/options/ytdl-args")" "Downloading $numvideos $plural to $(cat "${DIRECTORY}/data/options/dl-location")..." &
fi
else
echo "Warning: no videos selected!"
fi
done
#end of search results while loop
done
#end of main while loop