124
bin/ffx.py
124
bin/ffx.py
@@ -14,6 +14,8 @@ from ffx.database import databaseContext
|
|||||||
|
|
||||||
from ffx.media_descriptor import MediaDescriptor
|
from ffx.media_descriptor import MediaDescriptor
|
||||||
from ffx.track_descriptor import TrackDescriptor
|
from ffx.track_descriptor import TrackDescriptor
|
||||||
|
from ffx.show_descriptor import ShowDescriptor
|
||||||
|
|
||||||
from ffx.track_type import TrackType
|
from ffx.track_type import TrackType
|
||||||
from ffx.video_encoder import VideoEncoder
|
from ffx.video_encoder import VideoEncoder
|
||||||
from ffx.track_disposition import TrackDisposition
|
from ffx.track_disposition import TrackDisposition
|
||||||
@@ -299,9 +301,11 @@ def checkUniqueDispositions(context, mediaDescriptor: MediaDescriptor):
|
|||||||
@click.option('--denoise-research-window', type=str, default='', help='Range to search for comparable patches on luminosity plane. Better filtering but costly.')
|
@click.option('--denoise-research-window', type=str, default='', help='Range to search for comparable patches on luminosity plane. Better filtering but costly.')
|
||||||
@click.option('--denoise-chroma-research-window', type=str, default='', help='Range to search for comparable patches on chroma planes.')
|
@click.option('--denoise-chroma-research-window', type=str, default='', help='Range to search for comparable patches on chroma planes.')
|
||||||
|
|
||||||
|
@click.option('--show', type=int, default=-1, help='Set TMDB show identifier')
|
||||||
|
@click.option('--season', type=int, default=-1, help='Set season of show')
|
||||||
|
@click.option('--episode', type=int, default=-1, help='Set episode of show')
|
||||||
|
|
||||||
@click.option("--no-tmdb", is_flag=True, default=False)
|
@click.option("--no-tmdb", is_flag=True, default=False)
|
||||||
# @click.option("--no-jellyfin", is_flag=True, default=False)
|
|
||||||
@click.option("--no-pattern", is_flag=True, default=False)
|
@click.option("--no-pattern", is_flag=True, default=False)
|
||||||
|
|
||||||
@click.option("--dont-pass-dispositions", is_flag=True, default=False)
|
@click.option("--dont-pass-dispositions", is_flag=True, default=False)
|
||||||
@@ -346,6 +350,10 @@ def convert(ctx,
|
|||||||
denoise_research_window,
|
denoise_research_window,
|
||||||
denoise_chroma_research_window,
|
denoise_chroma_research_window,
|
||||||
|
|
||||||
|
show,
|
||||||
|
season,
|
||||||
|
episode,
|
||||||
|
|
||||||
no_tmdb,
|
no_tmdb,
|
||||||
# no_jellyfin,
|
# no_jellyfin,
|
||||||
no_pattern,
|
no_pattern,
|
||||||
@@ -389,6 +397,11 @@ def convert(ctx,
|
|||||||
context['subtitle_prefix'] = subtitle_prefix
|
context['subtitle_prefix'] = subtitle_prefix
|
||||||
|
|
||||||
|
|
||||||
|
existingSourcePaths = [p for p in paths if os.path.isfile(p) and p.split('.')[-1] in FfxController.INPUT_FILE_EXTENSIONS]
|
||||||
|
|
||||||
|
|
||||||
|
# CLI Overrides
|
||||||
|
|
||||||
cliOverrides = {}
|
cliOverrides = {}
|
||||||
|
|
||||||
if language:
|
if language:
|
||||||
@@ -426,6 +439,18 @@ def convert(ctx,
|
|||||||
if forced_subtitle != -1:
|
if forced_subtitle != -1:
|
||||||
cliOverrides['forced_subtitle'] = forced_subtitle
|
cliOverrides['forced_subtitle'] = forced_subtitle
|
||||||
|
|
||||||
|
if show != -1 or season != -1 or episode != -1:
|
||||||
|
if len(existingSourcePaths) > 1:
|
||||||
|
context['logger'].warning(f"Ignoring TMDB show, season, episode overrides, not supported for multiple source files")
|
||||||
|
else:
|
||||||
|
cliOverrides['tmdb'] = {}
|
||||||
|
if show != -1:
|
||||||
|
cliOverrides['tmdb']['show'] = show
|
||||||
|
if season != -1:
|
||||||
|
cliOverrides['tmdb']['season'] = season
|
||||||
|
if episode != -1:
|
||||||
|
cliOverrides['tmdb']['episode'] = episode
|
||||||
|
|
||||||
if cliOverrides:
|
if cliOverrides:
|
||||||
context['overrides'] = cliOverrides
|
context['overrides'] = cliOverrides
|
||||||
|
|
||||||
@@ -468,7 +493,7 @@ def convert(ctx,
|
|||||||
|
|
||||||
tc = TmdbController() if context['use_tmdb'] else None
|
tc = TmdbController() if context['use_tmdb'] else None
|
||||||
|
|
||||||
existingSourcePaths = [p for p in paths if os.path.isfile(p) and p.split('.')[-1] in FfxController.INPUT_FILE_EXTENSIONS]
|
|
||||||
ctx.obj['logger'].info(f"\nRunning {len(existingSourcePaths) * len(q_list)} jobs")
|
ctx.obj['logger'].info(f"\nRunning {len(existingSourcePaths) * len(q_list)} jobs")
|
||||||
|
|
||||||
jobIndex = 0
|
jobIndex = 0
|
||||||
@@ -487,6 +512,15 @@ def convert(ctx,
|
|||||||
|
|
||||||
|
|
||||||
mediaFileProperties = FileProperties(context, sourceFilename)
|
mediaFileProperties = FileProperties(context, sourceFilename)
|
||||||
|
|
||||||
|
#HINT: -1 if not set
|
||||||
|
showSeason = (cliOverrides['tmdb']['season'] if 'tmdb' in cliOverrides.keys()
|
||||||
|
and 'season' in cliOverrides['tmdb'] else mediaFileProperties.getSeason())
|
||||||
|
showEpisode = (cliOverrides['tmdb']['episode'] if 'tmdb' in cliOverrides.keys()
|
||||||
|
and 'episode' in cliOverrides['tmdb'] else mediaFileProperties.getEpisode())
|
||||||
|
ctx.obj['logger'].debug(f"Season={showSeason} Episode={showEpisode}")
|
||||||
|
|
||||||
|
|
||||||
sourceMediaDescriptor = mediaFileProperties.getMediaDescriptor()
|
sourceMediaDescriptor = mediaFileProperties.getMediaDescriptor()
|
||||||
|
|
||||||
#HINT: This is None if the filename did not match anything in database
|
#HINT: This is None if the filename did not match anything in database
|
||||||
@@ -494,80 +528,84 @@ def convert(ctx,
|
|||||||
|
|
||||||
ctx.obj['logger'].debug(f"Pattern matching: {'No' if currentPattern is None else 'Yes'}")
|
ctx.obj['logger'].debug(f"Pattern matching: {'No' if currentPattern is None else 'Yes'}")
|
||||||
|
|
||||||
# fileBasename = ''
|
# Setup FfxController accordingly depending on pattern matching is enabled and a pattern was matched
|
||||||
|
|
||||||
if currentPattern is None:
|
if currentPattern is None:
|
||||||
|
|
||||||
# Case no pattern matching
|
|
||||||
|
|
||||||
# fileBasename = currentShowDescriptor.getFilenamePrefix()
|
|
||||||
|
|
||||||
checkUniqueDispositions(context, sourceMediaDescriptor)
|
checkUniqueDispositions(context, sourceMediaDescriptor)
|
||||||
|
currentShowDescriptor = None
|
||||||
|
|
||||||
if context['import_subtitles']:
|
if context['import_subtitles']:
|
||||||
sourceMediaDescriptor.importSubtitles(context['subtitle_directory'],
|
sourceMediaDescriptor.importSubtitles(context['subtitle_directory'],
|
||||||
context['subtitle_prefix'],
|
context['subtitle_prefix'],
|
||||||
mediaFileProperties.getSeason(),
|
showSeason,
|
||||||
mediaFileProperties.getEpisode())
|
showEpisode)
|
||||||
|
|
||||||
if cliOverrides:
|
if cliOverrides:
|
||||||
sourceMediaDescriptor.applyOverrides(cliOverrides)
|
sourceMediaDescriptor.applyOverrides(cliOverrides)
|
||||||
|
|
||||||
#YOLO
|
|
||||||
fc = FfxController(context, sourceMediaDescriptor)
|
fc = FfxController(context, sourceMediaDescriptor)
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
# Case pattern matching
|
|
||||||
|
|
||||||
targetMediaDescriptor = currentPattern.getMediaDescriptor(ctx.obj)
|
targetMediaDescriptor = currentPattern.getMediaDescriptor(ctx.obj)
|
||||||
|
|
||||||
checkUniqueDispositions(context, targetMediaDescriptor)
|
checkUniqueDispositions(context, targetMediaDescriptor)
|
||||||
|
|
||||||
|
|
||||||
currentShowDescriptor = currentPattern.getShowDescriptor(ctx.obj)
|
currentShowDescriptor = currentPattern.getShowDescriptor(ctx.obj)
|
||||||
|
|
||||||
|
|
||||||
if context['use_tmdb']:
|
|
||||||
|
|
||||||
ctx.obj['logger'].debug(f"Querying TMDB for show_id={currentShowDescriptor.getId()} season={mediaFileProperties.getSeason()} episode{mediaFileProperties.getEpisode()}")
|
|
||||||
tmdbEpisodeResult = tc.queryEpisode(currentShowDescriptor.getId(), mediaFileProperties.getSeason(), mediaFileProperties.getEpisode())
|
|
||||||
ctx.obj['logger'].debug(f"tmdbEpisodeResult={tmdbEpisodeResult}")
|
|
||||||
|
|
||||||
if tmdbEpisodeResult:
|
|
||||||
filteredEpisodeName = filterFilename(tmdbEpisodeResult['name'])
|
|
||||||
sourceFileBasename = TmdbController.getEpisodeFileBasename(currentShowDescriptor.getFilenamePrefix(),
|
|
||||||
filteredEpisodeName,
|
|
||||||
mediaFileProperties.getSeason(),
|
|
||||||
mediaFileProperties.getEpisode(),
|
|
||||||
currentShowDescriptor.getIndexSeasonDigits(),
|
|
||||||
currentShowDescriptor.getIndexEpisodeDigits(),
|
|
||||||
currentShowDescriptor.getIndicatorSeasonDigits(),
|
|
||||||
currentShowDescriptor.getIndicatorEpisodeDigits())
|
|
||||||
else:
|
|
||||||
sourceFileBasename = currentShowDescriptor.getFilenamePrefix()
|
|
||||||
|
|
||||||
if context['import_subtitles']:
|
if context['import_subtitles']:
|
||||||
targetMediaDescriptor.importSubtitles(context['subtitle_directory'],
|
targetMediaDescriptor.importSubtitles(context['subtitle_directory'],
|
||||||
context['subtitle_prefix'],
|
context['subtitle_prefix'],
|
||||||
mediaFileProperties.getSeason(),
|
showSeason,
|
||||||
mediaFileProperties.getEpisode())
|
showEpisode)
|
||||||
|
|
||||||
ctx.obj['logger'].debug(f"tmd subindices: {[t.getIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getSubIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getDispositionFlag(TrackDisposition.DEFAULT) for t in targetMediaDescriptor.getAllTrackDescriptors()]}")
|
ctx.obj['logger'].debug(f"tmd subindices: {[t.getIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getSubIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getDispositionFlag(TrackDisposition.DEFAULT) for t in targetMediaDescriptor.getAllTrackDescriptors()]}")
|
||||||
|
|
||||||
|
|
||||||
if cliOverrides:
|
if cliOverrides:
|
||||||
targetMediaDescriptor.applyOverrides(cliOverrides)
|
targetMediaDescriptor.applyOverrides(cliOverrides)
|
||||||
|
|
||||||
|
|
||||||
ctx.obj['logger'].debug(f"tmd subindices: {[t.getIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getSubIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getDispositionFlag(TrackDisposition.DEFAULT) for t in targetMediaDescriptor.getAllTrackDescriptors()]}")
|
ctx.obj['logger'].debug(f"tmd subindices: {[t.getIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getSubIndex() for t in targetMediaDescriptor.getAllTrackDescriptors()]} {[t.getDispositionFlag(TrackDisposition.DEFAULT) for t in targetMediaDescriptor.getAllTrackDescriptors()]}")
|
||||||
|
|
||||||
ctx.obj['logger'].debug(f"Input mapping tokens (2nd pass): {targetMediaDescriptor.getInputMappingTokens()}")
|
ctx.obj['logger'].debug(f"Input mapping tokens (2nd pass): {targetMediaDescriptor.getInputMappingTokens()}")
|
||||||
|
|
||||||
fc = FfxController(context, targetMediaDescriptor, sourceMediaDescriptor)
|
fc = FfxController(context, targetMediaDescriptor, sourceMediaDescriptor)
|
||||||
|
|
||||||
ctx.obj['logger'].debug(f"Season={mediaFileProperties.getSeason()} Episode={mediaFileProperties.getEpisode()}")
|
|
||||||
|
# Assemble target filename accordingly depending on TMDB lookup is enabled
|
||||||
|
#HINT: -1 if not set
|
||||||
|
showId = cliOverrides['tmdb']['show'] if 'tmdb' in cliOverrides.keys() and 'show' in cliOverrides['tmdb'] else (-1 if currentShowDescriptor is None else currentShowDescriptor.getId())
|
||||||
|
|
||||||
|
if context['use_tmdb'] and showId != -1 and showSeason != -1 and showEpisode != -1:
|
||||||
|
|
||||||
|
ctx.obj['logger'].debug(f"Querying TMDB for show_id={showId} season={showSeason} episode{showEpisode}")
|
||||||
|
|
||||||
|
if currentPattern is None:
|
||||||
|
sName, showYear = tc.getShowNameAndYear(showId)
|
||||||
|
showName = filterFilename(sName)
|
||||||
|
showFilenamePrefix = f"{showName} ({str(showYear)})"
|
||||||
|
indexSeasonDigits = ShowDescriptor.DEFAULT_INDEX_SEASON_DIGITS
|
||||||
|
indexEpisodeDigits = ShowDescriptor.DEFAULT_INDEX_EPISODE_DIGITS
|
||||||
|
indicatorSeasonDigits = ShowDescriptor.DEFAULT_INDICATOR_SEASON_DIGITS
|
||||||
|
indicatorEpisodeDigits = ShowDescriptor.DEFAULT_INDICATOR_EPISODE_DIGITS
|
||||||
|
else:
|
||||||
|
showFilenamePrefix = currentShowDescriptor.getFilenamePrefix()
|
||||||
|
indexSeasonDigits = currentShowDescriptor.getIndexSeasonDigits()
|
||||||
|
indexEpisodeDigits = currentShowDescriptor.getIndexEpisodeDigits()
|
||||||
|
indicatorSeasonDigits = currentShowDescriptor.getIndicatorSeasonDigits()
|
||||||
|
indicatorEpisodeDigits = currentShowDescriptor.getIndicatorEpisodeDigits()
|
||||||
|
|
||||||
|
tmdbEpisodeResult = tc.queryEpisode(showId, showSeason, showEpisode)
|
||||||
|
|
||||||
|
ctx.obj['logger'].debug(f"tmdbEpisodeResult={tmdbEpisodeResult}")
|
||||||
|
|
||||||
|
if tmdbEpisodeResult:
|
||||||
|
filteredEpisodeName = filterFilename(tmdbEpisodeResult['name'])
|
||||||
|
sourceFileBasename = TmdbController.getEpisodeFileBasename(showFilenamePrefix,
|
||||||
|
filteredEpisodeName,
|
||||||
|
showSeason,
|
||||||
|
showEpisode,
|
||||||
|
indexSeasonDigits,
|
||||||
|
indexEpisodeDigits,
|
||||||
|
indicatorSeasonDigits,
|
||||||
|
indicatorEpisodeDigits)
|
||||||
|
|
||||||
|
|
||||||
ctx.obj['logger'].debug(f"fileBasename={sourceFileBasename}")
|
ctx.obj['logger'].debug(f"fileBasename={sourceFileBasename}")
|
||||||
|
|
||||||
|
|||||||
@@ -122,23 +122,12 @@ class FfxController():
|
|||||||
|
|
||||||
audioTokens = []
|
audioTokens = []
|
||||||
|
|
||||||
#sourceAudioTrackDescriptors = [smd for smd in self.__sourceMediaDescriptor.getAllTrackDescriptors() if smd.getType() == TrackType.AUDIO]
|
|
||||||
# targetAudioTrackDescriptors = [rtd for rtd in self.__targetMediaDescriptor.getReorderedTrackDescriptors() if rtd.getType() == TrackType.AUDIO]
|
|
||||||
targetAudioTrackDescriptors = [td for td in self.__targetMediaDescriptor.getAllTrackDescriptors() if td.getType() == TrackType.AUDIO]
|
targetAudioTrackDescriptors = [td for td in self.__targetMediaDescriptor.getAllTrackDescriptors() if td.getType() == TrackType.AUDIO]
|
||||||
|
|
||||||
trackSubIndex = 0
|
trackSubIndex = 0
|
||||||
for trackDescriptor in targetAudioTrackDescriptors:
|
for trackDescriptor in targetAudioTrackDescriptors:
|
||||||
|
|
||||||
# Calculate source sub index
|
|
||||||
#changedTargetTrackDescriptor : TrackDescriptor = targetAudioTrackDescriptors[trackDescriptor.getIndex()]
|
|
||||||
#changedTargetTrackSourceIndex = changedTargetTrackDescriptor.getSourceIndex()
|
|
||||||
#sourceSubIndex = sourceAudioTrackDescriptors[changedTargetTrackSourceIndex].getSubIndex()
|
|
||||||
|
|
||||||
trackAudioLayout = trackDescriptor.getAudioLayout()
|
trackAudioLayout = trackDescriptor.getAudioLayout()
|
||||||
|
|
||||||
#TODO: Sollte nicht die sub index unverändert bleiben wenn jellyfin reordering angewendet wurde?
|
|
||||||
# siehe auch: MediaDescriptor.getInputMappingTokens()
|
|
||||||
#trackSubIndex = trackDescriptor.getSubIndex()
|
|
||||||
|
|
||||||
if trackAudioLayout == AudioLayout.LAYOUT_6_1:
|
if trackAudioLayout == AudioLayout.LAYOUT_6_1:
|
||||||
audioTokens += [f"-c:a:{trackSubIndex}",
|
audioTokens += [f"-c:a:{trackSubIndex}",
|
||||||
@@ -180,10 +169,6 @@ class FfxController():
|
|||||||
|
|
||||||
sourceTrackDescriptors = ([] if self.__sourceMediaDescriptor is None
|
sourceTrackDescriptors = ([] if self.__sourceMediaDescriptor is None
|
||||||
else self.__sourceMediaDescriptor.getAllTrackDescriptors())
|
else self.__sourceMediaDescriptor.getAllTrackDescriptors())
|
||||||
# if not self.__sourceMediaDescriptor is None:
|
|
||||||
# sourceTrackDescriptors = self.__sourceMediaDescriptor.getAllTrackDescriptors()
|
|
||||||
# else:
|
|
||||||
# sourceTrackDescriptors = []
|
|
||||||
|
|
||||||
dispositionTokens = []
|
dispositionTokens = []
|
||||||
|
|
||||||
@@ -274,12 +259,9 @@ class FfxController():
|
|||||||
+ self.__targetMediaDescriptor.getInputMappingTokens()
|
+ self.__targetMediaDescriptor.getInputMappingTokens()
|
||||||
+ self.generateDispositionTokens())
|
+ self.generateDispositionTokens())
|
||||||
|
|
||||||
if not self.__sourceMediaDescriptor is None or 'overrides' in self.__context.keys():
|
# Optional tokens
|
||||||
commandSequence += self.generateMetadataTokens()
|
commandSequence += self.generateMetadataTokens()
|
||||||
|
commandSequence += self.__context['denoiser'].generateDenoiseTokens()
|
||||||
# if denoise:
|
|
||||||
# commandSequence += self.generateDenoiseTokens()
|
|
||||||
commandSequence1 += self.__context['denoiser'].generateDenoiseTokens()
|
|
||||||
|
|
||||||
commandSequence += (self.generateAudioEncodingTokens()
|
commandSequence += (self.generateAudioEncodingTokens()
|
||||||
+ self.generateAV1Tokens(int(quality), int(preset))
|
+ self.generateAV1Tokens(int(quality), int(preset))
|
||||||
@@ -301,8 +283,16 @@ class FfxController():
|
|||||||
if videoEncoder == VideoEncoder.VP9:
|
if videoEncoder == VideoEncoder.VP9:
|
||||||
|
|
||||||
commandSequence1 = (commandTokens
|
commandSequence1 = (commandTokens
|
||||||
+ self.__targetMediaDescriptor.getInputMappingTokens(only_video=True)
|
+ self.__targetMediaDescriptor.getInputMappingTokens(only_video=True))
|
||||||
+ self.generateVP9Pass1Tokens(int(quality)))
|
|
||||||
|
# Optional tokens
|
||||||
|
#NOTE: Filters and so needs to run on the first pass as well, as here
|
||||||
|
# the required bitrate for the second run is determined and recorded
|
||||||
|
# TODO: Results seems to be slightly better with first pass omitted,
|
||||||
|
# Confirm or find better filter settings for 2-pass
|
||||||
|
# commandSequence1 += self.__context['denoiser'].generateDenoiseTokens()
|
||||||
|
|
||||||
|
commandSequence1 += self.generateVP9Pass1Tokens(int(quality))
|
||||||
|
|
||||||
if self.__context['perform_crop']:
|
if self.__context['perform_crop']:
|
||||||
commandSequence1 += self.generateCropTokens()
|
commandSequence1 += self.generateCropTokens()
|
||||||
@@ -322,11 +312,8 @@ class FfxController():
|
|||||||
+ self.__targetMediaDescriptor.getInputMappingTokens()
|
+ self.__targetMediaDescriptor.getInputMappingTokens()
|
||||||
+ self.generateDispositionTokens())
|
+ self.generateDispositionTokens())
|
||||||
|
|
||||||
if not self.__sourceMediaDescriptor is None or 'overrides' in self.__context.keys():
|
# Optional tokens
|
||||||
commandSequence2 += self.generateMetadataTokens()
|
commandSequence2 += self.generateMetadataTokens()
|
||||||
|
|
||||||
# if denoise:
|
|
||||||
# commandSequence2 += self.generateDenoiseTokens()
|
|
||||||
commandSequence2 += self.__context['denoiser'].generateDenoiseTokens()
|
commandSequence2 += self.__context['denoiser'].generateDenoiseTokens()
|
||||||
|
|
||||||
commandSequence2 += self.generateVP9Pass2Tokens(int(quality)) + self.generateAudioEncodingTokens()
|
commandSequence2 += self.generateVP9Pass2Tokens(int(quality)) + self.generateAudioEncodingTokens()
|
||||||
@@ -348,7 +335,7 @@ class FfxController():
|
|||||||
|
|
||||||
|
|
||||||
def createEmptyFile(self,
|
def createEmptyFile(self,
|
||||||
path: str = 'output.mp4',
|
path: str = 'empty.mkv',
|
||||||
sizeX: int = 1280,
|
sizeX: int = 1280,
|
||||||
sizeY: int = 720,
|
sizeY: int = 720,
|
||||||
rate: int = 25,
|
rate: int = 25,
|
||||||
|
|||||||
@@ -354,8 +354,7 @@ class ShowDetailsScreen(Screen):
|
|||||||
|
|
||||||
showDescriptor = self.getShowDescriptorFromInput()
|
showDescriptor = self.getShowDescriptorFromInput()
|
||||||
if not showDescriptor is None:
|
if not showDescriptor is None:
|
||||||
showResult = self.__tc.queryShow(showDescriptor.getId())
|
showName, showYear = self.__tc.getShowNameAndYear(showDescriptor.getId())
|
||||||
firstAirDate = datetime.strptime(showResult['first_air_date'], '%Y-%m-%d')
|
|
||||||
|
|
||||||
self.query_one("#name_input", Input).value = filterFilename(showResult['name'])
|
self.query_one("#name_input", Input).value = filterFilename(showName)
|
||||||
self.query_one("#year_input", Input).value = str(firstAirDate.year)
|
self.query_one("#year_input", Input).value = str(showYear)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import os, click, requests, json, time, logging
|
import os, click, requests, json, time, logging
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
class TMDB_REQUEST_EXCEPTION(Exception):
|
class TMDB_REQUEST_EXCEPTION(Exception):
|
||||||
def __init__(self, statusCode, statusMessage):
|
def __init__(self, statusCode, statusMessage):
|
||||||
@@ -95,6 +97,14 @@ class TmdbController():
|
|||||||
return self.getTmdbRequest(tmdbUrl)
|
return self.getTmdbRequest(tmdbUrl)
|
||||||
|
|
||||||
|
|
||||||
|
def getShowNameAndYear(self, showId: int):
|
||||||
|
|
||||||
|
showResult = self.queryShow(int(showId))
|
||||||
|
firstAirDate = datetime.strptime(showResult['first_air_date'], '%Y-%m-%d')
|
||||||
|
|
||||||
|
return str(showResult['name']), int(firstAirDate.year)
|
||||||
|
|
||||||
|
|
||||||
def queryEpisode(self, showId, season, episode):
|
def queryEpisode(self, showId, season, episode):
|
||||||
"""
|
"""
|
||||||
First level keys in the response object:
|
First level keys in the response object:
|
||||||
|
|||||||
Reference in New Issue
Block a user