Compare commits

..

2 Commits

Author SHA1 Message Date
7797c47195
fixed some edge cases 2023-12-12 22:17:56 -07:00
c34856d134
refactor and added sync functionality 2023-12-12 18:41:31 -07:00

199
yt
View File

@ -27,14 +27,22 @@ test -n "$YT_PL_DIR" \
|| test -n "$XDG_DATA_HOME" && YT_PL_DIR="$XDG_DATA_HOME/yt" \
|| YT_PL_DIR="$HOME/.local/share/yt"
test -d "$YT_PL_DIR" \
|| mkdir -p "$YT_PL_DIR"
# formatted $YT_PL_DIR for use with sed
P="$(printf '%s\n' "$YT_PL_DIR" | sed 's;\/;\\/;g')"
argv0="$0"
com="$1"
u='add | archive | clone | list | new | pick | play | search | sync | verify'
FMT='%(title)s %(channel)s (%(duration>%H:%M:%S)s) [%(webpage_url)s]'
WBAPI='https://archive.org/wayback/available?url='
add() { # adds a video to a playlist file
test -z "$2" || test -n "$3" && usage 'add uri playlist'
while test -f "$YT_PL_DIR/$2.m3u"; do
file="$YT_PL_DIR/$2.m3u"
video="$(printf '%s\n' "$1" \
@ -47,8 +55,8 @@ add() { # adds a video to a playlist file
"$argv0" "$file" "$video"
exit
else
cache "$video"
archive "$video"
cache "$video" &
archive "$video" &
printf "%s\n" "$video" >> "$file"
fi
@ -57,6 +65,8 @@ add() { # adds a video to a playlist file
}
archive() { # archives a video to the Wayback Machine
test -z "$1" && usage 'archive uri...'
while test -n "$1"; do
if test -n "$(printf '%s\n' "$1" | grep -e 'web\.archive\.org')"
then
@ -78,6 +88,8 @@ archive() { # archives a video to the Wayback Machine
}
cache() { # cache the video title for faster retrieval
test -z "$1" && usage 'cache video...'
test -e "$cachefile" || touch "$cachefile"
while test -n "$1"; do
@ -88,13 +100,28 @@ cache() { # cache the video title for faster retrieval
}
clone() { # clones a YouTube playlist to a file
test -d "$YT_PL_DIR" || mkdir -p "$YT_PL_DIR"
test -z "$1" && usage 'clone uri [playlist]'
test -n "$2" && file="$2" \
|| file="$YT_PL_DIR/$(yt-dlp -s -I '1:1' --print '%(playlist)s' "$1").m3u"
n=1
yt-dlp --flat-playlist "$1" --print url > "$file"
verify "$file"
while test -z "$title"; do
title="$(yt-dlp -s -I "$n" --print '%(playlist)s' "$1" || true)"
n="$((n + 1))"
done
creator="$(yt-dlp -s -I "$n" --print '%(playlist_uploader)s' "$1")"
filename="$(printf '%s\n' "$title" | sed 's/ /_/g')"
file="$YT_PL_DIR/$filename.m3u"
videos="$(yt-dlp --flat-playlist "$1" --print url)"
prefix="$(printf "#EXTM3U\n#EXTART:%s\n#PLAYLIST:%s [%s]\n" \
"$creator" "$title" "$1")"
printf "%s: %s: Saving playlist to %s.\n" "$argv0" "$title" "$file" 1>&2
printf '%s\n\n%s\n' "$prefix" "$videos" >"$file"
verify "$filename"
}
lines() {
@ -105,6 +132,8 @@ lines() {
}
list() {
test -n "$1" && usage 'list'
if test -z "$YTPICK"; then
printf "%s: Please set \$YTPICK to your preferred picking tool." \
"$argv0" 1>&2
@ -117,7 +146,7 @@ list() {
}
menu() {
playlist="$(ls "$YT_PL_DIR" | sed 's/\.m3u//g' | $YTPICK)"
playlist="$(ls "$YT_PL_DIR" | sed 's/\.m3u//g' | sed -n '/[^.old]/p' | $YTPICK)"
while test -d "$YT_PL_DIR/$playlist"; do
dir="$playlist"
@ -128,16 +157,23 @@ menu() {
printf '%s/%s\n' "$dir" "$playlist"
}
music() { # downloads a video, splitting by chapter and only saving the audio
while test -n "$1"; do
yt-dlp -vx --split-chapters -o \
"chapter:%(fulltitle)s - %(section_number)s %(section_title)s.%(ext)s" \
"$1" --audio-quality 0 >> log 2>&1
shift
done
new() {
test -z "$1" && usage 'new playlist...'
file="$YT_PL_DIR/$1.m3u"
if test -f "$file"; then
printf "%s: %s: File exists." "$argv0" "$file"
elif test -d "$file"; then
printf "%s: %s: Is a directory." "$argv0" "$file"
else
touch "$file"
fi
}
pick() { # Pick a video to play from a playlist of videos
test -z "$1" && usage 'pick playlist...'
if test -z "$YTPICK"; then
printf "%s: Please set \$YTPICK to your preferred picking tool." \
"$argv0" 1>&2
@ -152,7 +188,7 @@ pick() { # Pick a video to play from a playlist of videos
then
continue
else
cache "$line"
cache "$line" &
fi
if test -z "$list"; then
@ -172,17 +208,21 @@ pick() { # Pick a video to play from a playlist of videos
}
play() { # play a video after caching its title
test -z "$1" && usage 'play uri...'
if test -z "$PLAYER"; then
printf "%s: Please set \$PLAYER to your preferred video player." \
"$argv0" 1>&2
exit 78 # sysexits.h(3) EX_CONFIG
fi
cache "$@"
cache "$@" &
"$PLAYER" "$@"
}
queue() {
test -z "$1" && usage 'queue playlist...'
if test -z "$PLAYER"; then
printf "%s: Please set \$PLAYER to your preferred video player." \
"$argv0" 1>&2
@ -196,6 +236,8 @@ queue() {
}
search() {
test -z "$1" && usage 'search term [count]'
if test -z "$YTPICK"; then
printf "%s: Please set \$YTPICK to your preferred picking tool." \
"$argv0" 1>&2
@ -204,6 +246,9 @@ search() {
results="$(yt-dlp "ytsearch$2:$1" --print "$FMT")"
cache "$(printf '%s\n' "$results" | sed -e 's/.*\[//g' -e 's/\]/ /g' \
| tr -d '\n')" &
selection="$(printf '%s\n' "$results" \
| $YTPICK \
| sed 's/.*\[//g' \
@ -229,16 +274,60 @@ search() {
fi
}
searchlocal() {
test -n "$1" && usage 'searchlocal'
if test -z "$YTPICK"; then
printf "%s: Please set \$YTPICK to your preferred picking tool." \
"$argv0" 1>&2
exit 78 # sysexits.h(3) EX_CONFIG
fi
$YTPICK <"$cachefile"
}
sync() {
if test -z "$1"
then
set -- "$YT_PL_DIR"/*.m3u
else
set -- $(printf "$@" | sed "s/.* /$P\/&\.m3u /g")
fi
while test -n "$1"; do
file="$1"
if test -f "$file"; then
URL="$(sed -n 's/^\#PLAYLIST:.* \[//p' <"$file" | tr -d ']')"
if test -n "$URL"; then
clone "$URL" && mv "$file" "$file.old"
fi
fi
shift
done
}
usage() {
printf "Usage: %s %s\n" "$argv0" "$@" 1>&2
exit 64 # sysexits.h(3) EX_USAGE
}
verify() { # replaces videos with archived versions if they are not available
while test -f "$YT_PL_DIR/$1.m3u"; do
file="$YT_PL_DIR/$1.m3u"
test -z "$1" && usage 'verify playlist...'
for video in $(lines "$file"); do
set -- $(printf '%s\n' "$@" | sed "s/[^ ]*/$P\/&.m3u /g")
while test -n "$1"; do
if ! test -f "$1"; then
printf '%s: %s: No such playlist.\n' \ "$argv0" "$1" 1>&2
exit 69 # syexits.h(3) EX_UNAVAILABLE
fi
printf "%s: %s: Verifying playlist.\n" "$argv0" "$1" 1>&2
for video in $(lines "$1"); do
if test -n "$(yt-dlp -s "$video" 2>&1 \
| grep -i -e 'video unavailable' -e 'private video' -e 'been removed')"
then
@ -254,22 +343,22 @@ verify() { # replaces videos with archived versions if they are not available
printf "%s: %s: Video not available on the Wayback Machine.\n" \
"$argv0" "$video" 1>&2
# replace the video link with a comment containing link
content="$(sed "s;^$video;\# $video;g" "$file")"
content="$(sed "s;^$video;\# $video;g" "$1")"
# write the new content buffer to file
printf '%s\n' "$content" > "$file"
printf '%s\n' "$content" > "$1"
else
printf "%s: %s: Replacing link with Wayback link.\n" \
"$argv0" "$video" 1>&2
content="$(sed "s;^$video;$wayback_url;g" "$file")"
printf '%s\n' "$content" >"$file"
cache "$wayback_url"
content="$(sed "s;^$video;$wayback_url;g" "$1")"
printf '%s\n' "$content" >"$1"
cache "$wayback_url" &
fi
else
printf '%s: %s: Video available.\n' "$argv0" "$video" 1>&2
cache "$video"
archive "$video"
cache "$video" &
archive "$video" &
fi
done
@ -284,57 +373,11 @@ for dep in \
do
if ! command -v "$dep" >/dev/null
then
printf "%s: %s: Missing dependency." "$argv0" "$dep" 1>&2
printf "%s: %s: Missing dependency.\n" "$0" "$dep" 1>&2
exit 69 # syexits.h(3) EX_UNAVAILABLE
fi
done
case "$com" in
add)
shift 2>/dev/null || usage 'add uri file'
add "$@"
;;
archive)
shift 2>/dev/null || usage 'archive uri...'
archive "$@"
;;
cache)
shift 2>/dev/null || usage 'cache uri...'
cache "$@"
;;
clone)
shift 2>/dev/null || usage 'clone uri [file]'
clone "$@"
;;
list)
shift 2>/dev/null || usage 'list'
list "$@"
;;
music)
shift 2>/dev/null || usage 'music uri...'
music "$@"
;;
pick)
shift 2>/dev/null || usage 'pick file...'
pick "$@"
;;
play)
shift 2>/dev/null || usage 'play uri...'
play "$@"
;;
queue)
shift 2>/dev/null || usage 'queue file...'
queue "$@"
;;
search)
shift 2>/dev/null || usage 'search term [count]'
search "$@"
;;
verify)
shift 2>/dev/null || usage 'file...'
verify "$@"
;;
*)
usage 'add | clone | list | music | pick | play | verify'
;;
esac
test -n "$com" && shift || usage "$u"
"$com" "$@"