Scenario4 inc

click-textual
Maveno 11 months ago
parent f007ada29f
commit 2abda01fe6

@ -440,10 +440,12 @@ def convert(ctx,
if context['use_tmdb']:
click.echo(f"Querying TMDB for show_id={currentShowDescriptor.getId()} season={mediaFileProperties.getSeason()} episode{mediaFileProperties.getEpisode()}")
tmdbEpisodeResult = tc.queryEpisode(currentShowDescriptor.getId(), mediaFileProperties.getSeason(), mediaFileProperties.getEpisode())
click.echo(f"tmdbEpisodeResult={tmdbEpisodeResult}")
if tmdbEpisodeResult:
sourceFileBasename = tc.getEpisodeFileBasename(currentShowDescriptor.getFilenamePrefix(),
sourceFileBasename = TmdbController.getEpisodeFileBasename(currentShowDescriptor.getFilenamePrefix(),
tmdbEpisodeResult['name'],
mediaFileProperties.getSeason(),
mediaFileProperties.getEpisode(),

@ -175,12 +175,12 @@ class FfxController():
# sourceTrackDescriptors = [] if self.__sourceMediaDescriptor is None else self.__sourceMediaDescriptor.getAllTrackDescriptors()
targetTrackDescriptors = self.__targetMediaDescriptor.getAllTrackDescriptors()
dispositionTokens = []
for trackIndex in range(len(targetTrackDescriptors)):
td = targetTrackDescriptors[trackIndex]
#sd = sourceTrackDescriptors[trackIndex]
#HINT: No dispositions for pgs subtitle tracks that have no external file source
if (td.getExternalSourceFilePath()

@ -43,24 +43,35 @@ class FileProperties():
self.__pc = PatternController(context)
# db pattern boruto_[sS]([0-9]+)[eE]([0-9]+).mkv
# Checking if database contains matching pattern
matchResult = self.__pc.matchFilename(self.__sourceFilename)
self.__logger.debug(f"FileProperties.__init__(): Match result {matchResult}")
self.__pattern: Pattern = matchResult['pattern'] if matchResult else None
matchedGroups = matchResult['match'].groups() if matchResult else {}
seIndicator = matchedGroups[0] if matchedGroups else self.__sourceFilename
if matchResult:
databaseMatchedGroups = matchResult['match'].groups()
self.__season = databaseMatchedGroups[0]
self.__episode = databaseMatchedGroups[1]
se_match = re.search(FileProperties.SEASON_EPISODE_INDICATOR_MATCH, seIndicator)
e_match = re.search(FileProperties.EPISODE_INDICATOR_MATCH, seIndicator)
else:
self.__logger.debug(f"FileProperties.__init__(): Checking file name for indicator {self.__sourceFilename}")
self.__season = -1
self.__episode = -1
se_match = re.search(FileProperties.SEASON_EPISODE_INDICATOR_MATCH, self.__sourceFilename)
e_match = re.search(FileProperties.EPISODE_INDICATOR_MATCH, self.__sourceFilename)
if se_match is not None:
self.__season = int(se_match.group(1))
self.__episode = int(se_match.group(2))
elif e_match is not None:
self.__season = -1
self.__episode = int(e_match.group(1))
else:
self.__season = -1
self.__episode = -1
def getFormatData(self):

@ -0,0 +1,47 @@
import click, re
from ffx.model.pattern import Pattern
from ffx.media_descriptor import MediaDescriptor
from ffx.tag_controller import TagController
from ffx.track_controller import TrackController
class MediaController():
def __init__(self, context):
self.context = context
self.Session = self.context['database']['session'] # convenience
self.__logger = context['logger']
self.__tc = TrackController(context = context)
self.__tac = TagController(context = context)
def setPatternMediaDescriptor(self, mediaDescriptor: MediaDescriptor, patternId: int):
try:
pid = int(patternId)
s = self.Session()
q = s.query(Pattern).filter(Pattern.id == pid)
if q.count():
pattern = q.first
for mediaTagKey, mediaTagValue in mediaDescriptor.getTags():
self.__tac.updateMediaTag(pid, mediaTagKey, mediaTagValue)
for trackDescriptor in mediaDescriptor.getAllTrackDescriptors():
self.__tc.addTrack(trackDescriptor, patternId = pid)
s.commit()
return True
else:
return False
except Exception as ex:
self.__logger.error(f"MediaController.setPatternMediaDescriptor(): {repr(ex)}")
raise click.ClickException(f"MediaController.setPatternMediaDescriptor(): {repr(ex)}")
finally:
s.close()

@ -501,3 +501,11 @@ class MediaDescriptor:
# click.echo(f"Found matching subtitle file {msfd["path"]}\n")
self.__logger.debug(f"importSubtitles(): Found matching subtitle file {msfd["path"]}")
matchingSubtitleTrackDescriptor[0].setExternalSourceFilePath(msfd["path"])
def getConfiguration(self, label: str = ''):
yield f"--- {label if label else 'MediaDescriptor '+str(id(self))} {' '.join([str(k)+'='+str(v) for k,v in self.__mediaTags.items()])}"
for td in self.getAllTrackDescriptors():
yield (f"{td.getIndex()}:{td.getType().indicator()}:{td.getSubIndex()} "
+ '|'.join([d.indicator() for d in td.getDispositionSet()])
+ ' ' + ' '.join([str(k)+'='+str(v) for k,v in td.getTags().items()]))

@ -504,7 +504,7 @@ class MediaDetailsScreen(Screen):
if patternDescriptor:
patternId = self.__pc.addPattern(patternDescriptor)
if patternId:
self.highlightPattern(False)
for tagKey, tagValue in self.__currentMediaDescriptor.getTags().items():

@ -25,7 +25,7 @@ class PatternController():
s.commit()
return pattern.getId()
else:
return None
return 0
except Exception as ex:
raise click.ClickException(f"PatternController.addPattern(): {repr(ex)}")
@ -116,7 +116,8 @@ class PatternController():
s.close()
def matchFilename(self, filename : str) -> re.Match:
def matchFilename(self, filename : str) -> dict:
"""Returns dict {'match': <a regex match obj>, 'pattern': <ffx pattern obj>} or empty dict of no pattern was found"""
try:
s = self.Session()
@ -126,7 +127,7 @@ class PatternController():
for pattern in q.all():
patternMatch = re.search(str(pattern.pattern), str(filename))
if patternMatch:
if patternMatch is not None:
matchResult['match'] = patternMatch
matchResult['pattern'] = pattern

@ -345,8 +345,7 @@ class PatternDetailsScreen(Screen):
else:
patternId = self.__pc.addPattern(patternDescriptor)
if patternId is not None:
if patternId:
self.dismiss(patternDescriptor)
else:
#TODO: Meldung

@ -55,33 +55,34 @@ class ShowDescriptor():
else:
self.__showYear = -1
if ShowDescriptor.INDEX_SEASON_DIGITS_KEY in kwargs.keys():
if type(kwargs[ShowDescriptor.INDEX_SEASON_DIGITS_KEY]) is not int:
raise TypeError(f"ShowDescriptor.__init__(): Argument {ShowDescriptor.INDEX_SEASON_DIGITS_KEY} is required to be of type int")
self.__indexSeasonDigits = kwargs[ShowDescriptor.INDEX_SEASON_DIGITS_KEY]
else:
self.__indexSeasonDigits = -1
self.__indexSeasonDigits = ShowDescriptor.DEFAULT_INDEX_SEASON_DIGITS
if ShowDescriptor.INDEX_EPISODE_DIGITS_KEY in kwargs.keys():
if type(kwargs[ShowDescriptor.INDEX_EPISODE_DIGITS_KEY]) is not int:
raise TypeError(f"ShowDescriptor.__init__(): Argument {ShowDescriptor.INDEX_EPISODE_DIGITS_KEY} is required to be of type int")
self.__indexEpisodeDigits = kwargs[ShowDescriptor.INDEX_EPISODE_DIGITS_KEY]
else:
self.__indexEpisodeDigits = -1
self.__indexEpisodeDigits = ShowDescriptor.DEFAULT_INDEX_EPISODE_DIGITS
if ShowDescriptor.INDICATOR_SEASON_DIGITS_KEY in kwargs.keys():
if type(kwargs[ShowDescriptor.INDICATOR_SEASON_DIGITS_KEY]) is not int:
raise TypeError(f"ShowDescriptor.__init__(): Argument {ShowDescriptor.INDICATOR_SEASON_DIGITS_KEY} is required to be of type int")
self.__indicatorSeasonDigits = kwargs[ShowDescriptor.INDICATOR_SEASON_DIGITS_KEY]
else:
self.__indicatorSeasonDigits = -1
self.__indicatorSeasonDigits = ShowDescriptor.DEFAULT_INDICATOR_SEASON_DIGITS
if ShowDescriptor.INDICATOR_EPISODE_DIGITS_KEY in kwargs.keys():
if type(kwargs[ShowDescriptor.INDICATOR_EPISODE_DIGITS_KEY]) is not int:
raise TypeError(f"ShowDescriptor.__init__(): Argument {ShowDescriptor.INDICATOR_EPISODE_DIGITS_KEY} is required to be of type int")
self.__indicatorEpisodeDigits = kwargs[ShowDescriptor.INDICATOR_EPISODE_DIGITS_KEY]
else:
self.__indicatorEpisodeDigits = -1
self.__indicatorEpisodeDigits = ShowDescriptor.DEFAULT_INDICATOR_EPISODE_DIGITS
def getId(self):

@ -17,12 +17,16 @@ class IndicatorCombinator():
if season == -1 and episode == -1:
return {
'variant': 'S00E00',
'indicator': ''
'indicator': '',
'season': season,
'episode': episode
}
else:
return {
'variant': f"S{season+1:02d}E{episode+1:02d}",
'indicator': f"S{season+1:02d}E{episode+1:02d}"
'variant': f"S{season:02d}E{episode:02d}",
'indicator': f"S{season:02d}E{episode:02d}",
'season': season,
'episode': episode
}
def assertFunc(self, testObj = {}):
@ -36,4 +40,4 @@ class IndicatorCombinator():
yield self.getPayload()
for season in range(IndicatorCombinator.MAX_SEASON):
for episode in range(IndicatorCombinator.MAX_EPISODE):
yield self.getPayload(season, episode)
yield self.getPayload(season+1, episode+1)

@ -2,7 +2,6 @@ import os, glob, sys, importlib, glob, inspect
from ffx.test.helper import createEmptyDirectory
class Scenario():
"""Scenarios

@ -91,8 +91,13 @@ class Scenario2(Scenario):
if rc:
self._logger.debug(f"{variantLabel}: Process returned ERROR {rc} ({err})")
# Phase 4: Evaluate results
resultFilenames = [rf for rf in self.getFilenamesInTestDirectory() if rf != 'ffmpeg2pass-0.log' and rf != variantFilename]
self._logger.debug(f"{variantLabel}: Result filenames: {resultFilenames}")
try:
jobFailed = bool(rc)

@ -4,6 +4,8 @@ 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.file_properties import FileProperties
@ -14,18 +16,98 @@ from ffx.track_type import TrackType
from ffx.track_disposition import TrackDisposition
from ffx.test.media_combinator import MediaCombinator
from ffx.test.indicator_combinator import IndicatorCombinator
from ffx.show_descriptor import ShowDescriptor
from ffx.show_controller import ShowController
from ffx.pattern_controller import PatternController
from ffx.media_controller import MediaController
from ffx.tmdb_controller import TmdbController
from ffx.tmdb_controller import TMDB_API_KEY_NOT_PRESENT_EXCEPTION
class Scenario4(Scenario):
TEST_SHOW_IDENTIFIER = 83095
TEST_SHOW_NAME = 'The Rising of the Shield Hero'
TEST_SHOW_YEAR = 2019
TEST_FILE_LABEL = 'rotsh'
TEST_FILE_EXTENSION = 'mkv'
TEST_PATTERN = f"{TEST_FILE_LABEL}_{FileProperties.SEASON_EPISODE_INDICATOR_MATCH}.{TEST_FILE_EXTENSION}"
EXPECTED_FILE_EXTENSION = 'webm'
def __init__(self, context):
super().__init__(context)
self.__tmdbApiKey = os.environ.get('TMDB_API_KEY', None)
if self.__tmdbApiKey is None:
raise TMDB_API_KEY_NOT_PRESENT_EXCEPTION
self.__testDbFilePath = os.path.join(self._testDirectory, 'test.db')
self.createEmptyTestDatabase()
self.__ic = IndicatorCombinator(context = context)
self.__sc = ShowController(context = context)
self.__pc = PatternController(context = context)
self.__mc = MediaController(context = context)
self.__tc = TmdbController()
def getScenario(self):
return self.__class__.__name__[8:]
def createEmptyTestDatabase(self):
if not self._context['database'] is None:
self._context['database']['engine'].dispose()
if os.path.isfile(self.__testDbFilePath):
os.unlink(self.__testDbFilePath)
self._context['database'] = None
self._logger.debug(f"Creating test db with path {self.__testDbFilePath}")
self._context['database'] = databaseContext(databasePath=self.__testDbFilePath)
def prepareTestDatabase(self, sourceMediaDescriptor: MediaDescriptor):
if not self._context['database'] is None:
self._context['database']['engine'].dispose()
if os.path.isfile(self.__testDbFilePath):
os.unlink(self.__testDbFilePath)
self._context['database'] = None
self._logger.debug(f"Creating test db with path {self.__testDbFilePath}")
self._context['database'] = databaseContext(databasePath=self.__testDbFilePath)
kwargs = {}
kwargs[ShowDescriptor.ID_KEY] = Scenario4.TEST_SHOW_IDENTIFIER
kwargs[ShowDescriptor.NAME_KEY] = Scenario4.TEST_SHOW_NAME
kwargs[ShowDescriptor.YEAR_KEY] = Scenario4.TEST_SHOW_YEAR
self.__testShowDescriptor = ShowDescriptor(**kwargs)
self._logger.debug(f"Adding test show '{self.__testShowDescriptor.getFilenamePrefix()}' to test db")
if not self.__sc.updateShow(self.__testShowDescriptor):
raise click.ClickException('Could not create test show in db')
testPatternDescriptor = {
'show_id': Scenario4.TEST_SHOW_IDENTIFIER,
'pattern': Scenario4.TEST_PATTERN
}
patternId = self.__pc.addPattern(testPatternDescriptor)
if patternId:
self.__mc.setPatternMediaDescriptor(sourceMediaDescriptor, patternId)
def job(self, yieldObj: dict):
@ -44,11 +126,11 @@ class Scenario4(Scenario):
variantLabel = f"{self.__class__.__name__} Variant {variantIdentifier}"
sourceMediaDescriptor: MediaDescriptor = targetYieldObj['payload']
#presetMediaDescriptor: MediaDescriptor = targetYieldObj['payload']['preset']
presetMediaDescriptor: MediaDescriptor = presetYieldObj['payload']
assertSelectorList: list = targetYieldObj['assertSelectors']
assertFuncList = targetYieldObj['assertFuncs']
shouldFail = targetYieldObj['shouldFail']
assertSelectorList: list = presetYieldObj['assertSelectors']
assertFuncList = presetYieldObj['assertFuncs']
shouldFail = presetYieldObj['shouldFail']
try:
jellyfinSelectorIndex = assertSelectorList.index('J')
@ -61,63 +143,113 @@ class Scenario4(Scenario):
if self._context['test_variant'] and variantIdentifier != self._context['test_variant']:
return
for l in sourceMediaDescriptor.getConfiguration(label = 'sourceMediaDescriptor'):
self._logger.debug(l)
for l in presetMediaDescriptor.getConfiguration(label = 'presetMediaDescriptor'):
self._logger.debug(l)
self._logger.debug(f"Running Job: {variantLabel}")
# Phase 1: Setup source files
self.clearTestDirectory()
mediaFilePath = createMediaTestFile(mediaDescriptor=sourceMediaDescriptor, directory=self._testDirectory, logger=self._logger, length = 2)
self.createEmptyTestDatabase()
self.prepareTestDatabase(sourceMediaDescriptor)
testFileList = []
for indicatorObj in [y for y in self.__ic.getYield() if y['indicator']]:
indicator = indicatorObj['indicator']
testFileObj = {}
testFileObj['season'] = indicatorObj['season']
testFileObj['episode'] = indicatorObj['episode']
testFileObj['basename'] = f"{Scenario4.TEST_FILE_LABEL}_{indicator}"
testFileObj['path'] = createMediaTestFile(mediaDescriptor = presetMediaDescriptor,
directory = self._testDirectory,
baseName = testFileObj['basename'],
logger=self._logger,
length = 2)
testFileObj['filename'] = f"{testFileObj['basename']}.{Scenario4.TEST_FILE_EXTENSION}"
testFileList.append(testFileObj)
# Phase 2: Prepare database
# # Phase 2: Prepare database
#
# Phase 3: Run ffx
commandSequence = [sys.executable,
self._ffxExecutablePath,
'convert',
mediaFilePath,
'--no-prompt']
'--database-file',
self.__testDbFilePath,
'convert']
commandSequence += [tfo['filename'] for tfo in testFileList]
commandSequence += ['--no-prompt']
if not testContext['use_jellyfin']:
commandSequence += ['--no-jellyfin']
# if not testContext['use_jellyfin']:
# commandSequence += ['--no-jellyfin']
self._logger.debug(f"{variantLabel}: Test sequence: {commandSequence}")
out, err, rc = executeProcess(commandSequence, directory = self._testDirectory)
if out:
self._logger.debug(f"{variantLabel}: Process output: {out}")
# if out:
# self._logger.debug(f"{variantLabel}: Process output: {out}")
if rc:
self._logger.debug(f"{variantLabel}: Process returned ERROR {rc} ({err})")
# Phase 4: Evaluate results
resultFilenames = [rf for rf in self.getFilenamesInTestDirectory() if rf.endswith(f".{Scenario4.EXPECTED_FILE_EXTENSION}")]
self._logger.debug(f"{variantLabel}: Result filenames: {resultFilenames}")
try:
jobFailed = bool(rc)
assert not (bool(rc)
), f"Process failed"
self._logger.debug(f"{variantLabel}: Should fail: {shouldFail} / actually failed: {jobFailed}")
for tfo in testFileList:
assert (jobFailed == shouldFail
), f"Process {'failed' if jobFailed else 'did not fail'}"
tmdbEpisodeResult = self.__tc.queryEpisode(Scenario4.TEST_SHOW_IDENTIFIER,
tfo['season'], tfo['episode'])
if not jobFailed:
expectedFileBasename = TmdbController.getEpisodeFileBasename(self.__testShowDescriptor.getFilenamePrefix(),
tmdbEpisodeResult['name'],
tfo['season'], tfo['episode'])
resultFile = os.path.join(self._testDirectory, 'media.webm')
expectedFilename = f"{expectedFileBasename}.{Scenario4.EXPECTED_FILE_EXTENSION}"
expectedFilePath = os.path.join(self._testDirectory, expectedFilename)
assert (os.path.isfile(resultFile)
), f"Result file 'media.webm' in path '{self._testDirectory}' wasn't created"
assert (os.path.isfile(expectedFilePath)
), f"Result file '{expectedFilename}' in path '{self._testDirectory}' wasn't created"
resultFileProperties = FileProperties(testContext, resultFile)
resultMediaDescriptor = resultFileProperties.getMediaDescriptor()
###
#
rfp = FileProperties(testContext, expectedFilePath)
self._logger.debug(f"{variantLabel}: Result file properties: {rfp.getFilename()} season={rfp.getSeason()} episode={rfp.getEpisode()}")
rmd = rfp.getMediaDescriptor()
rmt = rmd.getAllTrackDescriptors()
for l in rmd.getConfiguration(label = 'resultMediaDescriptor'):
self._logger.debug(l)
if testContext['use_jellyfin']:
sourceMediaDescriptor.applyJellyfinOrder()
resultMediaDescriptor.applySourceIndices(sourceMediaDescriptor)
resultMediaTracks = resultMediaDescriptor.getAllTrackDescriptors()
# num tracks differ
rmd.applySourceIndices(sourceMediaDescriptor)
for assertIndex in range(len(assertSelectorList)):
@ -125,17 +257,17 @@ class Scenario4(Scenario):
assertFunc = assertFuncList[assertIndex]
assertVariant = variantList[assertIndex]
if assertSelector == 'M':
assertFunc()
for variantIndex in range(len(assertVariant)):
assert (assertVariant[variantIndex].lower() == resultMediaTracks[variantIndex].getType().indicator()
), f"Stream #{variantIndex} is not of type {resultMediaTracks[variantIndex].getType().label()}"
elif assertSelector == 'AD' or assertSelector == 'AT':
assertFunc({'tracks': resultMediaDescriptor.getAudioTracks()})
# if assertSelector == 'M':
# assertFunc()
# for variantIndex in range(len(assertVariant)):
# assert (assertVariant[variantIndex].lower() == rmd.getType().indicator()
# ), f"Stream #{variantIndex} is not of type {rmd.getType().label()}"
#
if assertSelector == 'AD' or assertSelector == 'AT':
assertFunc({'tracks': rmd.getAudioTracks()})
elif assertSelector == 'SD' or assertSelector == 'ST':
assertFunc({'tracks': resultMediaDescriptor.getSubtitleTracks()})
assertFunc({'tracks': rmd.getSubtitleTracks()})
elif type(assertSelector) is str:
if assertSelector == 'J':
@ -148,9 +280,13 @@ class Scenario4(Scenario):
self._reportLogger.error(f"{variantLabel}: Test FAILED ({ae})")
exit()
def run(self):
MC_list = MediaCombinator.getAllClassReferences()
MC_list = [MediaCombinator.getClassReference(6)]
for MC in MC_list:
self._logger.debug(f"MC={MC.__name__}")
mc = MC(context = self._context, createPresets = True)

@ -1,19 +1,56 @@
import os, click, requests, json
import os, click, requests, json, time, logging
class TMDB_REQUEST_EXCEPTION(Exception):
def __init__(self, statusCode, statusMessage):
errorMessage = f"TMDB query failed with status code {statusCode}: {statusMessage}"
super().__init__(errorMessage)
class TMDB_API_KEY_NOT_PRESENT_EXCEPTION(Exception):
def __str__(self):
return 'TMDB api key is not available, please set environment variable TMDB_API_KEY'
class TMDB_EXCESSIVE_USAGE_EXCEPTION(Exception):
def __str__(self):
return 'Rate limit was triggered too often'
class TmdbController():
DEFAULT_LANGUAGE = 'de-DE'
def __init__(self):
RATE_LIMIT_WAIT_SECONDS = 10
RATE_LIMIT_RETRIES = 3
try:
self.__tmdbApiKey = os.environ['TMDB_API_KEY']
except KeyError:
raise click.ClickException('TMDB api key is not available, please set environment variable TMDB_API_KEY')
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()))
self.__tmdbApiKey = os.environ.get('TMDB_API_KEY', None)
if self.__tmdbApiKey is None:
raise TMDB_API_KEY_NOT_PRESENT_EXCEPTION
self.tmdbLanguage = TmdbController.DEFAULT_LANGUAGE
def getTmdbRequest(self, tmdbUrl):
retries = TmdbController.RATE_LIMIT_RETRIES
while True:
response = requests.get(tmdbUrl)
if response.status_code == 429:
if not retries:
raise TMDB_EXCESSIVE_USAGE_EXCEPTION()
self.__logger.warning('TMDB Rate limit (status_code 429)')
time.sleep(TmdbController.RATE_LIMIT_WAIT_SECONDS)
retries -= 1
else:
jsonResult = response.json()
if ('success' in jsonResult.keys()
and not jsonResult['success']):
raise TMDB_REQUEST_EXCEPTION(jsonResult['status_code'], jsonResult['status_message'])
return jsonResult
def queryShow(self, showId):
"""
First level keys in the response object:
@ -55,22 +92,8 @@ class TmdbController():
tmdbUrl = f"https://api.themoviedb.org/3/tv/{showId}{urlParams}"
#TODO Check for result
try:
#TODO: Content Type aware processing
# response = requests.get(tmdbUrl)
# response.encoding = 'utf-8'
# return response.json()
# response = requests.get(tmdbUrl)
return self.getTmdbRequest(tmdbUrl)
# contentType = response.headers.get('Content-Type')
# print(content_type) # Example: 'application/json; charset=UTF-8'
# decoded_content = response.content.decode('utf-8')
# return json.loads(decoded_content)
return requests.get(tmdbUrl).json()
except:
return {}
def queryEpisode(self, showId, season, episode):
"""
@ -94,14 +117,11 @@ class TmdbController():
tmdbUrl = f"https://api.themoviedb.org/3/tv/{showId}/season/{season}/episode/{episode}{urlParams}"
#TODO Check for result
try:
return requests.get(tmdbUrl).json()
except:
return {}
return self.getTmdbRequest(tmdbUrl)
def getEpisodeFileBasename(self,
showName,
@staticmethod
def getEpisodeFileBasename(showName,
episodeName,
season,
episode,

@ -5,25 +5,25 @@ from enum import Enum
class TrackDisposition(Enum):
DEFAULT = {"name": "default", "index": 0}
FORCED = {"name": "forced", "index": 1}
DUB = {"name": "dub", "index": 2}
ORIGINAL = {"name": "original", "index": 3}
COMMENT = {"name": "comment", "index": 4}
LYRICS = {"name": "lyrics", "index": 5}
KARAOKE = {"name": "karaoke", "index": 6}
HEARING_IMPAIRED = {"name": "hearing_impaired", "index": 7}
VISUAL_IMPAIRED = {"name": "visual_impaired", "index": 8}
CLEAN_EFFECTS = {"name": "clean_effects", "index": 9}
ATTACHED_PIC = {"name": "attached_pic", "index": 10}
TIMED_THUMBNAILS = {"name": "timed_thumbnails", "index": 11}
NON_DIEGETICS = {"name": "non_diegetic", "index": 12}
CAPTIONS = {"name": "captions", "index": 13}
DESCRIPTIONS = {"name": "descriptions", "index": 14}
METADATA = {"name": "metadata", "index": 15}
DEPENDENT = {"name": "dependent", "index": 16}
STILL_IMAGE = {"name": "still_image", "index": 17}
DEFAULT = {"name": "default", "index": 0, "indicator": "DE"}
FORCED = {"name": "forced", "index": 1, "indicator": "FO"}
DUB = {"name": "dub", "index": 2, "indicator": "DB"}
ORIGINAL = {"name": "original", "index": 3, "indicator": "OG"}
COMMENT = {"name": "comment", "index": 4, "indicator": "CM"}
LYRICS = {"name": "lyrics", "index": 5, "indicator": "LY"}
KARAOKE = {"name": "karaoke", "index": 6, "indicator": "KA"}
HEARING_IMPAIRED = {"name": "hearing_impaired", "index": 7, "indicator": "HI"}
VISUAL_IMPAIRED = {"name": "visual_impaired", "index": 8, "indicator": "VI"}
CLEAN_EFFECTS = {"name": "clean_effects", "index": 9, "indicator": "CE"}
ATTACHED_PIC = {"name": "attached_pic", "index": 10, "indicator": "AP"}
TIMED_THUMBNAILS = {"name": "timed_thumbnails", "index": 11, "indicator": "TT"}
NON_DIEGETICS = {"name": "non_diegetic", "index": 12, "indicator": "ND"}
CAPTIONS = {"name": "captions", "index": 13, "indicator": "CA"}
DESCRIPTIONS = {"name": "descriptions", "index": 14, "indicator": "DS"}
METADATA = {"name": "metadata", "index": 15, "indicator": "MD"}
DEPENDENT = {"name": "dependent", "index": 16, "indicator": "DP"}
STILL_IMAGE = {"name": "still_image", "index": 17, "indicator": "SI"}
def label(self):
@ -32,6 +32,9 @@ class TrackDisposition(Enum):
def index(self):
return int(self.value['index'])
def indicator(self):
return str(self.value['indicator'])
@staticmethod
def toFlags(dispositionSet):

@ -10,6 +10,7 @@ from ffx.database import databaseContext
from ffx.test.helper import createMediaTestFile
from ffx.test.scenario import Scenario
from ffx.tmdb_controller import TMDB_API_KEY_NOT_PRESENT_EXCEPTION
@click.group()
@ -20,7 +21,7 @@ def ffx(ctx, verbose, dry_run):
"""FFX"""
ctx.obj = {}
ctx.obj['database'] = databaseContext(databasePath=None)
ctx.obj['database'] = None
ctx.obj['dry_run'] = dry_run
ctx.obj['verbosity'] = verbose
@ -85,7 +86,9 @@ def run(ctx, scenario, variant):
for si in Scenario.list():
scen = Scenario.getClassReference(si)(ctx.obj)
try:
SCEN = Scenario.getClassReference(si)
scen = SCEN(ctx.obj)
if scenario and scenario != scen.getScenario():
continue
@ -94,6 +97,9 @@ def run(ctx, scenario, variant):
scen.run()
except TMDB_API_KEY_NOT_PRESENT_EXCEPTION:
ctx.obj['logger'].info(f"TMDB_API_KEY not set: Skipping {SCEN.__class__.__name__}")
@ffx.command()
@click.pass_context

Loading…
Cancel
Save