#389 Templating für Ausgabe-Dateinamen

main
Maveno 11 months ago
parent 5e57e57ad2
commit 59dbb8985a

@ -5,6 +5,7 @@ version = "0.2.2"
license = {file = "LICENSE.md"}
dependencies = [
"requests",
"jinja2",
"click",
"textual",
"sqlalchemy",

@ -8,6 +8,8 @@ class ConfigurationController():
DATABASE_PATH_CONFIG_KEY = 'databasePath'
LOG_DIRECTORY_CONFIG_KEY = 'logDirectory'
OUTPUT_FILENAME_TEMPLATE_KEY = 'outputFilenameTemplate'
def __init__(self):

@ -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 }}'

@ -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:

@ -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)

@ -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 += [

@ -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:

@ -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)

@ -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

@ -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:

Loading…
Cancel
Save