aboutsummaryrefslogtreecommitdiff
path: root/jellystack.py
blob: bb9e2ac2ebb0b1095e17b5be6c52812544ec39fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python3
# File: jellystack.py
# Location: /mnt/public/Support/Programs/jellyfin/scripts/
# Author: bgstack15
# Startdate: 2024-01-29-2 09:25
# SPDX-License-Identifier: GPL-3.0-only
# Title: jellyfin stackrpms cli frontend
# Project: jellystack
# Purpose: List and rescan individual libraries in jellyfin easier than navigating web ui
# History:
# Usage:
#    from rescan-library.sh
# Reference:
#    https://stackoverflow.com/questions/8258145/in-python-check-if-file-modification-time-is-older-than-a-specific-datetime
# Improve:
# Dependencies:
#    jellystack_lib.py, python>=3.4
# Documentation:
import jellystack_lib as js, os, argparse, shutil, sys
from datetime import datetime, timedelta
from pathlib import Path # python>=3.4
js_debug = False

# Ref: https://stackoverflow.com/questions/8258145/in-python-check-if-file-modification-time-is-older-than-a-specific-datetime
def is_file_older_than (file, delta):
   cutoff = datetime.utcnow() - delta
   mtime = datetime.utcfromtimestamp(os.path.getmtime(file))
   if mtime < cutoff:
      return True
   return False

def check_cached_library_names(clear_cache = False):
   """
   If cache is absent or older than 23 hours, generate new cache of library names
   """
   cache_dir = os.path.join(os.path.expanduser("~"),".cache","jellystack")
   _clear_cache = clear_cache
   _cache_is_empty = True
   try:
      os.mkdir(cache_dir)
   except:
      pass
   for thisdir, subdir, files in os.walk(cache_dir):
      for tf in files:
         if is_file_older_than(os.path.join(thisdir,tf), timedelta(hours=23)):
            _clear_cache = True
            if js_debug:
               print(f"found too-old file {tf}, will clear the cache.",file=sys.stderr)
            break
   if _clear_cache:
      shutil.rmtree(cache_dir)
      if js_debug:
         print(f"Clearing cache...",file=sys.stderr)
   try:
      os.mkdir(cache_dir)
   except:
      pass
   # populate cache
   try:
      for thisdir, subdir, files in os.walk(cache_dir):
         if len(files) > 0:
            _cache_is_empty = False
   except:
      pass
   if _cache_is_empty:
      if js_debug:
         print(f"Generating cache...",file=sys.stderr)
      client = get_client()
      lib_names = js.get_library_names_only(js.get_media_folders(client))
      #print(lib_names)
      for name in lib_names:
         Path(os.path.join(cache_dir,name)).touch()
   # and now, list all the files in that path
   for thisdir, subdir, files in os.walk(cache_dir):
      for tf in files:
         print(tf)

def get_client():
   try:
      client = js.get_authenticated_client(server,user,pw)
   except:
      raise Exception("Check password or url?")
   return client

if "__main__" == __name__:
   server = os.environ.get("server","http://vm4:8096")
   user = os.environ.get("username","admin")
   pw = os.environ.get("password","none")
   pwfile = os.path.join(os.path.expanduser("~"),".jellyfin.password")
   if pw == "none":
      #raise Exception(f"Set env var \"password\" and try again.")
      if os.path.exists(pwfile):
         try:
            with open(pwfile,"r") as o:
               pw = o.read().strip()
               # the strip helps remove the newline that most people stick at the end of passwords in a passwordfile, and I seriously doubt the newline is part of the password.
         except:
            pass
   parser = argparse.ArgumentParser()
   parser.add_argument("--autocomplete",action="store_true",help="print library names, using the cache.")
   parser.add_argument("--clear-cache",action="store_true",help="print library names, using the cache.")
   parser.add_argument("--library",help="Rescan this library by name or uuid.")
   args = parser.parse_args()
   if type(args.library) == str:
      args.library = args.library.rstrip("/") # to help with the bash autocomplete which always wants to add a trailing slash, if PWD has a directory named exactly the same as the library. I cannot find a way around it.
   #print(args,file=sys.stderr)
   if args.autocomplete:
      check_cached_library_names(args.clear_cache)
   else:
      client = get_client()
      folders = js.get_media_folders(client)
      if args.library is not None:
         js.refresh_library(args.library, folders, client)
      else:
         print("Use --autocomplete, or one of these for --library:")
         js.libraries_to_csv(folders)
bgstack15