aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--input/strangenewworlds.conf.example12
-rw-r--r--jellystack-autocomplete.bash (renamed from autocomplete-rescan.bash)17
-rw-r--r--jellystack_lib.py12
-rwxr-xr-xshow-manager.sh103
5 files changed, 144 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 5fb4e00..f390e0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
__pycache__/
play.py
+.*.swp
+*.conf
diff --git a/input/strangenewworlds.conf.example b/input/strangenewworlds.conf.example
new file mode 100644
index 0000000..289e7a5
--- /dev/null
+++ b/input/strangenewworlds.conf.example
@@ -0,0 +1,12 @@
+# Where all the episode mkv files are
+SOURCE_DIR="/mnt/public/Video/off.movies/Star Trek - Strange New Worlds (2021)"
+# Where they should be placed for Jellyfin to pick them up
+LINK_DIR="/mnt/public/Video/TV/Star Trek - Strange New Worlds (2021)"
+# Symlink prefix, so probably the relative path from LINK_DIR to SOURCE_DIR
+LINK_PREFIX="../../../off.movies/Star Trek - Strange New Worlds (2021)"
+# Jellyfin library name
+LIBRARY="TV"
+# Jellyfin show name
+SHOW="Star Trek: Strange New Worlds"
+# Show directory name. Not necessarily the same as SHOW.
+DIR="Star Trek - Strange New Worlds (2021)"
diff --git a/autocomplete-rescan.bash b/jellystack-autocomplete.bash
index 06af729..55ffad4 100644
--- a/autocomplete-rescan.bash
+++ b/jellystack-autocomplete.bash
@@ -1,5 +1,5 @@
#!/bin/bash
-# File: autocomplete-rescan.bash
+# File: jellystack-autocomplete.bash
# Location: /mnt/public/Support/Programs/jellyfin/scripts/
# Author: bgstack15, pawamoy
# Startdate: 2024-01-28-1 21:40
@@ -72,3 +72,18 @@ _complete_specific_path() {
complete -F _complete_specific_path rescan-library
alias rescan-library="/mnt/public/Support/Programs/jellyfin/scripts/rescan-library.sh"
+
+_show_manager_confs() {
+ # reference: vm4:/etc/bash_completion.d/docker-nfs-check
+ local cur prev words cword;
+ _init_completion || return
+ _tmpfile1="$( mktemp )"
+ # populate list
+ find /mnt/public/Support/Programs/jellyfin/scripts/input -mindepth 1 -maxdepth 1 ! -type d -name '*.conf' -printf '%P\n' | sed -r -e 's/\.conf$//;' > "${_tmpfile1}"
+ COMPREPLY=($( compgen -W "$( cat ${_tmpfile1} )" -- "$cur" | sed -r -e "/^${prev}/d;" ))
+ command rm -rf "${_tmpfile1:-NOTHINGTODEL}" 1>/dev/null 2>&1
+ return 0
+} &&
+complete -F _show_manager_confs manage-show
+. /mnt/public/Support/Programs/jellyfin/scripts/show-manager.sh
+alias manage-show="manage_show"
diff --git a/jellystack_lib.py b/jellystack_lib.py
index 5a96e26..5c5c132 100644
--- a/jellystack_lib.py
+++ b/jellystack_lib.py
@@ -83,6 +83,7 @@ def is_like_id(input_id):
def watched_episodes_for_show(client, library_id_or_name, show_id_or_name, season_id = -1, verbose = False):
"""
Given the show_id_or_name (show_id from the user's view in jellyfin, or exact name), return a list of the episode count watched and total episode count. If season_id is not defined (-1), then do it for all seasons. The episode-watched number is dependent on who logged in to jellyfin.
+ Season_id may also be string "sum" which will just produce a single 100/110 fraction in the output string.
If you cannot find the exact name to use, pass verbose=True to see what it is comparing against.
WARNING: Seasons are zero-indexed, but specials (if present in your library) are number zero!
Improve: research if admin user can look at other users' views.
@@ -128,7 +129,7 @@ def watched_episodes_for_show(client, library_id_or_name, show_id_or_name, seaso
# get season count
seasons = client.jellyfin.get_seasons(view_series_id)
season_count = seasons["TotalRecordCount"]
- if season_id != -1:
+ if season_id != -1 and season_id.isdigit():
# a specific season
return _watched_episodes_for_season(client, seasons["Items"][season_id]["Id"], season_id)
else:
@@ -138,6 +139,15 @@ def watched_episodes_for_show(client, library_id_or_name, show_id_or_name, seaso
while x < season_count:
response.append(_watched_episodes_for_season(client, seasons["Items"][x]["Id"], x))
x += 1
+ if season_id == "sum":
+ sumx = 0
+ sumy = 0
+ for i in response:
+ x, y = i.split("/")
+ sumx += int(x)
+ sumy += int(y)
+ return f"{sumx}/{sumy}"
+ else:
return response
def _watched_episodes_for_season(client, view_season_id, season_index):
diff --git a/show-manager.sh b/show-manager.sh
new file mode 100755
index 0000000..4c8c4bf
--- /dev/null
+++ b/show-manager.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+# File: show-manager.sh
+# Location: /mnt/public/Support/Programs/jellyfin/scripts/
+# Author: bgstack15
+# Startdate: 2024-02-18-1 17:24
+# SPDX-License-Identifier: GPL-3.0-only
+# Title: Slowly add new episodes of a completed show to jellyfin
+# Purpose: Check jellyfin for if the last season of a given show is greater than (x-2)/x episodes, and if so, then add that many new episodes.
+# History:
+# Usage:
+# . ./jellystack-autocomplete.bash ; manage_show stsnw
+# Improve:
+# hook in to jellyfin deeper, by checking file paths of the episodes where watched=True, to know which episodes to skip trying to add
+# learn how to completely clear the "watched" information about the show in jellyfin.
+# Documentation:
+# Assumptions:
+# 1. media files are sorted in "Season 01/" type directories.
+# 2. Media files are named "*s01e07 *" style which will be sorted alphabetically in episode number order.
+# 3. watched episodes are in exact order!
+# 4. input files are all mkv (this is to simplify filtering out non-episode files like images; it could be made more complex as needed)
+# Dependencies:
+# jellystack_lib with watched_episodes_for_show()
+
+# flow:
+# get episodes-watched for last season of show (value is, e.g., "8/10"
+
+
+# depends on content being in "Season 01/" directories.
+get_episodes_watched_count() {
+ # input env vars: library, show, DEBUG
+ # output: prints watched= and total= numbers
+ # usage: $( library="TV" show="Star Trek: Strange New Worlds" get_episodes_watched_count )
+ _pyverbose=False
+ test -n "${DEBUG}" && _pyverbose=True
+ cd /mnt/public/Support/Programs/jellyfin/scripts
+ . ~/.config/jellystack.viewing.user
+ {
+ python3 <<-EOF
+import jellystack_lib
+a = jellystack_lib.get_authenticated_client(url="${server}",username="${username}",password="${password}")
+b = jellystack_lib.watched_episodes_for_show(a,"${library}","${show}","sum",${_pyverbose})
+c = b.split("/")
+print(f"watched={c[0]}")
+print(f"total={c[1]}")
+EOF
+ }
+}
+
+symlink_file() {
+ # input vars: infile SOURCE_DIR LINK_DIR LINK_PREFIX VERBOSE APPLY
+ # reference: printf '%s\n' *s01e0* | while read line ; do ln -sf "../../../off.movies/Star Trek - Strange New Worlds (2021/Season 01/${line}" "/mnt/public/Video/TV/Star Trek - Strange New Worlds (2021/Season 01/" ; done
+ # We now calculate season number based on file name
+ #season_num_str="$( \printf '%02d' "${season_num}" )"
+ base="$( basename "${infile}" )"
+ season_num_str="$( \printf '%02d' "$( echo "${base}" | grep -oE '\<s[0-9]+e[0-9]+' | awk -F'e' '{print $1}' | tr -dc '0-9' )" )"
+ test -n "${VERBOSE}" && echo ln -s "${LINK_PREFIX}/Season ${season_num_str}/${base}" "${LINK_DIR}/Season ${season_num_str}/"
+ test -n "${APPLY}" && ln -s "${LINK_PREFIX}/Season ${season_num_str}/${base}" "${LINK_DIR}/Season ${season_num_str}/"
+}
+
+list_sorted_episode_files() {
+ # input env vars: SOURCE_DIR
+ # if changing from %P, probably do a cd in a sub-shell.
+ find "${SOURCE_DIR}" -name '*mkv' -iregex '.*\<s[0-9]+e[0-9]+\>.*' -printf '%P\n' | sort -n
+}
+
+# Logic flow:
+# diff=total-watched
+# if diff < 2,
+# find the smallest-number episode files and add them in.
+manage_show() {
+ # input vars: MAX_NEW_EPISODES SOURCE_DIR VERBOSE LIBRARY SHOW
+ # You may also run: manage_show "TV/Star Trek: Strange New Worlds"
+ conf="${1}"
+ test -f "/mnt/public/Support/Programs/jellyfin/scripts/input/${conf}.conf" && . "/mnt/public/Support/Programs/jellyfin/scripts/input/${conf}.conf"
+ # Not necessary with the conf file method
+ #test -z "${SHOW}" && test -z "${LIBRARY}" && {
+ # LIBRARY="$( echo "${1}" | awk -F'/' '{print $1}' )"
+ # SHOW="$( echo "${1}" | awk -F'/' '{print $2}' )"
+ #}
+ test -z "${MAX_NEW_EPISODES}" && MAX_NEW_EPISODES=2
+ # this next function sets vars: watched, total
+ eval $( library="${LIBRARY}" show="${SHOW}" get_episodes_watched_count )
+ # hardcode these to test max_new_episodes
+ #watched=6 total=8
+ diff=$((total-watched))
+ test -n "${VERBOSE}" && echo "Got watched=${watched} total=${total} diff=${diff}" 1>&2
+ if test ${diff:-0} -lt ${MAX_NEW_EPISODES} ;
+ then
+ need=$((MAX_NEW_EPISODES-diff))
+ echo "Must prepare next ${need} episodes." 1>&2
+ w1=$((watched+1))
+ end=$((watched+need))
+ list_sorted_episode_files | sed -n -r -e "${w1},${end}p" | while read infile ;
+ do
+ # VERBOSE and APPLY are used in this function:
+ infile="${infile}" symlink_file
+ done
+ fi
+}
+
+# Before the config file redesign, use one of these:
+# These will still get "/Season 01" prepended to the file basename:
+# SOURCE_DIR="/mnt/public/Video/off.movies/Star Trek - Strange New Worlds (2021)" LINK_DIR="/mnt/public/Video/TV/Star Trek - Strange New Worlds (2021)" LINK_PREFIX="../../../off.movies/Star Trek - Strange New Worlds (2021)" LIBRARY="TV" SHOW="Star Trek - Strange New Worlds (2021)" DIR="${SHOW}" manage_show
bgstack15