From 59dbb8985ac610b0573ad6608e3073bb49a7c61a Mon Sep 17 00:00:00 2001 From: Maveno Date: Sun, 17 Nov 2024 16:50:17 +0100 Subject: [PATCH] =?UTF-8?q?#389=20Templating=20f=C3=BCr=20Ausgabe-Dateinam?= =?UTF-8?q?en?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 1 + src/ffx/configuration_controller.py | 2 + src/ffx/constants.py | 2 + src/ffx/ffx.py | 6 +- src/ffx/helper.py | 89 +++++++++++++++++++++++++++++ src/ffx/media_descriptor.py | 6 +- src/ffx/show_descriptor.py | 3 +- src/ffx/test/scenario_4.py | 7 ++- src/ffx/tmdb_controller.py | 66 ++------------------- src/ffx/track_descriptor.py | 3 +- 10 files changed, 117 insertions(+), 68 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 577d963..311b4cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ version = "0.2.2" license = {file = "LICENSE.md"} dependencies = [ "requests", + "jinja2", "click", "textual", "sqlalchemy", diff --git a/src/ffx/configuration_controller.py b/src/ffx/configuration_controller.py index 8fb5561..74cc960 100644 --- a/src/ffx/configuration_controller.py +++ b/src/ffx/configuration_controller.py @@ -8,6 +8,8 @@ class ConfigurationController(): DATABASE_PATH_CONFIG_KEY = 'databasePath' LOG_DIRECTORY_CONFIG_KEY = 'logDirectory' + OUTPUT_FILENAME_TEMPLATE_KEY = 'outputFilenameTemplate' + def __init__(self): diff --git a/src/ffx/constants.py b/src/ffx/constants.py index 16b3924..3a6bc0e 100644 --- a/src/ffx/constants.py +++ b/src/ffx/constants.py @@ -11,3 +11,5 @@ DEFAULT_7_1_BANDWIDTH = "384" DEFAULT_CROP_START = 60 DEFAULT_CROP_LENGTH = 180 + +DEFAULT_OUTPUT_FILENAME_TEMPLATE = '{{ ffx_show_name }} - {{ ffx_index }}{{ ffx_index_separator }}{{ ffx_episode_name }}{{ ffx_indicator_separator }}{{ ffx_indicator }}' diff --git a/src/ffx/ffx.py b/src/ffx/ffx.py index fe5bde1..4bec8cd 100755 --- a/src/ffx/ffx.py +++ b/src/ffx/ffx.py @@ -23,6 +23,7 @@ from ffx.track_codec import TrackCodec from ffx.process import executeProcess from ffx.helper import filterFilename +from ffx.helper import getEpisodeFileBasename from ffx.constants import DEFAULT_STEREO_BANDWIDTH, DEFAULT_AC3_BANDWIDTH, DEFAULT_DTS_BANDWIDTH, DEFAULT_7_1_BANDWIDTH @@ -649,14 +650,15 @@ def convert(ctx, if tmdbEpisodeResult: filteredEpisodeName = filterFilename(tmdbEpisodeResult['name']) - sourceFileBasename = TmdbController.getEpisodeFileBasename(showFilenamePrefix, + sourceFileBasename = getEpisodeFileBasename(showFilenamePrefix, filteredEpisodeName, shiftedShowSeason, shiftedShowEpisode, indexSeasonDigits, indexEpisodeDigits, indicatorSeasonDigits, - indicatorEpisodeDigits) + indicatorEpisodeDigits, + context=ctx.obj) if label: if shiftedShowSeason > -1 and shiftedShowEpisode > -1: diff --git a/src/ffx/helper.py b/src/ffx/helper.py index b116557..9b51e93 100644 --- a/src/ffx/helper.py +++ b/src/ffx/helper.py @@ -1,8 +1,21 @@ +import logging + +from jinja2 import Environment, Undefined +from .constants import DEFAULT_OUTPUT_FILENAME_TEMPLATE +from .configuration_controller import ConfigurationController + + +class EmptyStringUndefined(Undefined): + def __str__(self): + return '' + + DIFF_ADDED_KEY = 'added' DIFF_REMOVED_KEY = 'removed' DIFF_CHANGED_KEY = 'changed' DIFF_UNCHANGED_KEY = 'unchanged' + def dictDiff(a : dict, b : dict): a_keys = set(a.keys()) @@ -75,3 +88,79 @@ def filterFilename(fileName: str) -> str: fileName = str(fileName).replace("?", '#') return fileName.strip() + + +def getEpisodeFileBasename(showName, + episodeName, + season, + episode, + indexSeasonDigits = 2, + indexEpisodeDigits = 2, + indicatorSeasonDigits = 2, + indicatorEpisodeDigits = 2, + context = None): + """ + One Piece: + indexSeasonDigits = 0, + indexEpisodeDigits = 4, + indicatorSeasonDigits = 2, + indicatorEpisodeDigits = 4 + + Three-Body: + indexSeasonDigits = 0, + indexEpisodeDigits = 2, + indicatorSeasonDigits = 2, + indicatorEpisodeDigits = 2 + + Dragonball: + indexSeasonDigits = 0, + indexEpisodeDigits = 3, + indicatorSeasonDigits = 2, + indicatorEpisodeDigits = 3 + + Boruto: + indexSeasonDigits = 0, + indexEpisodeDigits = 4, + indicatorSeasonDigits = 2, + indicatorEpisodeDigits = 4 + """ + + cc: ConfigurationController = context['config'] if context is not None and 'config' in context.keys() else None + configData = cc.getData() if cc is not None else {} + outputFilenameTemplate = configData.get(ConfigurationController.OUTPUT_FILENAME_TEMPLATE_KEY, + DEFAULT_OUTPUT_FILENAME_TEMPLATE) + + if context is not None and 'logger' in context.keys(): + logger = context['logger'] + else: + logger = logging.getLogger('FFX') + logger.addHandler(logging.NullHandler()) + + + indexSeparator = ' ' if indexSeasonDigits or indexEpisodeDigits else '' + seasonIndex = '{num:{fill}{width}}'.format(num=season, fill='0', width=indexSeasonDigits) if indexSeasonDigits else '' + episodeIndex = '{num:{fill}{width}}'.format(num=episode, fill='0', width=indexEpisodeDigits) if indexEpisodeDigits else '' + + indicatorSeparator = ' - ' if indicatorSeasonDigits or indicatorEpisodeDigits else '' + seasonIndicator = 'S{num:{fill}{width}}'.format(num=season, fill='0', width=indicatorSeasonDigits) if indicatorSeasonDigits else '' + episodeIndicator = 'E{num:{fill}{width}}'.format(num=episode, fill='0', width=indicatorEpisodeDigits) if indicatorEpisodeDigits else '' + + jinjaKwargs = { + 'ffx_show_name': showName, + 'ffx_index_separator': indexSeparator, + 'ffx_season_index': str(seasonIndex), + 'ffx_episode_index': str(episodeIndex), + 'ffx_index': str(seasonIndex) + str(episodeIndex), + 'ffx_episode_name': episodeName, + 'ffx_indicator_separator': indicatorSeparator, + 'ffx_season_indicator': str(seasonIndicator), + 'ffx_episode_indicator': str(episodeIndicator), + 'ffx_indicator': str(seasonIndicator) + str(episodeIndicator) + } + + jinjaEnv = Environment(undefined=EmptyStringUndefined) + jinjaTemplate = jinjaEnv.from_string(outputFilenameTemplate) + return jinjaTemplate.render(**jinjaKwargs) + + # return ''.join(filenameTokens) + diff --git a/src/ffx/media_descriptor.py b/src/ffx/media_descriptor.py index d47029c..068173a 100644 --- a/src/ffx/media_descriptor.py +++ b/src/ffx/media_descriptor.py @@ -45,7 +45,8 @@ class MediaDescriptor: self.__logger = self.__context['logger'] else: self.__context = {} - self.__logger = logging.getLogger('FFX').addHandler(logging.NullHandler()) + self.__logger = logging.getLogger('FFX') + self.__logger.addHandler(logging.NullHandler()) if MediaDescriptor.TAGS_KEY in kwargs.keys(): if type(kwargs[MediaDescriptor.TAGS_KEY]) is not dict: @@ -402,7 +403,8 @@ class MediaDescriptor: if importedFilePath: - self.__logger.info(f"Substituting subtitle stream {td.getSubIndex()} " + self.__logger.info(f"Substituting subtitle stream #{td.getIndex()} " + + f"({td.getType().label()}:{td.getSubIndex()})" + f"with import from file {td.getExternalSourceFilePath()}") importFileTokens += [ diff --git a/src/ffx/show_descriptor.py b/src/ffx/show_descriptor.py index 566d142..a045e8d 100644 --- a/src/ffx/show_descriptor.py +++ b/src/ffx/show_descriptor.py @@ -32,7 +32,8 @@ class ShowDescriptor(): self.__logger = self.__context['logger'] else: self.__context = {} - self.__logger = logging.getLogger('FFX').addHandler(logging.NullHandler()) + self.__logger = logging.getLogger('FFX') + self.__logger.addHandler(logging.NullHandler()) if ShowDescriptor.ID_KEY in kwargs.keys(): if type(kwargs[ShowDescriptor.ID_KEY]) is not int: diff --git a/src/ffx/test/scenario_4.py b/src/ffx/test/scenario_4.py index 12f318d..f4f3efc 100644 --- a/src/ffx/test/scenario_4.py +++ b/src/ffx/test/scenario_4.py @@ -5,7 +5,9 @@ from .scenario import Scenario from ffx.test.helper import createMediaTestFile from ffx.process import executeProcess from ffx.database import databaseContext + from ffx.test.helper import createEmptyDirectory +from ffx.helper import getEpisodeFileBasename from ffx.file_properties import FileProperties @@ -205,9 +207,10 @@ class Scenario4(Scenario): tmdbEpisodeResult = self.__tc.queryEpisode(Scenario4.TEST_SHOW_IDENTIFIER, tfo['season'], tfo['episode']) - expectedFileBasename = TmdbController.getEpisodeFileBasename(self.__testShowDescriptor.getFilenamePrefix(), + expectedFileBasename = getEpisodeFileBasename(self.__testShowDescriptor.getFilenamePrefix(), tmdbEpisodeResult['name'], - tfo['season'], tfo['episode']) + tfo['season'], tfo['episode'], + context=testContext) expectedFilename = f"{expectedFileBasename}.{Scenario4.EXPECTED_FILE_EXTENSION}" expectedFilePath = os.path.join(self._testDirectory, expectedFilename) diff --git a/src/ffx/tmdb_controller.py b/src/ffx/tmdb_controller.py index 586d3f2..1190564 100644 --- a/src/ffx/tmdb_controller.py +++ b/src/ffx/tmdb_controller.py @@ -25,8 +25,12 @@ class TmdbController(): def __init__(self, context = None): self.__context = context - self.__logger = (context['logger'] if context is not None and 'logger' in context.keys() - else logging.getLogger('FFX').addHandler(logging.NullHandler())) + + if context is None: + self.__logger = logging.getLogger('FFX') + self.__logger.addHandler(logging.NullHandler()) + else: + self.__logger = context['logger'] self.__tmdbApiKey = os.environ.get('TMDB_API_KEY', None) if self.__tmdbApiKey is None: @@ -128,61 +132,3 @@ class TmdbController(): tmdbUrl = f"https://api.themoviedb.org/3/tv/{showId}/season/{season}/episode/{episode}{urlParams}" return self.getTmdbRequest(tmdbUrl) - - - @staticmethod - def getEpisodeFileBasename(showName, - episodeName, - season, - episode, - indexSeasonDigits = 2, - indexEpisodeDigits = 2, - indicatorSeasonDigits = 2, - indicatorEpisodeDigits = 2): - """ - One Piece: - indexSeasonDigits = 0, - indexEpisodeDigits = 4, - indicatorSeasonDigits = 2, - indicatorEpisodeDigits = 4 - - Three-Body: - indexSeasonDigits = 0, - indexEpisodeDigits = 2, - indicatorSeasonDigits = 2, - indicatorEpisodeDigits = 2 - - Dragonball: - indexSeasonDigits = 0, - indexEpisodeDigits = 3, - indicatorSeasonDigits = 2, - indicatorEpisodeDigits = 3 - - Boruto: - indexSeasonDigits = 0, - indexEpisodeDigits = 4, - indicatorSeasonDigits = 2, - indicatorEpisodeDigits = 4 - """ - filenameTokens = [str(showName), ' - '] - - if indexSeasonDigits: - filenameTokens += ['{num:{fill}{width}}'.format(num=season, fill='0', width=indexSeasonDigits)] - if indexEpisodeDigits: - filenameTokens += ['{num:{fill}{width}}'.format(num=episode, fill='0', width=indexEpisodeDigits)] - if indexSeasonDigits or indexEpisodeDigits: - filenameTokens += [' '] - - filenameTokens += [episodeName] - - if indicatorSeasonDigits or indicatorEpisodeDigits: - filenameTokens += [' - '] - if indicatorSeasonDigits: - filenameTokens += ['S{num:{fill}{width}}'.format(num=season, fill='0', width=indicatorSeasonDigits)] - if indicatorEpisodeDigits: - filenameTokens += ['E{num:{fill}{width}}'.format(num=episode, fill='0', width=indicatorEpisodeDigits)] - - return ''.join(filenameTokens) - - def importShow(self, showId: int): - pass \ No newline at end of file diff --git a/src/ffx/track_descriptor.py b/src/ffx/track_descriptor.py index 633897e..5c24006 100644 --- a/src/ffx/track_descriptor.py +++ b/src/ffx/track_descriptor.py @@ -47,7 +47,8 @@ class TrackDescriptor: self.__logger = self.__context['logger'] else: self.__context = {} - self.__logger = logging.getLogger('FFX').addHandler(logging.NullHandler()) + self.__logger = logging.getLogger('FFX') + self.__logger.addHandler(logging.NullHandler()) if TrackDescriptor.ID_KEY in kwargs.keys(): if type(kwargs[TrackDescriptor.ID_KEY]) is not int: