diff --git a/ani-cli b/ani-cli index 212423d..d321543 100755 --- a/ani-cli +++ b/ani-cli @@ -482,6 +482,8 @@ parse_args() { scrape="file" play_dir="$OPTARG" [ "$play_dir" != "/" ] && play_dir="$(sed -E 's/\/$//' <<< "$play_dir")" # remove trailing slash... unless searching / for some reason + . "$CFG_DIR/lib/ani-cli/UI-play" || die "UI-play file not found" + lg "play UI loaded" ;; t) theme="$OPTARG" @@ -718,268 +720,11 @@ main() { fi } -# runs sql command on the history database -run_stmt() { - printf "%s\n" "$1" | sqlite3 -noheader -list "$HISTORY_DB" -} - -# Return number of matches for anime/episode in db -check_db() { - case "$1" in - directory) - stmt="SELECT COUNT(*) FROM file_history WHERE directory = '$2';" - ;; - file) - stmt="SELECT COUNT(*) FROM file_history WHERE directory = '$2' AND filename = '$3';" - ;; - search) - stmt="SELECT COUNT(*) FROM search_history WHERE anime_name = '$2';" - ;; - watch | sync) - stmt="SELECT COUNT(*) FROM watch_history WHERE anime_name = '$2' AND episode_number = '$3';" - ;; - anime) - stmt="SELECT COUNT(*) FROM anime WHERE anime_name = '$2';" - ;; - esac - res=$(run_stmt "$stmt") - return "$res" -} - -# return true (0) if $source_dt > $target_dt -check_date() { - source_dt="$1" - target_dt="$2" - if [[ "$source_dt" < "$target_dt" ]] || [[ "$source_dt" == "$target_dt" ]]; then - return 1 - else - return 0 - fi -} - -# updates search/watch date for passed in anime -update_date() { - datetime=$(date +'%Y-%m-%d %H:%M:%S') - stmt="" - case "$1" in - directory) - stmt="UPDATE file_history SET watch_date = '$datetime' WHERE directory = '$2' and filename = 'DIRECTORY';" - ;; - file) - stmt="UPDATE file_history SET watch_date = '$datetime' WHERE directory = '$2' and filename = '$3';" - ;; - search) - stmt="UPDATE search_history SET search_date = '$datetime' WHERE anime_name = '$2';" - ;; - sync) - temp_dt="${3// /:}" - [ -z "$temp_dt" ] && return 1 - hist_dt=$(run_stmt "SELECT watch_date FROM watch_history WHERE anime_name='$2' AND episode_number='$3';") - hist_dt="${hist_dt// /:}" - if ! check_date "$hist_dt" "$temp_dt"; then - lg "Passed in date is older or same than current date... doing nothing" - return 1 - fi - stmt="UPDATE watch_history SET watch_date = '$temp_dt' WHERE anime_name = '$2' AND episode_number = $3;" - ;; - watch) - stmt="UPDATE watch_history SET watch_date = '$datetime' WHERE anime_name = '$2' AND episode_number = $3;" - ;; - anime) - return - ;; - esac - lg "UPDATE STMT -> $stmt" - run_stmt "$stmt" -} - -# inserts into search/watch history db -# check the anime_name/id -insert_history() { - datetime=$(date +'%Y-%m-%d %H:%M:%S') - lg "Checking if ($*) exists in db" - if ! check_db "$@"; then - lg "Match found... Updating row in history db..." - update_date "$@" - res=$? - else - lg "Row not found in DB... inserting" - case "$1" in - directory) - stmt="INSERT INTO file_history(directory, filename, watch_date) VALUES('$2', 'DIRECTORY', '$datetime');" - ;; - file) - stmt="INSERT INTO file_history(directory, filename, watch_date) VALUES('$2', '$3', '$datetime');" - ;; - search) - stmt="INSERT INTO search_history(anime_name, search_date) VALUES('$2', '$datetime');" - ;; - watch) - stmt="INSERT INTO watch_history(anime_name, episode_number, watch_date) VALUES('$2', '$3', '$datetime');" - ;; - sync) - stmt="INSERT INTO watch_history(anime_name, episode_number, watch_date) VALUES('$2', '$3', '$4');" - ;; - anime) - stmt="INSERT INTO anime(anime_name, start_episode, end_episode, data_date) VALUES('$2', $3, $4, '$datetime');" - ;; - esac - lg "INSERT STATEMENT -> $stmt" - run_stmt "$stmt" - res=$? - fi - return $res -} - -sync_search_history() { - cnt=0 - errs=0 - while read -r line; do - anime_name=$(awk -F '|' '{print $2}' <<< "$line") - if sqlite3 -noheader "$HISTORY_DB" "SELECT COUNT(*) FROM search_history WHERE anime_name = '$anime_name'"; then - search_date=$(awk -F '|' '{print $3}' <<< "$line") - if ! sqlite3 "$HISTORY_DB" "INSERT INTO search_history(anime_name, search_date) VALUES('$anime_name', '$search_date')"; then - ((++errs)) - continue - fi - ((++cnt)) - fi - done < <(sqlite3 -list -noheader "$temp_db" "SELECT * FROM search_history") - lg "$cnt rows inserted into search_history table" - lg "$errs errors on insert" -} - -sync_watch_history() { - cnt=0 - errs=0 - while read -r line; do - anime_name="${line/ //}" - while read -r ep; do - episode_num=$(awk -F '|' '{print $1}' <<< "$ep") - watch_date=$(awk -F '|' '{print $NF}' <<< "$ep") - if ! insert_history "sync" "$anime_name" "$episode_num" "$watch_date"; then - ((++errs)) - continue - fi - ((++cnt)) - done < <(sqlite3 -list -noheader "$temp_db" "SELECT episode_number, watch_date FROM watch_history WHERE anime_name = '$anime_name'") - done < <(sqlite3 -list -noheader "$temp_db" "SELECT anime_name FROM watch_history") - lg "$cnt rows inserted into watch_history table" - lg "$errs rows skipped on insert" -} - -# opens the passed in file with $PLAYER_FN -play_file() { - lg "Checking if file is playable" - if [[ "$1" =~ (\.mp4|\.mkv|\.ts|\.webm)$ ]]; then - filename="${1##*/}" - directory="${1%/*}" - insert_history "file" "$directory" "$filename" - notification "Playing $1" - case "$PLAYER_FN" in - mpv) - nohup "$PLAYER_FN" --force-media-title="aniwrapper: play-from-file - $1" "$1" > /dev/null 2>&1 & - ;; - *) - nohup "$PLAYER_FN" "$1" > /dev/null 2>&1 & - ;; - esac - return $? - else - die "File: $1 is not playable... Quitting" - fi -} - -# gets the list of directories and playable files from the passed in directory -# sets the $watched list to the list of watched files -get_directory_data() { - search_dir="$1" - inputlist="" - watched="" - cnt=1 - [ "$search_dir" = "/" ] && cnt=0 # account for no ../ on / - for directory in "$1"/*; do - directory="${directory##*/}" - [ ! -d "$search_dir/$directory" ] && continue - [ -z "$inputlist" ] && inputlist="$directory" || inputlist="$inputlist|$directory" - if ! check_db "directory" "$search_dir/$directory"; then - lg "$search_dir/$directory opened before... adding $cnt to list" 1> /dev/stderr - [ -z "$watched" ] && watched="$cnt" || watched="$watched, $cnt" - fi - ((++cnt)) - done - shopt -s nullglob # set nullglob to avoid printing output if no files with extension exist - shopt -s nocaseglob # case insensitive globbing - for filename in "$search_dir"/*.{mp4,mkv,ts,mp3,webm}; do - filename="${filename##*/}" - [ -z "$inputlist" ] && inputlist="$filename" || inputlist="$inputlist|$filename" - if ! check_db "file" "$search_dir" "$filename"; then - lg "$filename watched before... adding $cnt to list" 1> /dev/stderr - [ -z "$watched" ] && watched="$cnt" || watched="$watched, $cnt" - fi - ((++cnt)) - done - shopt -u nullglob - shopt -u nocaseglob - if [[ -n "$inputlist" && "$search_dir" != / ]]; then - inputlist="../|$inputlist|Back|Quit" - elif [[ -z "$inputlist" && "$search_dir" != / ]]; then - inputlist="../|Back|Quit" - elif [[ "$search_dir" = / ]]; then - inputlist="$inputlist|Quit" - else - inputlist="Quit" - fi - lg "INPUT LIST: $inputlist" 1> /dev/stderr - lg "WATCHED LIST: $watched" 1> /dev/stderr -} - -# recursive function for finding path to video file given a starting directory -find_media() { - inp="$1" - [ -z "$inp" ] && die "No directory" - lg "BEGIN find_media() on $inp" 1> /dev/stderr - - # base case hit when a file is found - if [ -f "$inp" ]; then - printf "%s\n" "$inp" - return 0 - fi - - get_directory_data "$inp" - selection="$(rofi -dpi "$DPI" -dmenu -no-custom -async-pre-read 33 -config "$ROFI_CFG" \ - -l 15 -i -sep '|' -mesg "$(generate_span "Current directory: $inp")" -a "$watched" \ - -p "Enter selection" -window-title 'aniwrapper' <<< "$inputlist")" - [ -z "$selection" ] && return 1 - case "$selection" in - Back | ../) - dotdotslash="${inp%/*}" - [ -z "$dotdotslash" ] && dotdotslash="/" - insert_history "directory" "$dotdotslash" - find_media "$dotdotslash" - ;; - Quit) - return 1 - ;; - *) - if [ -d "$inp/$selection" ]; then - insert_history "directory" "$inp/$selection" - if [ "$inp" = "/" ]; then - find_media "/$selection" - else - find_media "$inp/$selection" - fi - else - find_media "$inp/$selection" - fi - ;; - esac -} - progress "Checking dependencies..." dep_ch "$PLAYER_FN" "curl" "sed" "grep" "sqlite3" "rofi" "git" "axel" "openssl" "ffmpeg" parse_args "$@" shift $((OPTIND - 1)) +lg "db library loaded" if ((IS_ROFI)); then . "$CFG_DIR/lib/ani-cli/UI-ROFI" || die "No UI file" lg "rofi UI loaded" @@ -987,4 +732,5 @@ else . "$CFG_DIR/lib/ani-cli/UI" || die "No UI file" lg "command-line UI loaded" fi +. "$CFG_DIR/lib/ani-cli/db" || die "Error loading db library" main "$@" diff --git a/lib/ani-cli/UI-play b/lib/ani-cli/UI-play new file mode 100644 index 0000000..ebc7ea3 --- /dev/null +++ b/lib/ani-cli/UI-play @@ -0,0 +1,121 @@ +# display a log message if verbose mode is enabled +lg() { + ((VERBOSE)) && printf "\033[1;35m%s\033[0m\n" "$*" >&2 +} + +# display error message and exit +die() { + ((!SILENT)) && printf "\033[1;31m%s\033[0m\n" "$*" >&2 + exit 1 +} + +# gets the list of directories and playable files from the passed in directory +# sets the $watched list to the list of watched files +get_directory_data() { + search_dir="$1" + inputlist="" + watched="" + cnt=1 + [ "$search_dir" = "/" ] && cnt=0 # account for no ../ on / + for directory in "$1"/*; do + directory="${directory##*/}" + [ ! -d "$search_dir/$directory" ] && continue + [ -z "$inputlist" ] && inputlist="$directory" || inputlist="$inputlist|$directory" + if ! check_db "directory" "$search_dir/$directory"; then + lg "$search_dir/$directory opened before... adding $cnt to list" 1> /dev/stderr + [ -z "$watched" ] && watched="$cnt" || watched="$watched, $cnt" + fi + ((++cnt)) + done + shopt -s nullglob # set nullglob to avoid printing output if no files with extension exist + shopt -s nocaseglob # case insensitive globbing + for filename in "$search_dir"/*.{mp4,mkv,ts,mp3,webm}; do + filename="${filename##*/}" + [ -z "$inputlist" ] && inputlist="$filename" || inputlist="$inputlist|$filename" + if ! check_db "file" "$search_dir" "$filename"; then + lg "$filename watched before... adding $cnt to list" 1> /dev/stderr + [ -z "$watched" ] && watched="$cnt" || watched="$watched, $cnt" + fi + ((++cnt)) + done + shopt -u nullglob + shopt -u nocaseglob + if [[ -n "$inputlist" && "$search_dir" != / ]]; then + inputlist="../|$inputlist|Back|Quit" + elif [[ -z "$inputlist" && "$search_dir" != / ]]; then + inputlist="../|Back|Quit" + elif [[ "$search_dir" = / ]]; then + inputlist="$inputlist|Quit" + else + inputlist="Quit" + fi + lg "INPUT LIST: $inputlist" 1> /dev/stderr + lg "WATCHED LIST: $watched" 1> /dev/stderr +} + +# recursive function for finding path to video file given a starting directory +find_media() { + inp="$1" + [ -z "$inp" ] && die "No directory" + lg "BEGIN find_media() on $inp" 1> /dev/stderr + + # base case hit when a file is found + if [ -f "$inp" ]; then + printf "%s\n" "$inp" + return 0 + fi + + get_directory_data "$inp" + selection="$(rofi -dpi "$DPI" -dmenu -no-custom -async-pre-read 33 -config "$ROFI_CFG" \ + -l 15 -i -sep '|' -mesg "$(generate_span "Current directory: $inp")" -a "$watched" \ + -p "Enter selection" -window-title 'aniwrapper' <<< "$inputlist")" + [ -z "$selection" ] && return 1 + case "$selection" in + Back | ../) + dotdotslash="${inp%/*}" + [ -z "$dotdotslash" ] && dotdotslash="/" + insert_history "directory" "$dotdotslash" + find_media "$dotdotslash" + ;; + Quit) + return 1 + ;; + *) + if [ -d "$inp/$selection" ]; then + insert_history "directory" "$inp/$selection" + if [ "$inp" = "/" ]; then + find_media "/$selection" + else + find_media "$inp/$selection" + fi + else + find_media "$inp/$selection" + fi + ;; + esac +} + +# opens the passed in file with $PLAYER_FN +play_file() { + lg "Checking if file is playable" + if [[ "$1" =~ (\.mp4|\.mkv|\.ts|\.webm)$ ]]; then + filename="${1##*/}" + directory="${1%/*}" + insert_history "file" "$directory" "$filename" + notification "Playing $1" + case "$PLAYER_FN" in + mpv) + nohup "$PLAYER_FN" --force-media-title="aniwrapper: play-from-file - $1" "$1" > /dev/null 2>&1 & + ;; + *) + nohup "$PLAYER_FN" "$1" > /dev/null 2>&1 & + ;; + esac + return $? + else + die "File: $1 is not playable... Quitting" + fi +} + + +# vim: ft=sh diff --git a/lib/ani-cli/db b/lib/ani-cli/db new file mode 100644 index 0000000..fd55220 --- /dev/null +++ b/lib/ani-cli/db @@ -0,0 +1,151 @@ +# runs sql command on the history database +run_stmt() { + printf "%s\n" "$1" | sqlite3 -noheader -list "$HISTORY_DB" +} + +# Return number of matches for anime/episode in db +check_db() { + case "$1" in + directory) + stmt="SELECT COUNT(*) FROM file_history WHERE directory = '$2';" + ;; + file) + stmt="SELECT COUNT(*) FROM file_history WHERE directory = '$2' AND filename = '$3';" + ;; + search) + stmt="SELECT COUNT(*) FROM search_history WHERE anime_name = '$2';" + ;; + watch | sync) + stmt="SELECT COUNT(*) FROM watch_history WHERE anime_name = '$2' AND episode_number = '$3';" + ;; + anime) + stmt="SELECT COUNT(*) FROM anime WHERE anime_name = '$2';" + ;; + esac + res=$(run_stmt "$stmt") + return "$res" +} + +# return true (0) if $source_dt > $target_dt +check_date() { + source_dt="$1" + target_dt="$2" + if [[ "$source_dt" < "$target_dt" ]] || [[ "$source_dt" == "$target_dt" ]]; then + return 1 + else + return 0 + fi +} + +# updates search/watch date for passed in anime +update_date() { + datetime=$(date +'%Y-%m-%d %H:%M:%S') + stmt="" + case "$1" in + directory) + stmt="UPDATE file_history SET watch_date = '$datetime' WHERE directory = '$2' and filename = 'DIRECTORY';" + ;; + file) + stmt="UPDATE file_history SET watch_date = '$datetime' WHERE directory = '$2' and filename = '$3';" + ;; + search) + stmt="UPDATE search_history SET search_date = '$datetime' WHERE anime_name = '$2';" + ;; + sync) + temp_dt="${3// /:}" + [ -z "$temp_dt" ] && return 1 + hist_dt=$(run_stmt "SELECT watch_date FROM watch_history WHERE anime_name='$2' AND episode_number='$3';") + hist_dt="${hist_dt// /:}" + if ! check_date "$hist_dt" "$temp_dt"; then + lg "Passed in date is older or same than current date... doing nothing" + return 1 + fi + stmt="UPDATE watch_history SET watch_date = '$temp_dt' WHERE anime_name = '$2' AND episode_number = $3;" + ;; + watch) + stmt="UPDATE watch_history SET watch_date = '$datetime' WHERE anime_name = '$2' AND episode_number = $3;" + ;; + anime) + return + ;; + esac + lg "UPDATE STMT -> $stmt" + run_stmt "$stmt" +} + +# inserts into search/watch history db +# check the anime_name/id +insert_history() { + datetime=$(date +'%Y-%m-%d %H:%M:%S') + lg "Checking if ($*) exists in db" + if ! check_db "$@"; then + lg "Match found... Updating row in history db..." + update_date "$@" + res=$? + else + lg "Row not found in DB... inserting" + case "$1" in + directory) + stmt="INSERT INTO file_history(directory, filename, watch_date) VALUES('$2', 'DIRECTORY', '$datetime');" + ;; + file) + stmt="INSERT INTO file_history(directory, filename, watch_date) VALUES('$2', '$3', '$datetime');" + ;; + search) + stmt="INSERT INTO search_history(anime_name, search_date) VALUES('$2', '$datetime');" + ;; + watch) + stmt="INSERT INTO watch_history(anime_name, episode_number, watch_date) VALUES('$2', '$3', '$datetime');" + ;; + sync) + stmt="INSERT INTO watch_history(anime_name, episode_number, watch_date) VALUES('$2', '$3', '$4');" + ;; + anime) + stmt="INSERT INTO anime(anime_name, start_episode, end_episode, data_date) VALUES('$2', $3, $4, '$datetime');" + ;; + esac + lg "INSERT STATEMENT -> $stmt" + run_stmt "$stmt" + res=$? + fi + return $res +} + +sync_search_history() { + cnt=0 + errs=0 + while read -r line; do + anime_name=$(awk -F '|' '{print $2}' <<< "$line") + if sqlite3 -noheader "$HISTORY_DB" "SELECT COUNT(*) FROM search_history WHERE anime_name = '$anime_name'"; then + search_date=$(awk -F '|' '{print $3}' <<< "$line") + if ! sqlite3 "$HISTORY_DB" "INSERT INTO search_history(anime_name, search_date) VALUES('$anime_name', '$search_date')"; then + ((++errs)) + continue + fi + ((++cnt)) + fi + done < <(sqlite3 -list -noheader "$temp_db" "SELECT * FROM search_history") + lg "$cnt rows inserted into search_history table" + lg "$errs errors on insert" +} + +sync_watch_history() { + cnt=0 + errs=0 + while read -r line; do + anime_name="${line/ //}" + while read -r ep; do + episode_num=$(awk -F '|' '{print $1}' <<< "$ep") + watch_date=$(awk -F '|' '{print $NF}' <<< "$ep") + if ! insert_history "sync" "$anime_name" "$episode_num" "$watch_date"; then + ((++errs)) + continue + fi + ((++cnt)) + done < <(sqlite3 -list -noheader "$temp_db" "SELECT episode_number, watch_date FROM watch_history WHERE anime_name = '$anime_name'") + done < <(sqlite3 -list -noheader "$temp_db" "SELECT anime_name FROM watch_history") + lg "$cnt rows inserted into watch_history table" + lg "$errs rows skipped on insert" +} + +# vim: ft=sh