diff --git a/Contents/Code/__init__.py b/Contents/Code/__init__.py index 0ec9426d..30be7a3c 100644 --- a/Contents/Code/__init__.py +++ b/Contents/Code/__init__.py @@ -29,12 +29,12 @@ # local imports if sys.version_info.major < 3: from default_prefs import default_prefs - from helpers import issue_url_games, issue_url_movies + from constants import issue_url_games, issue_url_movies from plex_api_helper import add_themes, get_plex_item, plex_listener from youtube_dl_helper import process_youtube else: from .default_prefs import default_prefs - from .helpers import issue_url_games, issue_url_movies + from .constants import issue_url_games, issue_url_movies from .plex_api_helper import add_themes, get_plex_item, plex_listener from .youtube_dl_helper import process_youtube diff --git a/Contents/Code/helpers.py b/Contents/Code/constants.py similarity index 100% rename from Contents/Code/helpers.py rename to Contents/Code/constants.py diff --git a/Contents/Code/default_prefs.py b/Contents/Code/default_prefs.py index c3f01557..33ae7200 100644 --- a/Contents/Code/default_prefs.py +++ b/Contents/Code/default_prefs.py @@ -1,5 +1,6 @@ default_prefs = dict( bool_prefer_mp4a_codec='True', + bool_remove_unused_theme_songs='True', int_plexapi_plexapi_timeout='180', int_plexapi_upload_retries_max='3', int_plexapi_upload_threads='3', diff --git a/Contents/Code/plex_api_helper.py b/Contents/Code/plex_api_helper.py index 1cac76da..2108fb8b 100644 --- a/Contents/Code/plex_api_helper.py +++ b/Contents/Code/plex_api_helper.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- # standard imports +import hashlib import os +import shutil import sys import time import threading @@ -12,6 +14,7 @@ except ImportError: pass else: # the code is running outside of Plex + from plexhints.core_kit import Core # core kit from plexhints.log_kit import Log # log kit from plexhints.parse_kit import JSON # parse kit from plexhints.prefs_kit import Prefs # prefs kit @@ -29,10 +32,10 @@ # local imports if sys.version_info.major < 3: - from helpers import guid_map, issue_url_movies + from constants import guid_map, issue_url_movies from youtube_dl_helper import process_youtube else: - from .helpers import guid_map, issue_url_movies + from .constants import guid_map, issue_url_movies from .youtube_dl_helper import process_youtube plex = None @@ -41,6 +44,10 @@ q = queue.Queue() processing_completed = [] +# constants +app_support_directory = Core.app_support_path +metadata_movie_directory = os.path.join(app_support_directory, 'Metadata', 'Movies') + def setup_plexapi(): """ @@ -116,6 +123,10 @@ def add_themes(rating_key, theme_files=None, theme_urls=None): if plex: plex_item = plex.fetchItem(ekey=int(rating_key)) # must be an int or weird things happen + # remove existing theme uploads + if Prefs['bool_remove_unused_theme_songs']: + remove_uploaded_themes(plex_item=plex_item) + if theme_files: for theme_file in theme_files: Log.Info('Attempting to upload theme file: %s' % theme_file) @@ -130,6 +141,55 @@ def add_themes(rating_key, theme_files=None, theme_urls=None): return uploaded +def remove_uploaded_themes(plex_item): + # type: (any) -> None + """ + Remove themes for the specified item. + + Deletes the themes upload directory for the item specified by the ``plex_item``. + + Parameters + ---------- + plex_item : any + The item to remove the themes from. + + Returns + ------- + bool + True if the themes were removed successfully, False otherwise. + + Examples + -------- + >>> remove_uploaded_themes(plex_item=...) + ... + """ + guid = plex_item.guid + full_hash = hashlib.sha1(guid).hexdigest() + theme_upload_path = os.path.join( + metadata_movie_directory, full_hash[0], full_hash[1:] + '.bundle', 'Uploads', 'themes') + if os.path.isdir(theme_upload_path): + shutil.rmtree(path=theme_upload_path, ignore_errors=True, onerror=remove_uploaded_themes_error_handler) + + +def remove_uploaded_themes_error_handler(func, path, exc_info): + # type: (any, any, any) -> None + """ + Error handler for removing themes. + + Handles errors that occur when removing themes using ``shutil``. + + Parameters + ---------- + func : any + The function that caused the error. + path : str + The path that caused the error. + exc_info : any + The exception information. + """ + Log.Error('Error removing themes with function: %s, path: %s, exception info: %s' % (func, path, exc_info)) + + def upload_theme(plex_item, filepath=None, url=None): # type: (any, Optional[str], Optional[str]) -> bool """ diff --git a/Contents/DefaultPrefs.json b/Contents/DefaultPrefs.json index c23672b4..8ac594af 100644 --- a/Contents/DefaultPrefs.json +++ b/Contents/DefaultPrefs.json @@ -6,6 +6,13 @@ "default": "True", "secure": "false" }, + { + "id": "bool_remove_unused_theme_songs", + "type": "bool", + "label": "Remove unused theme songs (frees up space in your Plex metadata directory)", + "default": "True", + "secure": "false" + }, { "id": "int_plexapi_plexapi_timeout", "type": "text", diff --git a/docs/source/about/usage.rst b/docs/source/about/usage.rst index 730437a1..70b780d8 100644 --- a/docs/source/about/usage.rst +++ b/docs/source/about/usage.rst @@ -37,6 +37,16 @@ Description Default True +Remove unused theme songs +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Description + When Themerr-plex uploads a theme song to the Plex server, it will remove any existing theme songs for the same + movie. With this setting enabled, Themerr-plex can free up space in Plex's metadata directory. + +Default + True + PlexAPI Timeout ^^^^^^^^^^^^^^^