ani-cli-npm 1.0.7 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/discord.xml +7 -0
- package/bin/index.js +24 -26
- package/bin/m3u8.html +25 -0
- package/gravity/5 +1 -0
- package/gravity/67 +466 -0
- package/gravity/ani-cli.sh +686 -0
- package/gravity/fuck.txt +116 -0
- package/gravity/temp.sh +676 -0
- package/gravity/testdisk.log +54 -0
- package/gravity/testuwu/.matter +24 -0
- package/gravity/testuwu/blackhole.cpp +73 -0
- package/gravity/testuwu/nul: +1 -0
- package/gravity/testuwu/output1_10.txt +224 -0
- package/gravity/testuwu/output1_11.txt +224 -0
- package/gravity/testuwu/run +0 -0
- package/gravity/trez +466 -0
- package/package.json +1 -1
@@ -0,0 +1,686 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# License preamble at the end of the file
|
4
|
+
# Version number
|
5
|
+
VERSION="3.4.1"
|
6
|
+
|
7
|
+
|
8
|
+
#######################
|
9
|
+
# AUXILIARY FUNCTIONS #
|
10
|
+
#######################
|
11
|
+
|
12
|
+
help_text () {
|
13
|
+
while read -r line; do
|
14
|
+
printf "%s\n" "$line"
|
15
|
+
done <<-EOF
|
16
|
+
Usage:
|
17
|
+
${0##*/} [-f] [-s] [-v] [-x] [-q <quality>] [-a <episode>] [-d | -p <download_dir>] [<query>] [-r <provider_no.>]
|
18
|
+
${0##*/} [-f] [-s] [-v] [-x] [-q <quality>] -c
|
19
|
+
${0##*/} -h | -D | -U | -V
|
20
|
+
Options:
|
21
|
+
-v use VLC as the media player
|
22
|
+
-q set video quality (best|worst|360|480|720|1080)
|
23
|
+
-s watch anime together with friends, using Syncplay (works with mpv only)
|
24
|
+
-f use fzf for anime selection
|
25
|
+
-a specify episode to watch
|
26
|
+
-d download episode
|
27
|
+
-p download episode to specified directory
|
28
|
+
-c continue watching anime from history
|
29
|
+
-h show helptext
|
30
|
+
-D delete history
|
31
|
+
-U fetch update from github
|
32
|
+
-V print version number and exit
|
33
|
+
-r select provider to scrape first [1-3]
|
34
|
+
-x print all video links from all providers to stdout (for debugging purpose)
|
35
|
+
Episode selection:
|
36
|
+
Multiple episodes can be chosen given a range
|
37
|
+
Choose episode [1-13]: 1 6
|
38
|
+
This would choose episodes 1 2 3 4 5 6
|
39
|
+
To select the last episode use -1
|
40
|
+
When selecting non-interactively, the first result will be
|
41
|
+
selected, if anime is passed
|
42
|
+
EOF
|
43
|
+
}
|
44
|
+
|
45
|
+
retry () {
|
46
|
+
err "$*"
|
47
|
+
prompt
|
48
|
+
}
|
49
|
+
|
50
|
+
# display an error message to stderr (in red)
|
51
|
+
err () {
|
52
|
+
printf "\33[2K\r\033[1;31m%s\033[0m\n" "$*" >&2
|
53
|
+
}
|
54
|
+
|
55
|
+
#display error message and exit
|
56
|
+
die () {
|
57
|
+
err "$*"
|
58
|
+
exit 1
|
59
|
+
}
|
60
|
+
|
61
|
+
# display an informational message (first argument in green, second in magenta)
|
62
|
+
inf () {
|
63
|
+
printf "\33[2K\r\033[1;35m%s \033[1;35m%s\033[0m\n" "$1" "$2"
|
64
|
+
}
|
65
|
+
|
66
|
+
progress() {
|
67
|
+
printf "\33[2K\r\033[1;34m%s\033[0m" "$1"
|
68
|
+
}
|
69
|
+
|
70
|
+
debug () {
|
71
|
+
printf "\n\033[1;32mReferrer :\033[0m %s\n\033[1;32mlinks >>\n\033[0m%s\n" "$1" "$2"
|
72
|
+
}
|
73
|
+
|
74
|
+
# prompts the user with message in $1-2 ($1 in blue, $2 in magenta) and saves the input to the variables in $REPLY and $REPLY2
|
75
|
+
prompt () {
|
76
|
+
[ -n "$*" ] && printf "\33[2K\r\033[1;35m%s\n" "$*"
|
77
|
+
printf "\033[1;35m> \033[0m"
|
78
|
+
read -r REPLY REPLY2
|
79
|
+
}
|
80
|
+
|
81
|
+
selection_menu() {
|
82
|
+
menu_line_parity=0
|
83
|
+
while read -r option line; do
|
84
|
+
if [ "$option" = "q" ]; then
|
85
|
+
printf "\033[1;31m(\033[1;31m%s\033[1;31m) \033[1;31m%s\033[0m\n" "$option" "$line"
|
86
|
+
else
|
87
|
+
if [ "$menu_line_parity" -eq 0 ]; then
|
88
|
+
printf "\033[1;33m(\033[1;33m%s\033[1;33m) \033[1;33m%s\033[0m\n" "$option" "$line"
|
89
|
+
menu_line_parity=1
|
90
|
+
else
|
91
|
+
printf "\033[1;36m(\033[1;36m%s\033[1;36m) \033[1;36m%s\033[0m\n" "$option" "$line"
|
92
|
+
menu_line_parity=0
|
93
|
+
fi
|
94
|
+
fi
|
95
|
+
done <<-EOF
|
96
|
+
$*
|
97
|
+
EOF
|
98
|
+
prompt
|
99
|
+
}
|
100
|
+
|
101
|
+
selection_menu_fzf() {
|
102
|
+
printf "%s\n%s" "$1" "$2" | fzf --height=30% --border -1 --layout=reverse --header-first --header-lines=1 --cycle --with-nth 2.. | cut -f1 -d' '
|
103
|
+
}
|
104
|
+
|
105
|
+
version_text () {
|
106
|
+
inf "Version: $VERSION"
|
107
|
+
}
|
108
|
+
|
109
|
+
# get the newest version of this script from github and replace it
|
110
|
+
update_script () {
|
111
|
+
update="$(curl -A "$agent" -s "https://raw.githubusercontent.com/pystardust/ani-cli/master/ani-cli")" || die "Connection error"
|
112
|
+
update="$(printf '%s\n' "$update" | diff -u "$0" -)"
|
113
|
+
if [ -z "$update" ]; then
|
114
|
+
inf "Script is up to date :)"
|
115
|
+
else
|
116
|
+
if printf '%s\n' "$update" | patch "$0" - ; then
|
117
|
+
inf "Script has been updated"
|
118
|
+
else
|
119
|
+
die "Can't update for some reason!"
|
120
|
+
fi
|
121
|
+
fi
|
122
|
+
exit 0
|
123
|
+
}
|
124
|
+
|
125
|
+
# checks if dependencies are present
|
126
|
+
dep_ch () {
|
127
|
+
for dep; do
|
128
|
+
if ! command -v "$dep" >/dev/null ; then
|
129
|
+
die "Program \"$dep\" not found. Please install it."
|
130
|
+
fi
|
131
|
+
done
|
132
|
+
}
|
133
|
+
|
134
|
+
download () {
|
135
|
+
case $2 in
|
136
|
+
*m3u8*)
|
137
|
+
ffmpeg -loglevel error -stats -referer "$1" -i "$2" -c copy "$download_dir/$3.mp4" ;;
|
138
|
+
*)
|
139
|
+
axel -a -k -n 10 --header=Referer:"$1" "$2" -o "$download_dir/$3.mp4" ;;
|
140
|
+
esac
|
141
|
+
}
|
142
|
+
|
143
|
+
#############
|
144
|
+
# SEARCHING #
|
145
|
+
#############
|
146
|
+
|
147
|
+
# gets anime names along with its id for search term
|
148
|
+
search_anime () {
|
149
|
+
search=$(printf '%s' "$1" | tr ' ' '-' )
|
150
|
+
curl -s "https://gogoanime.lu//search.html?keyword=$search" -L |
|
151
|
+
sed -nE 's_^[[:space:]]*<a href="/category/([^"]*)" title.*">$_\1_p'
|
152
|
+
}
|
153
|
+
|
154
|
+
#fetches all the episodes embed links in an anime from gogoanime server
|
155
|
+
episode_list () {
|
156
|
+
select_ep_result=$(curl -A "$agent" -s "$base_url/v1/$1" | sed -nE "s_.*epslistplace.*>(.*)</div>_\1_p" | tr "," "\n" | sed -e '/extra/d' -e '/PV/d' | sed -nE 's_".*":"(.*)".*_\1_p')
|
157
|
+
first_ep_number=1
|
158
|
+
[ -z "$select_ep_result" ] && last_ep_number=0 || last_ep_number=$(printf "%s\n" "$select_ep_result" | wc -l)
|
159
|
+
}
|
160
|
+
|
161
|
+
process_hist_entry () {
|
162
|
+
temp_anime_id=$(printf "%s" "$anime_id" | sed 's/\t[0-9]*.$//')
|
163
|
+
current_ep=$(printf "%s" "$anime_id" | sed "s/$temp_anime_id\t//g")
|
164
|
+
episode_list "$temp_anime_id"
|
165
|
+
latest_ep=$last_ep_number
|
166
|
+
if [ -n "$latest_ep" ] && [ "$latest_ep" -ge "$current_ep" ]; then
|
167
|
+
printf "%s : %s / %s\n" "$temp_anime_id" "$current_ep" "$latest_ep"
|
168
|
+
fi
|
169
|
+
}
|
170
|
+
|
171
|
+
# compares history with gogoplay, only shows unfinished anime
|
172
|
+
search_history () {
|
173
|
+
[ ! -s "$logfile" ] && die "History is empty"
|
174
|
+
progress "Processing $scrape.."
|
175
|
+
search_results=$(while read -r anime_id; do process_hist_entry & done < "$logfile"; wait)
|
176
|
+
[ -z "$search_results" ] && die "No unwatched episodes"
|
177
|
+
one_hist=$(printf '%s\n' "$search_results" | grep -e "$" -c)
|
178
|
+
[ "$one_hist" = 1 ] && select_first=1
|
179
|
+
anime_selection "$search_results"
|
180
|
+
ep_choice_start=$(sed -n -E "s/${selection_id}\t(.*)/\1/p" "$logfile")
|
181
|
+
}
|
182
|
+
|
183
|
+
##################
|
184
|
+
# URL PROCESSING #
|
185
|
+
##################
|
186
|
+
|
187
|
+
generate_link() {
|
188
|
+
case $1 in
|
189
|
+
1)
|
190
|
+
provider_name='Xstreamcdn'
|
191
|
+
progress "Fetching $provider_name links.."
|
192
|
+
fb_id=$(printf "%s" "$resp" | sed -n "s_.*fembed.*/v/__p")
|
193
|
+
refr="https://fembed-hd.com/v/$fb_id"
|
194
|
+
[ -z "$fb_id" ] && return 0
|
195
|
+
result_links="$(curl -A "$agent" -s -X POST "https://fembed-hd.com/api/source/$fb_id" -H "x-requested-with:XMLHttpRequest" |
|
196
|
+
sed -e 's/\\//g' -e 's/.*data"://' | tr "}" "\n" | sed -nE 's/.*file":"(.*)","label":"(.*)","type.*/\2>\1/p')"
|
197
|
+
;;
|
198
|
+
2)
|
199
|
+
provider_name='Animixplay'
|
200
|
+
progress "Fetching $provider_name Direct link.."
|
201
|
+
refr="$base_url"
|
202
|
+
[ -z "$id" ] && return 0
|
203
|
+
enc_id=$(printf "%s" "$id" | base64)
|
204
|
+
ani_id=$(printf "%sLTXs3GrU8we9O%s" "$id" "$enc_id" | base64)
|
205
|
+
|
206
|
+
echo $id
|
207
|
+
echo $enc_id
|
208
|
+
echo $ani_id
|
209
|
+
sleep 500
|
210
|
+
|
211
|
+
|
212
|
+
#MjUwNTQ=
|
213
|
+
#TWpVd05UUT0=
|
214
|
+
#TWpVd05UUT1MVFhzM0dyVTh3ZTlPVFdwVmQwNVVVVDA9
|
215
|
+
#https://animixplay.to/api/liveMjUwNTQLTXs3GrU8we9OTWpVd05UUQo=
|
216
|
+
echo "$base_url/api/live$ani_id"
|
217
|
+
result_links="$(curl -s "$base_url/api/live${ani_id}" -A "$agent" -I | sed -nE 's_location: (.*)_\1_p' | cut -d"#" -f2 | base64 -d)"
|
218
|
+
echo $result_links "LINKS"
|
219
|
+
sleep 100
|
220
|
+
;;
|
221
|
+
|
222
|
+
|
223
|
+
*)
|
224
|
+
provider_name='Gogoanime'
|
225
|
+
progress "Fetching $provider_name Direct link.."
|
226
|
+
refr="$gogohd_url"
|
227
|
+
[ -z "$id" ] && return 0
|
228
|
+
secret_key=$(printf "%s" "$resp" | sed -n '2p' | tr -d "\n" | od -A n -t x1 | tr -d " |\n")
|
229
|
+
iv=$(printf "%s" "$resp" | sed -n '3p' | tr -d "\n" | od -A n -t x1 | tr -d " |\n")
|
230
|
+
second_key=$(printf "%s" "$resp" | sed -n '4p' | tr -d "\n" | od -A n -t x1 | tr -d " |\n")
|
231
|
+
token=$(printf "%s" "$resp" | head -1 | base64 -d | openssl enc -d -aes256 -K "$secret_key" -iv "$iv" | sed -nE 's/.*&(token.*)/\1/p')
|
232
|
+
ajax=$(printf '%s' "$id" | openssl enc -e -aes256 -K "$secret_key" -iv "$iv" -a)
|
233
|
+
data=$(curl -A "$agent" -sL -H "X-Requested-With:XMLHttpRequest" "${gogohd_url}encrypt-ajax.php?id=${ajax}&alias=${id}&${token}" | sed -e 's/{"data":"//' -e 's/"}/\n/' -e 's/\\//g')
|
234
|
+
result_links="$(printf '%s' "$data" | base64 -d 2>/dev/null | openssl enc -d -aes256 -K "$second_key" -iv "$iv" 2>/dev/null |
|
235
|
+
sed -e 's/\].*/\]/' -e 's/\\//g' | grep -Eo 'https:\/\/[-a-zA-Z0-9@:%._\+~#=][a-zA-Z0-9][-a-zA-Z0-9@:%_\+.~#?&\/\/=]*')"
|
236
|
+
;;
|
237
|
+
esac
|
238
|
+
}
|
239
|
+
|
240
|
+
# chooses the link for the set quality
|
241
|
+
get_video_link() {
|
242
|
+
dpage_url="$1"
|
243
|
+
id=$(printf "%s" "$dpage_url" | sed -nE 's/.*id=([^&]*).*/\1/p')
|
244
|
+
#multiple sed are used (regex seperated by ';') for extracting only required data from response of embed url
|
245
|
+
resp="$(curl -A "$agent" -sL "${gogohd_url}streaming.php?id=$id" |
|
246
|
+
sed -nE 's/.*class="container-(.*)">/\1/p ;
|
247
|
+
s/.*class="wrapper container-(.*)">/\1/p ;
|
248
|
+
s/.*class=".*videocontent-(.*)">/\1/p ;
|
249
|
+
s/.*data-value="(.*)">.*/\1/p ;
|
250
|
+
s/.*data-status="1".*data-video="(.*)">.*/\1/p')"
|
251
|
+
provider=1
|
252
|
+
[ -n "$select_provider" ] && provider="$select_provider"
|
253
|
+
i=0
|
254
|
+
while [ "$i" -lt 3 ] && [ -z "$result_links" ];do
|
255
|
+
generate_link "$provider"
|
256
|
+
provider=$((provider % 3 + 1))
|
257
|
+
if [ "$debug" -eq 1 ]; then
|
258
|
+
debug "$refr" "$result_links"
|
259
|
+
unset result_links
|
260
|
+
fi
|
261
|
+
: $((i+=1))
|
262
|
+
done
|
263
|
+
[ "$debug" -eq 1 ] && return 0
|
264
|
+
if printf '%s' "$result_links" | grep -q "m3u8"; then
|
265
|
+
get_video_quality_m3u8 "$result_links"
|
266
|
+
else
|
267
|
+
video_url=$(get_video_quality_mp4 "$result_links")
|
268
|
+
fi
|
269
|
+
unset result_links
|
270
|
+
}
|
271
|
+
|
272
|
+
get_video_quality_mp4() {
|
273
|
+
case $quality in
|
274
|
+
best)
|
275
|
+
video_url=$(printf '%s' "$1" | tail -n 1 | cut -d">" -f2) ;;
|
276
|
+
worst)
|
277
|
+
video_url=$(printf '%s' "$1" | head -n 1 | cut -d">" -f2) ;;
|
278
|
+
*)
|
279
|
+
video_url=$(printf '%s' "$1" | grep -i "${quality}p" | head -n 1 | cut -d">" -f2)
|
280
|
+
if [ -z "$video_url" ]; then
|
281
|
+
err "Current video quality is not available (defaulting to best quality)"
|
282
|
+
video_url=$(printf '%s' "$1" | tail -n 1 | cut -d">" -f2)
|
283
|
+
fi
|
284
|
+
;;
|
285
|
+
esac
|
286
|
+
printf '%s' "$video_url"
|
287
|
+
}
|
288
|
+
|
289
|
+
get_video_quality_m3u8() {
|
290
|
+
printf '%s' "$1" | grep -qE "manifest.*m3u.*" && video_url=$1 && return 0
|
291
|
+
m3u8_links=$(curl -A "$agent" -s --referer "$dpage_link" "$1")
|
292
|
+
echo ""
|
293
|
+
echo $m3u8_links
|
294
|
+
echo ""
|
295
|
+
echo dpage: $dpage_link
|
296
|
+
echo 1: $1
|
297
|
+
echo ""
|
298
|
+
sleep 5
|
299
|
+
case $quality in
|
300
|
+
best)
|
301
|
+
res_selector=$(printf "%s" "$m3u8_links" | sed -nE 's_.*RESOLUTION=.*x([^,]*).*_\1_p' | sort -nr | head -1);;
|
302
|
+
worst)
|
303
|
+
res_selector=$(printf "%s" "$m3u8_links" | sed -nE 's_.*RESOLUTION=.*x([^,]*).*_\1_p' | sort -nr | tail -1);;
|
304
|
+
*)
|
305
|
+
res_selector=$quality
|
306
|
+
if ! (printf '%s' "$m3u8_links" | grep -q "x$quality"); then
|
307
|
+
err "Current video quality is not available (defaulting to best quality)"
|
308
|
+
res_selector=$(printf "%s" "$m3u8_links" | sed -nE 's_.*RESOLUTION=.*x([^,]*).*_\1_p' | sort -nr | head -1)
|
309
|
+
fi
|
310
|
+
;;
|
311
|
+
esac
|
312
|
+
video_url=$(printf '%s' "$m3u8_links" | sed -n "/x$res_selector/{n;p;}" | tr -d '\r')
|
313
|
+
echo $video_url
|
314
|
+
printf "%s" "$m3u8_links" | grep -q "http" || video_url="$(printf "%s" "$1" | sed 's|[^/]*$||')$video_url" || true
|
315
|
+
}
|
316
|
+
|
317
|
+
|
318
|
+
#################
|
319
|
+
# INPUT PARSING #
|
320
|
+
#################
|
321
|
+
|
322
|
+
append () {
|
323
|
+
[ -z "$1" ] || printf "%s\n" "$1"
|
324
|
+
printf "%s %s" "$3" "$2"
|
325
|
+
}
|
326
|
+
|
327
|
+
# only lets the user pass in case of a valid search
|
328
|
+
process_search () {
|
329
|
+
progress "Searching $scrape.."
|
330
|
+
search_results=$(search_anime "$query")
|
331
|
+
while [ -z "$search_results" ]; do
|
332
|
+
retry 'No search results found'
|
333
|
+
query="$REPLY $REPLY2"
|
334
|
+
progress "Searching $scrape.."
|
335
|
+
search_results=$(search_anime "$query")
|
336
|
+
done
|
337
|
+
anime_selection "$search_results"
|
338
|
+
episode_selection
|
339
|
+
}
|
340
|
+
|
341
|
+
# anime-selection menu handling function
|
342
|
+
anime_selection () {
|
343
|
+
if [ "$fzf" -eq 0 ];then
|
344
|
+
inf "$scrape Results >>"
|
345
|
+
else
|
346
|
+
progress ""
|
347
|
+
fi
|
348
|
+
count=1
|
349
|
+
unset selection_list
|
350
|
+
while read -r anime_id; do
|
351
|
+
displayed_title=$(printf '%s' "$anime_id" | tr '-' ' ')
|
352
|
+
selection_list=$(append "$selection_list" "$displayed_title" "$count")
|
353
|
+
: $((count+=1))
|
354
|
+
done <<-EOF
|
355
|
+
$search_results
|
356
|
+
EOF
|
357
|
+
if [ -n "$select_first" ]; then
|
358
|
+
tput clear
|
359
|
+
choice=1
|
360
|
+
elif [ -z "$ep_choice_to_start" ] || { [ -n "$ep_choice_to_start" ] && [ -z "$select_first" ]; }; then
|
361
|
+
selection_list=$(append "$selection_list" "quit" "q")
|
362
|
+
if [ "$fzf" -eq 1 ]; then
|
363
|
+
choice=$(selection_menu_fzf ". $scrape Results>>" "$selection_list")
|
364
|
+
[ -z "$choice" ] && exit 0
|
365
|
+
else
|
366
|
+
selection_menu "$selection_list"
|
367
|
+
choice="$REPLY"
|
368
|
+
[ -z "$choice" ] && choice=1
|
369
|
+
fi
|
370
|
+
while ! [ "$choice" -eq "$choice" ] 2>/dev/null || [ "$choice" -lt 1 ] || [ "$choice" -ge "$count" ] || [ "$choice" = " " ]; do
|
371
|
+
[ "$choice" = "q" ] && exit 0
|
372
|
+
retry "Invalid choice entered"
|
373
|
+
choice="$REPLY"
|
374
|
+
done
|
375
|
+
fi
|
376
|
+
# Select respective anime_id
|
377
|
+
selection_id="$(printf "%s" "$search_results" | sed -n "${choice}p" | cut -d':' -f1 | tr -d ' ')"
|
378
|
+
progress "Searching Episodes.."
|
379
|
+
episode_list "$selection_id"
|
380
|
+
}
|
381
|
+
|
382
|
+
# gets episode number from user, makes sure it's in range, skips input if only one episode exists
|
383
|
+
episode_selection () {
|
384
|
+
[ "$last_ep_number" -eq 0 ] && die "Episodes not released yet!"
|
385
|
+
if [ "$last_ep_number" -gt "$first_ep_number" ]; then
|
386
|
+
[ "$ep_choice_to_start" = "-1" ] && ep_choice_to_start="$last_ep_number"
|
387
|
+
if [ -z "$ep_choice_to_start" ]; then
|
388
|
+
# if branches, because order matters this time
|
389
|
+
while : ; do
|
390
|
+
last_ep_number=$(printf '%s' "$last_ep_number"|tr -d "[:space:]")
|
391
|
+
prompt "To specify a range, use: start_number end_number (Episodes: $first_ep_number-$last_ep_number)"
|
392
|
+
ep_choice_start="$REPLY"
|
393
|
+
ep_choice_end="$REPLY2"
|
394
|
+
[ "$REPLY" = q ] && exit 0
|
395
|
+
[ "$ep_choice_start" = "-1" ] && ep_choice_start="$last_ep_number" || [ -z "$ep_choice_start" ] && ep_choice_start="$last_ep_number"
|
396
|
+
[ "$ep_choice_end" = "-1" ] && ep_choice_end="$last_ep_number"
|
397
|
+
if ! [ "$ep_choice_start" -eq "$ep_choice_start" ] 2>/dev/null || { [ -n "$ep_choice_end" ] && ! [ "$ep_choice_end" -eq "$ep_choice_end" ] 2>/dev/null; }; then
|
398
|
+
err "Invalid number(s)"
|
399
|
+
continue
|
400
|
+
fi
|
401
|
+
if [ "$ep_choice_start" -gt "$last_ep_number" ] 2>/dev/null || [ "$ep_choice_end" -gt "$last_ep_number" ] 2>/dev/null || [ "$ep_choice_start" -lt "$first_ep_number" ] 2>/dev/null; then
|
402
|
+
err "Episode out of range"
|
403
|
+
continue
|
404
|
+
fi
|
405
|
+
if [ -n "$ep_choice_end" ] && [ "$ep_choice_end" -le "$ep_choice_start" ]; then
|
406
|
+
err "Invalid range"
|
407
|
+
continue
|
408
|
+
fi
|
409
|
+
break
|
410
|
+
done
|
411
|
+
else
|
412
|
+
ep_choice_start="$ep_choice_to_start" && unset ep_choice_to_start
|
413
|
+
fi
|
414
|
+
else
|
415
|
+
# In case the anime contains only a single episode
|
416
|
+
ep_choice_start=1
|
417
|
+
fi
|
418
|
+
[ -n "$ep_choice_end" ] && auto_play=1
|
419
|
+
}
|
420
|
+
|
421
|
+
# creates $episodes from $ep_choice_start and $ep_choice_end
|
422
|
+
generate_ep_list() {
|
423
|
+
episodes=$ep_choice_start
|
424
|
+
[ -n "$ep_choice_end" ] && episodes=$(seq "$ep_choice_start" "$ep_choice_end")
|
425
|
+
}
|
426
|
+
|
427
|
+
|
428
|
+
##################
|
429
|
+
# VIDEO PLAYBACK #
|
430
|
+
##################
|
431
|
+
|
432
|
+
# opens selected episodes one-by-one
|
433
|
+
open_selection() {
|
434
|
+
for ep in $episodes; do
|
435
|
+
open_episode "$selection_id" "$ep"
|
436
|
+
done
|
437
|
+
episode=${ep_choice_end:-$ep_choice_start}
|
438
|
+
}
|
439
|
+
|
440
|
+
open_episode () {
|
441
|
+
anime_id="$1"
|
442
|
+
episode="$2"
|
443
|
+
tput clear
|
444
|
+
progress "Loading episode $episode..."
|
445
|
+
# decrypting url
|
446
|
+
dpage_link=$(printf "%s" "$select_ep_result" | sed -n "${episode}p")
|
447
|
+
if [ -z "$dpage_link" ];then
|
448
|
+
err "Episode doesn't exist!!"
|
449
|
+
else
|
450
|
+
get_video_link "$dpage_link"
|
451
|
+
fi
|
452
|
+
[ "$debug" -eq 1 ] && exit 0
|
453
|
+
# write anime and episode number and save to temporary history
|
454
|
+
grep -q "$selection_id" "$logfile" || printf "%s\t%s\n" "$selection_id" $((episode+1)) >> "$logfile"
|
455
|
+
sed -E "s/^${selection_id}\t[0-9]*/${selection_id}\t$((episode+1))/" "$logfile" > "${logfile}.new"
|
456
|
+
[ ! "$PID" = "0" ] && kill "$PID" >/dev/null 2>&1
|
457
|
+
[ -z "$video_url" ] && die "Video URL not found"
|
458
|
+
trackma_title="$(printf '%s' "$anime_id Episode $episode" | tr '-' ' ' | awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,1,1)) substr($i,2) }}1')"
|
459
|
+
if [ "$auto_play" -eq 0 ]; then
|
460
|
+
play_episode "$video_url" "$refr" "$trackma_title"
|
461
|
+
else
|
462
|
+
printf "\n"
|
463
|
+
play_episode "$video_url" "$refr" "$trackma_title"
|
464
|
+
wait
|
465
|
+
sleep 2
|
466
|
+
fi
|
467
|
+
PID=$!
|
468
|
+
# overwrite history with temporary history
|
469
|
+
mv "${logfile}.new" "$logfile"
|
470
|
+
}
|
471
|
+
|
472
|
+
play_episode () {
|
473
|
+
video_url="$1"; refr="$2" trackma_title="$3"
|
474
|
+
if [ "$player_fn" = "download" ];then
|
475
|
+
inf "Currently downloading $trackma_title ($provider_name)"
|
476
|
+
else
|
477
|
+
inf "Currently playing $trackma_title ($provider_name)"
|
478
|
+
fi
|
479
|
+
case "$player_fn" in
|
480
|
+
download)
|
481
|
+
if download "$refr" "$video_url" "$trackma_title"; then
|
482
|
+
inf "Downloaded episode: $trackma_title"
|
483
|
+
else
|
484
|
+
err "Download failed episode: $trackma_title , please retry or check your internet connection"
|
485
|
+
fi
|
486
|
+
;;
|
487
|
+
iina)
|
488
|
+
echo "$player_fn $video_url --no-stdin --keep-running --mpv-referrer=$refr --mpv-force-media-title=$trackma_title"
|
489
|
+
nohup "$player_fn" "$video_url" --no-stdin --keep-running --mpv-referrer="$refr" --mpv-force-media-title="$trackma_title" > /dev/null 2>&1 & ;;
|
490
|
+
vlc)
|
491
|
+
if uname -a | grep -qE '[Aa]ndroid';then
|
492
|
+
echo android
|
493
|
+
am start --user 0 -a android.intent.action.VIEW -d "$video_url" -n org.videolan.vlc/org.videolan.vlc.gui.video.VideoPlayerActivity -e "title" "$trackma_title" > /dev/null 2>&1 &
|
494
|
+
else
|
495
|
+
echo not android?
|
496
|
+
echo "$player_fn $video_url --http-referrer=$refr --meta-title $trackma_title --play-and-exit"
|
497
|
+
nohup "$player_fn" "$video_url" --http-referrer="$refr" --meta-title "$trackma_title" --play-and-exit > /dev/null 2>&1 &
|
498
|
+
|
499
|
+
fi
|
500
|
+
;;
|
501
|
+
"syncplay"|"/Applications/Syncplay.app/Contents/MacOS/syncplay"|"/c/Program Files (x86)/Syncplay/Syncplay.exe")
|
502
|
+
nohup "$player_fn" "$video_url" -- --referrer="$refr" --force-media-title="$trackma_title" > /dev/null 2>&1 & ;;
|
503
|
+
*)
|
504
|
+
if uname -a | grep -qE '[Aa]ndroid';then
|
505
|
+
am start --user 0 -a android.intent.action.VIEW -d "$video_url" -n is.xyz.mpv/.MPVActivity > /dev/null 2>&1 &
|
506
|
+
else
|
507
|
+
nohup "$player_fn" "$video_url" --referrer="$refr" --force-media-title="$trackma_title" > /dev/null 2>&1 &
|
508
|
+
fi
|
509
|
+
;;
|
510
|
+
esac
|
511
|
+
}
|
512
|
+
|
513
|
+
############
|
514
|
+
# START UP #
|
515
|
+
############
|
516
|
+
|
517
|
+
# clears the colors and deletes temporary logfile when exited using SIGINT
|
518
|
+
trap 'printf "\033[0m";rm -f "$logfile".new;exit 1' INT HUP
|
519
|
+
|
520
|
+
# default options
|
521
|
+
agent="Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0"
|
522
|
+
PID=0
|
523
|
+
quality=best
|
524
|
+
scrape=Query
|
525
|
+
debug=0
|
526
|
+
choice=
|
527
|
+
fzf=0
|
528
|
+
auto_play=0
|
529
|
+
download_dir="$(pwd)"
|
530
|
+
case "$(uname)" in
|
531
|
+
Darwin*) player_fn='iina';;
|
532
|
+
*) player_fn='mpv';;
|
533
|
+
esac
|
534
|
+
# history file path
|
535
|
+
logdir="${XDG_CACHE_HOME:-$HOME/.cache}"
|
536
|
+
logfile="$logdir/ani-hsts"
|
537
|
+
# create history file and history dir if none found
|
538
|
+
[ -d "$logdir" ] || mkdir "$logdir"
|
539
|
+
[ -f "$logfile" ] || : > "$logfile"
|
540
|
+
|
541
|
+
while getopts 'svq:dp:chDUVa:xr:fn' OPT; do
|
542
|
+
case $OPT in
|
543
|
+
d) player_fn='download' ;;
|
544
|
+
a) ep_choice_to_start=$OPTARG ;;
|
545
|
+
U) update_script ;;
|
546
|
+
D)
|
547
|
+
: > "$logfile"
|
548
|
+
exit 0
|
549
|
+
;;
|
550
|
+
p)
|
551
|
+
player_fn='download'
|
552
|
+
download_dir="$OPTARG"
|
553
|
+
;;
|
554
|
+
n) scrape=New ;;
|
555
|
+
s)
|
556
|
+
case "$(uname -s)" in
|
557
|
+
Darwin*) player_fn="/Applications/Syncplay.app/Contents/MacOS/syncplay" ;;
|
558
|
+
MINGW*|*Msys) player_fn="/c/Program Files (x86)/Syncplay/Syncplay.exe" ;;
|
559
|
+
*) player_fn="syncplay" ;;
|
560
|
+
esac
|
561
|
+
;;
|
562
|
+
q) quality=$OPTARG ;;
|
563
|
+
x) debug=1 ;;
|
564
|
+
r) select_provider=$OPTARG ;;
|
565
|
+
f) fzf=1 ;;
|
566
|
+
c) scrape=History ;;
|
567
|
+
v) player_fn='vlc';;
|
568
|
+
V)
|
569
|
+
version_text
|
570
|
+
exit 0
|
571
|
+
;;
|
572
|
+
h)
|
573
|
+
help_text
|
574
|
+
exit 0
|
575
|
+
;;
|
576
|
+
*)
|
577
|
+
help_text
|
578
|
+
exit 1
|
579
|
+
;;
|
580
|
+
esac
|
581
|
+
done
|
582
|
+
shift $((OPTIND - 1))
|
583
|
+
progress "Checking dependencies.."
|
584
|
+
# shellcheck disable=SC2046
|
585
|
+
dep_ch "curl" "sed" "grep" "openssl" || true
|
586
|
+
|
587
|
+
if [ "$player_fn" = "download" ];then
|
588
|
+
dep_ch "ffmpeg" "axel"
|
589
|
+
elif ! (uname -a | grep -qE '[Aa]ndroid');then
|
590
|
+
dep_ch "$player_fn"
|
591
|
+
fi
|
592
|
+
|
593
|
+
gogohd_url="https://gogohd.net/"
|
594
|
+
base_url="https://animixplay.to"
|
595
|
+
if [ "$scrape" = "Query" ];then
|
596
|
+
if [ -z "$*" ]; then
|
597
|
+
prompt "Search Anime"
|
598
|
+
query="$REPLY $REPLY2"
|
599
|
+
else
|
600
|
+
if [ -n "$ep_choice_to_start" ]; then
|
601
|
+
REPLY=1
|
602
|
+
select_first=1
|
603
|
+
fi
|
604
|
+
query="$*"
|
605
|
+
fi
|
606
|
+
process_search
|
607
|
+
elif [ "$scrape" = "New" ];then
|
608
|
+
progress ""
|
609
|
+
selection_id="$(curl -s "https://animixplay.to/rss.xml" | sed -nE 's_.*link.*animixplay.to/v1/([^<]*)/ep([^<]*)<.*_\1 episode \2_p' | tr '-' ' ' | fzf --height=30% --border -1 --layout=reverse --cycle)"
|
610
|
+
[ -z "$selection_id" ] && die "No anime Selected"
|
611
|
+
ep=$(printf "%s" "$selection_id" | sed 's_.*episode __')
|
612
|
+
selection_id=$(printf "%s" "$selection_id" | sed 's_ episode.*__' | tr ' ' '-')
|
613
|
+
episode_list "$selection_id"
|
614
|
+
open_episode "$selection_id" "$ep"
|
615
|
+
exit 0
|
616
|
+
else
|
617
|
+
search_history
|
618
|
+
fi
|
619
|
+
|
620
|
+
generate_ep_list
|
621
|
+
open_selection
|
622
|
+
|
623
|
+
########
|
624
|
+
# LOOP #
|
625
|
+
########
|
626
|
+
|
627
|
+
while : ; do
|
628
|
+
auto_play=0
|
629
|
+
unset menu
|
630
|
+
unset options
|
631
|
+
[ "$episode" -ne "$last_ep_number" ] && menu=$(append "$menu" 'next' 'n')
|
632
|
+
[ "$episode" -ne "$first_ep_number" ] && menu=$(append "$menu" 'previous' 'p')
|
633
|
+
menu=$(append "$menu" 'replay' 'r')
|
634
|
+
[ "$first_ep_number" -ne "$last_ep_number" ] && menu=$(append "$menu" 'select' 's')
|
635
|
+
menu=$(append "$menu" 'quit' 'q')
|
636
|
+
if [ "$fzf" -eq 1 ];then
|
637
|
+
progress ""
|
638
|
+
choice="$(selection_menu_fzf ". Menu>>" "$menu")"
|
639
|
+
[ -z "$choice" ] && die "No anime Selected"
|
640
|
+
else
|
641
|
+
selection_menu "$menu"
|
642
|
+
choice="$REPLY"
|
643
|
+
fi
|
644
|
+
case $choice in
|
645
|
+
n|'')
|
646
|
+
ep_choice_start=$((episode + 1))
|
647
|
+
unset ep_choice_end
|
648
|
+
;;
|
649
|
+
p)
|
650
|
+
ep_choice_start=$((episode - 1))
|
651
|
+
unset ep_choice_end
|
652
|
+
;;
|
653
|
+
r)
|
654
|
+
ep_choice_start="$episode"
|
655
|
+
unset ep_choice_end
|
656
|
+
;;
|
657
|
+
s)
|
658
|
+
episode_selection ;;
|
659
|
+
q)
|
660
|
+
break ;;
|
661
|
+
*)
|
662
|
+
tput clear
|
663
|
+
err "Invalid choice"
|
664
|
+
continue
|
665
|
+
;;
|
666
|
+
esac
|
667
|
+
generate_ep_list
|
668
|
+
open_selection
|
669
|
+
done
|
670
|
+
|
671
|
+
# ani-cli
|
672
|
+
#
|
673
|
+
# This program is free software: you can redistribute it and/or modify
|
674
|
+
# it under the terms of the GNU General Public License as published by
|
675
|
+
# the Free Software Foundation, either version 3 of the License, or
|
676
|
+
# (at your option) any later version.
|
677
|
+
#
|
678
|
+
# This program is distributed in the hope that it will be useful,
|
679
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
680
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
681
|
+
# GNU General Public License for more details.
|
682
|
+
#
|
683
|
+
# You should have received a copy of the GNU General Public License
|
684
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
685
|
+
#
|
686
|
+
# Project repository: https://github.com/pystardust/ani-cli
|