Compare commits
10 Commits
bf5117c655
...
66f2f852f2
| Author | SHA1 | Date | |
|---|---|---|---|
| 66f2f852f2 | |||
| 0c273bb02c | |||
| a2846eb4a3 | |||
| 6be68d0538 | |||
| 11c2cf9b1d | |||
| b72d79b987 | |||
|
|
89fe982535 | ||
| df1d74b2fc | |||
| 4fd4316e51 | |||
| ad67e8279f |
0
.travis.yml
Normal file → Executable file
0
.travis.yml
Normal file → Executable file
2
README.md
Normal file → Executable file
2
README.md
Normal file → Executable file
@@ -14,7 +14,7 @@ I'm a fan of command line and "doing things yourself".
|
||||
I also don't like having a Google account, but still want to keep track of subscriptions.
|
||||
Thus [subs](http://github.com/mitchweaver/subs) was born.
|
||||
|
||||

|
||||

|
||||
|
||||
## Environment
|
||||
|
||||
|
||||
137
subs
137
subs
@@ -1,4 +1,12 @@
|
||||
#!/bin/sh
|
||||
# █████
|
||||
# ▒▒███
|
||||
# █████ █████ ████ ▒███████ █████
|
||||
# ███▒▒ ▒▒███ ▒███ ▒███▒▒███ ███▒▒
|
||||
# ▒▒█████ ▒███ ▒███ ▒███ ▒███▒▒█████
|
||||
# ▒▒▒▒███ ▒███ ▒███ ▒███ ▒███ ▒▒▒▒███
|
||||
# ██████ ▒▒████████ ████████ ██████
|
||||
# ▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒
|
||||
#
|
||||
# Watch your youtube subscriptions without a youtube account
|
||||
# via curl, dmenu, mpv and basic unix commands.
|
||||
@@ -9,16 +17,22 @@
|
||||
# For more information and examples, see:
|
||||
# http://github.com/mitchweaver/subs
|
||||
#
|
||||
# >> note: this is highly experimental / janky, it can and will break <<
|
||||
#
|
||||
# -/-/-/-/- Settings -/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
|
||||
: "${SUBS_FILE:=~/files/subs.txt}"
|
||||
: "${SUBS_MENU_PROG:='dmenu -p Subs:'}"
|
||||
: "${SUBS_MENU_PROG:=dmenu -l 18 -p Subs:}"
|
||||
: "${SUBS:=${XDG_CACHE_HOME:-~/.cache}/subs}"
|
||||
: "${SUBS_LINKS:=$SUBS/links}"
|
||||
: "${SUBS_CACHE:=$SUBS/cache}"
|
||||
: "${SUBS_SLEEP_VALUE:=0.05}" # raise this if you experience problems
|
||||
: "${SUBS_SLEEP_VALUE:=1}" # raise this if you experience problems
|
||||
: "${SUBS_DAEMON_INTERVAL:=600}"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SEP=^^^^^ # shouldn't need to change this
|
||||
# -/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
|
||||
export LC_ALL=C # this speeds things up a bit but can cause
|
||||
# issues for titles in foreign languages
|
||||
# -/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
|
||||
|
||||
die() {
|
||||
>&2 printf '%s\n' "$*"
|
||||
@@ -26,7 +40,7 @@ die() {
|
||||
}
|
||||
|
||||
usage() {
|
||||
die 'Usage: subs [-m no-video] [-g gen-links] [-u update-cache] [-d daemonize]'
|
||||
die 'Usage: subs [-m no-video] [-g gen-links] [-u update-cache] [-d daemonize] [-n dont-play]'
|
||||
}
|
||||
|
||||
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||
@@ -40,6 +54,7 @@ gen_links() {
|
||||
|
||||
count=0
|
||||
total=$(sed -e '/^$/d' -e '/^#/d' <"$SUBS_FILE" | wc -l)
|
||||
total=${total##* }
|
||||
|
||||
while read -r line ; do
|
||||
|
||||
@@ -55,20 +70,31 @@ gen_links() {
|
||||
case $line in
|
||||
UC*)
|
||||
# YT channel IDs always begin with 'UC' and are 24 chars long
|
||||
printf "[%s/%s] using channel ID '%s' for xml link\n" "$count" "$total" "$line"
|
||||
if [ ${#line} -eq 24 ] ; then
|
||||
printf "[%s/%s] using channel ID '%s' for xml link\n" "$count" "$total" "$line"
|
||||
|
||||
[ ${#line} -eq 24 ] &&
|
||||
printf 'https://youtube.com/feeds/videos.xml?%s\n' \
|
||||
"channel_id=$line" >>"$SUBS_LINKS"
|
||||
else
|
||||
>&2 printf 'Error: cannot determine channel for %s\n' "$line"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# otherwise we are given a username, we must find out its channel ID
|
||||
printf "fetching channel ID for %s...\n" "$line"
|
||||
printf "Fetching channel ID for %s..." "$line"
|
||||
|
||||
curl -sfL --retry 10 "https://youtube.com/user/$line/about" | \
|
||||
data=$(curl -sL --retry 10 "https://youtube.com/user/$line/about")
|
||||
if printf '%s\n' "$data" | grep '404 Not Found' >/dev/null ; then
|
||||
>&2 printf '\n[ERROR]: Could not determine channel for %s... 404\n' "$line"
|
||||
>&2 printf '[%s] %s\n' "$(date)" "$line" >> "$SUBS"/ERRORS.log
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$data" | \
|
||||
while read -r line ; do
|
||||
case $line in
|
||||
*channel/UC??????????????????????*)
|
||||
printf ' Found!\n'
|
||||
line=${line##*channel/}
|
||||
line=${line%%\"*}
|
||||
printf "[%s/%s] using channel ID '%s' for xml link\n" "$count" "$total" "$line"
|
||||
@@ -76,18 +102,10 @@ gen_links() {
|
||||
"$line" >>"$SUBS_LINKS"
|
||||
break
|
||||
esac
|
||||
done &
|
||||
sleep "${SUBS_SLEEP_VALUE:-0}"
|
||||
done
|
||||
esac
|
||||
|
||||
done <"$SUBS_FILE"
|
||||
|
||||
count=0
|
||||
while [ "$count" -ne "$total" ] ; do
|
||||
count=$(wc -l < "$SUBS_LINKS")
|
||||
printf "[%s/%s] waiting for jobs to complete...\n" "$count" "$total"
|
||||
sleep 0.5
|
||||
done
|
||||
}
|
||||
|
||||
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||
@@ -97,7 +115,13 @@ gen_links() {
|
||||
# with a line of its videos dates, titles, and urls.
|
||||
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||
get_vids() {
|
||||
data=$(curl -sfL --retry 15 "$1")
|
||||
data=$(curl -sL --retry 15 "$1")
|
||||
|
||||
if printf '%s\n' "$data" | grep '404 Not Found' >/dev/null ; then
|
||||
>&2 printf '[ERROR]: Could not get vids for %s... 404\n' "$1"
|
||||
>&2 printf '[%s] %s\n' "$(date)" "$1" >> "$SUBS"/ERRORS.log
|
||||
return 1
|
||||
fi
|
||||
|
||||
# hide the first <published> tag which is the channel
|
||||
# creation date
|
||||
@@ -134,6 +158,7 @@ get_vids() {
|
||||
|
||||
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||
# Updates the local cache of subscriptions. ([-u] flag)
|
||||
# shellcheck disable=2086
|
||||
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||
update_subs() {
|
||||
[ -f "$SUBS_LINKS" ] || die 'Subs links have not been generated.'
|
||||
@@ -142,6 +167,7 @@ update_subs() {
|
||||
mkdir -p "$SUBS_CACHE"
|
||||
|
||||
total=$(wc -l <"$SUBS_LINKS")
|
||||
total=${total##* }
|
||||
|
||||
count=0
|
||||
while read -r link ; do
|
||||
@@ -152,10 +178,13 @@ update_subs() {
|
||||
done <"$SUBS_LINKS"
|
||||
|
||||
count=0
|
||||
while [ "$count" -ne "$total" ] ; do
|
||||
max_retries=$total
|
||||
while [ "$count" -ne "$total" ] && [ "$max_retries" -ne "$total" ] ; do
|
||||
count=$(printf '%s\n' "$SUBS_CACHE"/* | wc -l)
|
||||
count=${count##* }
|
||||
printf "[%s/%s] waiting for fetch jobs to complete...\n" "$count" "$total"
|
||||
sleep 0.5
|
||||
sleep 1
|
||||
max_retries=$(( max_retries + 1 ))
|
||||
done
|
||||
|
||||
printf '%s\n\n' 'done!'
|
||||
@@ -182,25 +211,31 @@ cat_subs() {
|
||||
# Finally, play the result with mpv.
|
||||
get_sel() {
|
||||
if [ -d "$SUBS_CACHE" ] ; then
|
||||
sel=$(cat_subs | $SUBS_MENU_PROG)
|
||||
# Pipe your subs feed into your desired menu and replace HTML escape codes (" -> ")
|
||||
sel=$(cat_subs | sed -e 's/"/"/g' -e 's/&/\&/g' -e 's/</</g' -e 's/>/>/g' | $SUBS_MENU_PROG)
|
||||
else
|
||||
die 'Subs cache has not been retrieved.'
|
||||
fi
|
||||
|
||||
[ "$sel" ] || die Interrupted
|
||||
|
||||
chan="${sel#* }"
|
||||
chan="${chan%%] *}"
|
||||
title=${sel#*"$chan"\] }
|
||||
oldchan="${sel#* }"
|
||||
chan=$(printf '%s' "${oldchan%%] *}" | sed -e 's/\&/&/g' -e 's/"/\"/g' -e 's/</\</g' -e 's/>/\>/g' )
|
||||
title=$(printf '%s' "${sel#*"${oldchan%%] *}"\] }" | sed -e 's/\&/&/g' -e 's/"/\"/g' -e 's/</\</g' -e 's/>/\>/g' )
|
||||
while read -r line ; do
|
||||
case $line in
|
||||
*"$SEP$title$SEP"*)
|
||||
url=${line##*$SEP}
|
||||
if [ "$url" ] ; then
|
||||
printf 'playing: %s\n' "$url"
|
||||
# Play the selection.
|
||||
# shellcheck disable=2086
|
||||
exec mpv $MPV_OPTS "$url"
|
||||
if [ "$DONT_PLAY" ] ; then
|
||||
# just print the url
|
||||
# (useful for piping to other programs)
|
||||
printf '%s\n' "$url"
|
||||
else
|
||||
printf 'playing: %s\n' "$url"
|
||||
# shellcheck disable=2086
|
||||
exec mpv $MPV_OPTS "$url"
|
||||
fi
|
||||
fi
|
||||
break
|
||||
esac
|
||||
@@ -213,6 +248,7 @@ daemonize() {
|
||||
daemon_file=${XDG_CACHE_HOME:-~/.cache}/subs_daemon.cache
|
||||
if [ ! -f "$daemon_file" ] ; then
|
||||
cp -f "${SUBS_FILE:=~/files/subs.txt}" "$daemon_file"
|
||||
gen_links
|
||||
fi
|
||||
|
||||
while true ; do
|
||||
@@ -221,29 +257,42 @@ daemonize() {
|
||||
cp -f "${SUBS_FILE:=~/files/subs.txt}" "$daemon_file"
|
||||
fi
|
||||
update_subs
|
||||
interval=${SUBS_DAEMON_INTERVAL:-$(( 5 * 60 ))}
|
||||
printf 'Sleeping for %s seconds...\n' "$interval"
|
||||
sleep "$interval"
|
||||
printf 'Sleeping for %s seconds...\n' "$SUBS_DAEMON_INTERVAL"
|
||||
sleep "$SUBS_DAEMON_INTERVAL"
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
mkdir -p "$SUBS"
|
||||
|
||||
case ${1#-} in
|
||||
m)
|
||||
export MPV_OPTS="$MPV_OPTS --no-video"
|
||||
shift
|
||||
esac
|
||||
|
||||
case ${1#-} in
|
||||
h) usage ;;
|
||||
g) gen_links ;;
|
||||
u) update_subs ;;
|
||||
c) cat_subs ;;
|
||||
d) daemonize ;;
|
||||
*) get_sel
|
||||
esac
|
||||
if [ "$1" ] ; then
|
||||
case ${1#-} in
|
||||
g)
|
||||
gen_links
|
||||
;;
|
||||
u)
|
||||
update_subs
|
||||
;;
|
||||
c)
|
||||
cat_subs
|
||||
;;
|
||||
d)
|
||||
daemonize
|
||||
;;
|
||||
m)
|
||||
MPV_OPTS="$MPV_OPTS --no-video" \
|
||||
get_sel
|
||||
;;
|
||||
n)
|
||||
DONT_PLAY=true \
|
||||
get_sel
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
esac
|
||||
else
|
||||
get_sel
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user