-
Notifications
You must be signed in to change notification settings - Fork 0
/
seen
executable file
·385 lines (326 loc) · 11.7 KB
/
seen
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
#!/bin/bash
#seen42 v1.7
# Many of us watch series of shows on their computer. Many of us take a break between episodes. Many of us forget what
# episode number we watched last. And as most of us are too lazy to search through episode which one we have seen
# and which not: Some of us place a reminder in the directory of the episodes. Name it "Last_seen_ep42" or for short
# "seen42"
# This is this reminder. But now it moves forward if you click on it. And it opens the correct episode if you are on
# the console and moves the marker automatically after watching. And if you keep copying it, it will spread everywhere.
# Thats it. Thats all it does.
# License: This work is almost certainly below the "threshold of originality" but to avoid confusion it's MIT-Licensed
# A copy of the license and the original (and probably not) updated source can be
# found @ https://github.com/cryptkiddy/seen42
#How To:
# moves the $seen-episodes-marker by one. (aka. renames itself if you click it "seen1"->"seen2"...)
# Start by naming this file "seen1" (or "seen0" if nothing was seen yet ^^)
# ( Sidenote: can also be put in your PATH to handle initial move automatically.
# Just call it like you would execute this file and go from there. )
#
# "seen --all" will set the marker to read "seenAll", which is usefull after finishing the episodes.
# "seen --open" or "seen o" can be used to automatically start the next episode and advance the pointer if it has been
# watched for a given time (see settings)
# ( sidenote2: if seenAll existis it is ignored as you might be rewatching, and then it's handy to have it
# ignored but kept around as marker (I like it that way YMMV ) )
# settings -----
PLAYER="smplayer -fullscreen -close-at-end" #player to use. Should be blocking, otherwise this script can not work properly. use wrappers if needed.
SECONDS_TO_ASSUME_SEEN=240 #==4min ; if player is opened less than this time no automatic advance of seen will be done (so you can have a short look into episodes)
### internal -----------
SEENALL=false
OPEN=false
VERBOSE=false
REGEXDEBUG=false
NUMBEREDSEEN=false
SeenNumber=-1
#array of regex scrapers, telling us what filenames to consider an episode (and in what order, cnf. seen --open) ((some regex ideas taken from kodi))
#in this ++EPISODE_NUMBER_VAL++ will be expanded to the episode we are looking for.
#use "break" to stop searching, if anything was found before this entry. If not "break" is ignored. Feel free to use "break abc123..." for debugging. everything after "break"
# is ignored, but echod in verbose mode. comments start with "#" on a new line and are simply echod. Note that comments always need their own line.
SEASON='\([0-9]\{0,2\}[1-9]\)'
SEASON_STRING='[sS]\([eE]\([aA]\([sS]\([oO]\([nN]\?\)\)\?\)\?\)\?\)\?'
EPISODE_STRING='[eE]\([pP]\([iI]\([sS]\([oO]\([dD]\([eE]\)\?\)\?\)\?\)\?\)\?\)\?'
EPISODE='0*++EPISODE_NUMBER_VAL++'
ScraperRegex=(
"break 1" #generic hint: it is often better to split a regex into different small ones, as ordering in this list results in ordering of matches in output.
"# abc_season01e3_abc.mkv, s1e3.lol s-01.e_4.ext"
".*/.*${SEASON_STRING}${SEASON}[._]\?${EPISODE_STRING}$EPISODE\(\|[^0-9]\+.*\)"
".*/.*${SEASON_STRING}[_-]\?${SEASON}[._-]\?${EPISODE_STRING}[_-]\?$EPISODE\(\|[^0-9]\+.*\)"
"break 2"
"# abc_e3.mkv abc_e-3.ext abc_e 3.ext"
".*/.*${EPISODE_STRING}$EPISODE\(\|[^0-9]\+.*\)"
".*/.*${EPISODE_STRING}[_ -]$EPISODE\(\|[^0-9]\+.*\)"
"break 3"
"# abc_1x3_abc.mkv abc_1.3_abc.mkv"
".*/.*${SEASON}[xX._-]$EPISODE\(\|[^0-9]\+.*\)"
".*/.*${SEASON}[xX._-]$EPISODE\(\|[^0-9]\+.*\)"
"break 4"
"# abc_108.mkv abc_2308.ext"
"# 2 digit season we require a separating 0 : 1208 12011 (s12e8 s12e11)" #( for 1 digit season: see below)
".*/\(\|.*[^0-9]\)[0]*[1-9]\{1,3\}[0]${EPISODE}\(\|[^0-9]\+.*\)"
"break 5"
"# abc_34. _abc"
".*/\(\|.*[^0-9]\)[0]*${EPISODE}[.]\ \(\|[^0-9]\+.*\)"
"# abc_34._abc"
".*/\(\|.*[^0-9]\)[0]*${EPISODE}[.]\(\|[^0-9]\+.*\)"
"# '34 - bla.mp4' == Filename starts with the number"
".*/[0]*${EPISODE}\(\|[^0-9]\+.*\)" #FIXME: this seems to be ignored if the ones before trigger?
"break 5.5"
"#Regex is for e.g.: Season 02 Ep 34 : string must include '34'. formats possible: 200034 (s2 ep 34) or 00034 or without the 0. one 0 between ep and s is needed. If Ep and Seas"
"# are separate, season is simply ignored in filename."
".*/\(.*[^0-9]\+\|\)\([1-9]0\+\)\?0*++EPISODE_NUMBER_VAL++\(\|[^0-9]\+.*\)"
"break 6 -- below lies desperation"
"# 12345_abc_8_12abc.mkv (contains episodenumber surrounded by nonwhitespace. Pretty low bar..)"
".*/\(\|.*[^0-9]\)${EPISODE}\(\|[^0-9]\+.*\)"
"break 7"
"# 1 digit season we accept 108 (s1e8) and 18 and even 112 (s1e12)"
".*/\(\|.*[^0-9]\)[0]*[1-9]${EPISODE}\(\|[^0-9]\+.*\)"
"break 8"
"# abc_08abc, abc_234_8_abc.mkv abc_1238_abc.mkv (s5e8)"
".*/.*${EPISODE}\(\|[^0-9]\+.*\)"
"break 9"
"# *8* (s1ep8) (anything with the episode number ANYWHERE in it)"
".*/.*${EPISODE}.*"
"break 10"
"# screw it. take whatever resembles a file."
".*"
)
#TODO, NOTE: Mostly episodes are named such that alphabetically e.g. 7 follows 6 and is followed by 8. Use that as default preselection for chooser.
# Ideas: dont modify arrays, work with arrays of indexes into the filename array. (use only videofiles to begin with)
# Extract selector stuff into function, that takes episodecount as array. Sort arrays, look for consecutive number in e.g. Ep3 Ep 4 and Ep 5 array and if exists,
# that is probably the desired EP 4. Special handling required for first and last episode.
# 2. Idea: sliding window over the array of all videonames. Stash any good fit. must be done before pruning for "fitting names"
# 3. Idea: use substitute on the found files with our regex to replace $CURRENTNUMBER with $PREV and $NEXT. See if those new names exist in the folder. handle first/last EP. (check if are video files.)
# - what about: Exists, but has different suffix ("movieE10S30[0xAFDE1356C]")
# 4. Idea: if rhash calculated crc checksum appears in filename, ignore that for episode search
#Parse commandline
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-a|a|--all|all)
SEENALL=true
;;
-o|o|--open|open)
OPEN=true
;;
-v|v|--verbose|verbose)
VERBOSE=true
;;
-rd|rd|--regexdebug|regexdebug)
REGEXDEBUG=true
VERBOSE=true
OPEN=true
;;
*)
#check if number
re='^[0-9]+$'
if [[ $key =~ $re ]] ; then
NUMBEREDSEEN=true
SeenNumber=$key
else
#unknown option
echo "error, wrong parameter. See https://github.com/cryptkiddy/seen42"
exit 254
fi
unset re
;;
esac
shift #advance parameter
done
mv -n seen{.sh,0} 2>/dev/null #so you can name it properly if not in use.
#find current marker if it exists, note this chooses the lowest seen42 marker. This allows rewatching keeping the highest marker.
markerArray=()
for marker in seen*
do
if [[ -f "$marker" && "$marker" =~ ^seen[0-9]+$ ]]
then
markerArray+=("${marker/seen/}")
fi
done
IFS=$'\n'
mapfile -t sortedMarker < <(sort -n <<<"${markerArray[*]}")
unset IFS
count=${sortedMarker[0]}
if [ "y$count" == "y" ]
then
#did not find old marker
if $SEENALL
then
cp -n "$0" seenAll
exit 0
else
cp -n "$0" seen0
fi
count=0 # not found <=> seen0 exists => use this for further processing
fi
countpre=$count
countpost=$((count+1))
if $VERBOSE
then
echo Next episode to come: $countpost
fi
if $OPEN
then
#get candidates by filetype and name according to regex in $ScraperRegex
episode_candidate_array=()
for regex in "${ScraperRegex[@]}"
do
if [[ "$regex" == \#* ]]
then
if $VERBOSE
then
echo "##$regex"
fi
continue
fi
if [[ "$regex" == break* ]]
then
if $VERBOSE
then
echo "$regex"
echo
fi
if [ ${#episode_candidate_array[@]} -ne 0 ]
then
if ! $REGEXDEBUG
then
break
else
#echo "+skip break due to RegExDebug"
continue
fi
else
continue
fi
fi
if $VERBOSE
then
echo RegEx: "$regex"
fi
# find a fittingly named episode (or multiple ):
array_by_filename=()
while IFS= read -r -d $'\0'; do
array_by_filename+=("$REPLY")
done < <(find . -maxdepth 1 -regextype sed \( -type f -o -type l \) -iregex "${regex//++EPISODE_NUMBER_VAL++/$countpost}" -print0 )
for FIL in "${array_by_filename[@]}"
do
if $VERBOSE
then
echo -n "---- $FIL"
fi
tmp=$(file -N -i -L -- "$FIL" | sed -n 's-: video/[^:]*$--p')
if [ "y$tmp" != "y" ]
then
if $VERBOSE
then
echo " added"
fi
episode_candidate_array+=("$tmp")
else
if $VERBOSE
then
echo ": is not a movie"
echo " NONMOVIE DISCARDED"
fi
fi
done
done
#remove double keeping only topmost appareance in $episode_candidate_array of each
episode_candidate_uniq=()
while read -r line
do
if [ "y" != "$(echo "y$line" |tr -d '[:space:]')" ]
then
episode_candidate_uniq+=("$line")
fi
done <<< "$(printf "%s\n" "${episode_candidate_array[@]}" | awk -v RS='\n' '!a[$0]++{printf "%s%s", $0, RT}')"
episode_candidate_array=("${episode_candidate_uniq[@]}")
unset episode_candidate_uniq
if $REGEXDEBUG
then
echo Exiting due to RegExDebug enabled.
exit
fi
#show selection dialog (except if only one candidate)
if [ ${#episode_candidate_array[@]} -eq 0 ]
then
echo No appropriately named episode found. Exiting.
exit 1
elif [ ${#episode_candidate_array[@]} -eq 1 ]
then
CANDID_SELECTED="${episode_candidate_array[0]}"
else
#present selection screen if multiple candidates found
selected="Null"
echo "Choose episode $countpost from candidates:"
echo "0) Exit programm"
select _ in "${episode_candidate_array[@]}"
do
re='^[0-9]+$'
if ! [[ "$REPLY" =~ $re ]] #check if is integer
then
echo Err: not a number.
#redisplay
else
if [ "$REPLY" -eq 0 ]
then
echo Exiting.
exit 0
fi
selected=$(( REPLY - 1))
CANDID_SELECTED="${episode_candidate_array[$selected]}"
break
fi
done
if [ "y$selected" == "yNull" ]
then #if select was interrupted with ^D
echo Exiting
exit 0
fi
fi
if $VERBOSE
then
echo candidate selected is: "$CANDID_SELECTED"
fi
#episode found or seleced. Starting player and measuring time it was open:
echo starting: "$PLAYER" "$CANDID_SELECTED"
SECONDS=0
$PLAYER "$CANDID_SELECTED"
DURATION=$SECONDS
if [ $DURATION -le $SECONDS_TO_ASSUME_SEEN ]
then
#watched less than $SECONDS_TO_ASSUME_SEEN => probably not finished ( maybe was wrong episode, or looked too boring, or...)
echo Did not move seenMarker, because you did not watched long enough. \(only $DURATION seconds of $SECONDS_TO_ASSUME_SEEN needed.\)
exit 0
else
echo Moved seenMarker. Watched long enough. \($DURATION seconds of $SECONDS_TO_ASSUME_SEEN needed.\)
fi
fi
#set the seenAll marker.
if $SEENALL
then
moveTo='All'
elif $NUMBEREDSEEN
then
moveTo="$SeenNumber"
else
moveTo=$countpost
fi
#updater for seen file version and advancer:
#get our own version number
ownVerNum="$(awk -F v -- '$1 ~ /^#seen42 $/ {printf "%s",$2 }' "$0")"
#compare to seenfiles verNum:
areWeNewer="$(awk -F v -- '$1 ~ /^#seen42 $/ {printf "%d",($2>='"$ownVerNum"') }' "seen$countpre")" ## note that 0 is false here, hence the switched >= !!!
#if version of currently executed script is higher than version of script in markerFile update the marker file.
if [ ! "y$areWeNewer" == "y" ] && [ "$areWeNewer" == 0 ]
then
#file should be updated (our version is newer AND old file was a "seen42" script (contained marker => no risk of clobbering s.th.))
cp "$0" "seen$countpre" 2>/dev/null
echo updating seenMarker to version "$ownVerNum".
fi
if [ ! -e "seen$moveTo" ]
then
mv -n seen{$countpre,$moveTo} 2>/dev/null
echo seen{$countpre-\>,$moveTo}
else
echo ERROR: next seen file \(seen$moveTo\) already exists. Cowardly refusing to overwrite it. 1>&2
fi