#!/bin/sh dd="${XDG_CACHE_HOME}/ychannels" yd="${HOME}/ytvideos" cl="${XDG_DATA_HOME}/categories" chl="${XDG_DATA_HOME}/channels" cld="${XDG_DATA_HOME}/clists" mkdir -p "${dd}" "${yd}" "${cld}" pr() { printf "%s\n" "${@}"; } d() { i="$(cat)" l="$(pr "${i}" | wc -l)" [ "${l}" -gt "21" ] && l="21" [ "${i}" ] || l="0" pr "${i}" | dmenu -i -l "${l}" -p "${1}" } n() { notify-send -i "${XDG_CONFIG_HOME}/dunst/yt.png" "${1}"; } sv() { df="${1}" so="${2}" case "${so}" in "@@sv") sort -nr -t" " -k3 "${df}" ;; "@@sd") sort -nr -t" " -k4 "${df}" ;; *) sort -nr -t" " -k5 "${df}" ;; esac | cut -f1 } gv() { cn="${1}" so="${2}" df="${dd}/${cn}.tsv" sv "${df}" "${so}" } vu() { cn="${1}" vt="${2}" df="${dd}/${cn}.tsv" grep -F "${vt}" "${df}" | cut -f2 } ma() { pr "WATCH" "DOWNLOAD" "SEND TO A LIST" | d "Actions" } ca() { lsts="$(pr "${cld}"/* | sed 's|.*/||')" [ "${lsts}" = "*" ] && lsts="" pr "${lsts}" "## CREATE LIST ##" "## DELETE LIST ##" | d "Lists" } lva() { pr "WATCH" "DOWNLOAD" "DELETE" | d "Actions" } atl() { vt="${1}" cn="${2}" ln="${3}" pr "${cn}: ${vt}" >> "${cld}/${ln}" } clm() { while true; do lst="$(ca)" case "${lst}" in "## CREATE LIST ##") nlst="$(pr | d "Name")" [ "${nlst}" ] && touch "${cld}/${nlst}" ;; "## DELETE LIST ##") dlst="$(find "${cld}" -mindepth "1" -exec basename {} \; | d "Delete List")" [ "${dlst}" ] && rm -f "${cld}/${dlst}" ;; "") return ;; *) cvm "${lst}" ;; esac done } cvm() { ln="${1}" while true; do vi=$(d "Videos" < "${cld}/${ln}") [ "${vi}" ] || return cn="${vi%%: *}" vt="${vi##*: }" clvm "${vt}" "${cn}" "${ln}" done } clvm() { vt="${1}" cn="${2}" ln="${3}" ac="$(lva)" case "${ac}" in "WATCH") vp "${ac}" "${vt}" "${cn}" ;; "DOWNLOAD") vp "${ac}" "${vt}" "${cn}" && n "Download finished" ;; "DELETE") sed -i "/${vt}/d" "${cld}/${ln}" ;; *) return ;; esac } vp() { ac="${1}" vt="${2}" cn="${3}" vu="$(vu "${cn}" "${vt}")" case "${ac}" in "WATCH") mpv "${vu}" ;; "DOWNLOAD") cdd="${yd}/${cn}" mkdir -p "${cdd}" yt-dlp -o "${cdd}/%(title)s.%(ext)s" "${vu}" n "Download finished" ;; esac } gav() { so="${1}" avf="${dd}/all_videos.tsv" sv "${avf}" "${so}" } bac() { while vt="$(gav | d "Videos | Sort: @@s{v,d}")"; do [ "${vt}" ] || break [ "${vt}" = "@@sv" ] || [ "${vt}" = "@@sd" ] && { vt=$(gav "${vt}" | d "Videos") [ "${vt}" ] || continue } grep -lF "${vt}" "${dd}"/*.tsv | head -n "1" | while read -r "vf"; do vam "${vt}" "$(basename "${vf}" .tsv)" break done done } cm() { while true; do c="$(cut -d= -f1 "${cl}" | d "Categories")" [ "${c}" ] || return chm "${c}" done } chm() { c="${1}" IFS="|" ch="$(sed -n "s/^${c}=\(.*\)$/\1/p" "${cl}")" set -- ${ch} while true; do cn="$(pr "${@}" | d "Channels")" [ "${cn}" ] || return vm "${cn}" done } vm() { cn="${1}" while true; do vt=$(gv "${cn}" | d "Videos") [ "${vt}" ] || return [ "${vt}" = "@@sv" ] || [ "${vt}" = "@@sd" ] && { so="${vt}" vt="$(gv "${cn}" "${so}" | d "Videos")" } vam "${vt}" "${cn}" done } vam() { vt="${1}" cn="${2}" while [ "${vt}" ] && [ "${vt}" != "@@sv" ] && [ "${vt}" != "@@sd" ]; do ac="$(ma)" case "${ac}" in "WATCH") vp "${ac}" "${vt}" "${cn}" ;; "DOWNLOAD") vp "${ac}" "${vt}" "${cn}" && n "Download finished" ;; "SEND TO A LIST") ln="$(find "${cld}" -mindepth "1" -exec basename {} \; | d "Lists")" [ "${ln}" ] && atl "${vt}" "${cn}" "${ln}" && n "${vt} > list: ${ln}" ;; *) return ;; esac done } mm() { pr " ## ALL CHANNELS ##" " ## CATEGORIES ##" " ## CUSTOM LISTS ##" \ "$(cut -d= -f1 "${chl}")" | d "YouTube" } while true; do mc="$(mm)" case "${mc}" in " ## ALL CHANNELS ##") bac ;; " ## CATEGORIES ##") cm ;; " ## CUSTOM LISTS ##") clm ;; "") exit ;; *) vm "${mc}" ;; esac done