#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"} license = {file = "LICENSE.md"}
dependencies = [ dependencies = [
"requests", "requests",
"jinja2",
"click", "click",
"textual", "textual",
"sqlalchemy", "sqlalchemy",

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

@ -11,3 +11,5 @@ DEFAULT_7_1_BANDWIDTH = "384"
DEFAULT_CROP_START = 60 DEFAULT_CROP_START = 60
DEFAULT_CROP_LENGTH = 180 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.process import executeProcess
from ffx.helper import filterFilename 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 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: if tmdbEpisodeResult:
filteredEpisodeName = filterFilename(tmdbEpisodeResult['name']) filteredEpisodeName = filterFilename(tmdbEpisodeResult['name'])
sourceFileBasename = TmdbController.getEpisodeFileBasename(showFilenamePrefix, sourceFileBasename = getEpisodeFileBasename(showFilenamePrefix,
filteredEpisodeName, filteredEpisodeName,
shiftedShowSeason, shiftedShowSeason,
shiftedShowEpisode, shiftedShowEpisode,
indexSeasonDigits, indexSeasonDigits,
indexEpisodeDigits, indexEpisodeDigits,
indicatorSeasonDigits, indicatorSeasonDigits,
indicatorEpisodeDigits) indicatorEpisodeDigits,
context=ctx.obj)
if label: if label:
if shiftedShowSeason > -1 and shiftedShowEpisode > -1: 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_ADDED_KEY = 'added'
DIFF_REMOVED_KEY = 'removed' DIFF_REMOVED_KEY = 'removed'
DIFF_CHANGED_KEY = 'changed' DIFF_CHANGED_KEY = 'changed'
DIFF_UNCHANGED_KEY = 'unchanged' DIFF_UNCHANGED_KEY = 'unchanged'
def dictDiff(a : dict, b : dict): def dictDiff(a : dict, b : dict):
a_keys = set(a.keys()) a_keys = set(a.keys())
@ -75,3 +88,79 @@ def filterFilename(fileName: str) -> str:
fileName = str(fileName).replace("?", '#') fileName = str(fileName).replace("?", '#')
return fileName.strip() 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'] self.__logger = self.__context['logger']
else: else:
self.__context = {} 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 MediaDescriptor.TAGS_KEY in kwargs.keys():
if type(kwargs[MediaDescriptor.TAGS_KEY]) is not dict: if type(kwargs[MediaDescriptor.TAGS_KEY]) is not dict:
@ -402,7 +403,8 @@ class MediaDescriptor:
if importedFilePath: 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()}") + f"with import from file {td.getExternalSourceFilePath()}")
importFileTokens += [ importFileTokens += [

@ -32,7 +32,8 @@ class ShowDescriptor():
self.__logger = self.__context['logger'] self.__logger = self.__context['logger']
else: else:
self.__context = {} 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 ShowDescriptor.ID_KEY in kwargs.keys():
if type(kwargs[ShowDescriptor.ID_KEY]) is not int: 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.test.helper import createMediaTestFile
from ffx.process import executeProcess from ffx.process import executeProcess
from ffx.database import databaseContext from ffx.database import databaseContext
from ffx.test.helper import createEmptyDirectory from ffx.test.helper import createEmptyDirectory
from ffx.helper import getEpisodeFileBasename
from ffx.file_properties import FileProperties from ffx.file_properties import FileProperties
@ -205,9 +207,10 @@ class Scenario4(Scenario):
tmdbEpisodeResult = self.__tc.queryEpisode(Scenario4.TEST_SHOW_IDENTIFIER, tmdbEpisodeResult = self.__tc.queryEpisode(Scenario4.TEST_SHOW_IDENTIFIER,
tfo['season'], tfo['episode']) tfo['season'], tfo['episode'])
expectedFileBasename = TmdbController.getEpisodeFileBasename(self.__testShowDescriptor.getFilenamePrefix(), expectedFileBasename = getEpisodeFileBasename(self.__testShowDescriptor.getFilenamePrefix(),
tmdbEpisodeResult['name'], tmdbEpisodeResult['name'],
tfo['season'], tfo['episode']) tfo['season'], tfo['episode'],
context=testContext)
expectedFilename = f"{expectedFileBasename}.{Scenario4.EXPECTED_FILE_EXTENSION}" expectedFilename = f"{expectedFileBasename}.{Scenario4.EXPECTED_FILE_EXTENSION}"
expectedFilePath = os.path.join(self._testDirectory, expectedFilename) expectedFilePath = os.path.join(self._testDirectory, expectedFilename)

@ -25,8 +25,12 @@ class TmdbController():
def __init__(self, context = None): def __init__(self, context = None):
self.__context = context 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) self.__tmdbApiKey = os.environ.get('TMDB_API_KEY', None)
if self.__tmdbApiKey is 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}" tmdbUrl = f"https://api.themoviedb.org/3/tv/{showId}/season/{season}/episode/{episode}{urlParams}"
return self.getTmdbRequest(tmdbUrl) 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'] self.__logger = self.__context['logger']
else: else:
self.__context = {} 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 TrackDescriptor.ID_KEY in kwargs.keys():
if type(kwargs[TrackDescriptor.ID_KEY]) is not int: if type(kwargs[TrackDescriptor.ID_KEY]) is not int:

Loading…
Cancel
Save