5 Commits

Author SHA1 Message Date
Maveno
db7700a6b9 fix #409: Doppelter Show-Eintrag bei ffx inspect 2024-11-18 20:53:15 +01:00
Maveno
222234f978 hf fix tmdb filename filters 2024-11-18 18:37:31 +01:00
Maveno
3672474ff5 ff 2024-11-18 07:53:07 +01:00
Maveno
5ff0fc3fad hf Episodenteil Substitutionen 2024-11-18 07:51:23 +01:00
Maveno
554ca4cc03 v0.2.3 2024-11-17 18:25:22 +01:00
11 changed files with 108 additions and 36 deletions

View File

@@ -39,3 +39,10 @@ Signature, Tags cleaning, Bugfixes, Refactoring
### 0.2.2
CLI-Overrides
### 0.2.3
PyPi packaging
Templating output filename
Season shiftung
DB-Versionierung

View File

@@ -1,7 +1,7 @@
[project]
name = "ffx"
description = "FFX recoding and metadata managing tool"
version = "0.2.2"
version = "0.2.3"
license = {file = "LICENSE.md"}
dependencies = [
"requests",

View File

@@ -1,4 +1,4 @@
VERSION='0.2.2'
VERSION='0.2.3'
DATABASE_VERSION = 2
DEFAULT_QUALITY = 32

View File

@@ -22,7 +22,7 @@ from ffx.track_disposition import TrackDisposition
from ffx.track_codec import TrackCodec
from ffx.process import executeProcess
from ffx.helper import filterFilename
from ffx.helper import filterFilename, substituteTmdbFilename
from ffx.helper import getEpisodeFileBasename
from ffx.constants import DEFAULT_STEREO_BANDWIDTH, DEFAULT_AC3_BANDWIDTH, DEFAULT_DTS_BANDWIDTH, DEFAULT_7_1_BANDWIDTH
@@ -653,9 +653,9 @@ def convert(ctx,
ctx.obj['logger'].debug(f"tmdbEpisodeResult={tmdbEpisodeResult}")
if tmdbEpisodeResult:
filteredEpisodeName = filterFilename(tmdbEpisodeResult['name'])
substitutedEpisodeName = filterFilename(substituteTmdbFilename(tmdbEpisodeResult['name']))
sourceFileBasename = getEpisodeFileBasename(showFilenamePrefix,
filteredEpisodeName,
substitutedEpisodeName,
shiftedShowSeason,
shiftedShowEpisode,
indexSeasonDigits,

View File

@@ -1,4 +1,4 @@
import logging
import re, logging
from jinja2 import Environment, Undefined
from .constants import DEFAULT_OUTPUT_FILENAME_TEMPLATE
@@ -78,10 +78,7 @@ def filterFilename(fileName: str) -> str:
"""This filter replaces charactes from TMDB responses with characters
less problemating when using in filenames or removes them"""
# This appears in TMDB episode names
fileName = str(fileName).replace(' (*)', '')
fileName = str(fileName).replace('(*)', '')
fileName = str(fileName).replace('/', '-')
fileName = str(fileName).replace(':', ';')
fileName = str(fileName).replace('*', '')
fileName = str(fileName).replace("'", '')
@@ -89,6 +86,30 @@ def filterFilename(fileName: str) -> str:
return fileName.strip()
def substituteTmdbFilename(fileName: str) -> str:
"""If chaining this method with filterFilename use this one first as the latter will destroy some patterns"""
# This indicates filler episodes in TMDB episode names
fileName = str(fileName).replace(' (*)', '')
fileName = str(fileName).replace('(*)', '')
# This indicates the index of multi-episode files
episodePartMatch = re.search("\\(([0-9]+)\\)$", fileName)
if episodePartMatch is not None:
partSuffix = str(episodePartMatch.group(0))
partIndex = episodePartMatch.groups()[0]
fileName = str(fileName).replace(partSuffix, f"Teil {partIndex}")
# Also multi-episodes with first and last episode index
episodePartMatch = re.search("\\(([0-9]+)[-\\/]([0-9]+)\\)$", fileName)
if episodePartMatch is not None:
partSuffix = str(episodePartMatch.group(0))
partFirstIndex = episodePartMatch.groups()[0]
partLastIndex = episodePartMatch.groups()[1]
fileName = str(fileName).replace(partSuffix, f"Teil {partFirstIndex}-{partLastIndex}")
return fileName
def getEpisodeFileBasename(showName,
episodeName,

View File

@@ -15,6 +15,7 @@ from .show_details_screen import ShowDetailsScreen
from .pattern_details_screen import PatternDetailsScreen
from ffx.track_type import TrackType
from ffx.track_codec import TrackCodec
from ffx.model.track import Track
from ffx.track_disposition import TrackDisposition
@@ -36,7 +37,7 @@ class MediaDetailsScreen(Screen):
Grid {
grid-size: 5 8;
grid-rows: 8 2 2 2 8 2 2 8;
grid-rows: 8 2 2 2 2 8 2 2 8;
grid-columns: 25 25 120 10 75;
height: 100%;
width: 100%;
@@ -90,6 +91,10 @@ class MediaDetailsScreen(Screen):
border: solid green;
}
.purple {
tint: purple 40%;
}
.yellow {
tint: yellow 40%;
}
@@ -137,7 +142,25 @@ class MediaDetailsScreen(Screen):
self.loadProperties()
def getRowIndexFromShowId(self, showId : int) -> int:
def removeShow(self, showId : int = -1):
"""Remove show entry from DataTable.
Removes the <New show> entry if showId is not set"""
for rowKey, row in self.showsTable.rows.items(): # dict[RowKey, Row]
rowData = self.showsTable.get_row(rowKey)
try:
if (showId == -1 and rowData[0] == ' '
or showId == int(rowData[0])):
self.showsTable.remove_row(rowKey)
return
except:
continue
def getRowIndexFromShowId(self, showId : int = -1) -> int:
"""Find the index of the row where the value in the specified column matches the target_value."""
for rowKey, row in self.showsTable.rows.items(): # dict[RowKey, Row]
@@ -145,7 +168,8 @@ class MediaDetailsScreen(Screen):
rowData = self.showsTable.get_row(rowKey)
try:
if showId == int(rowData[0]):
if ((showId == -1 and rowData[0] == ' ')
or showId == int(rowData[0])):
return int(self.showsTable.get_row_index(rowKey))
except:
continue
@@ -378,33 +402,36 @@ class MediaDetailsScreen(Screen):
yield self.differencesTable
# 2
yield Static(" ", classes="four")
# 3
yield Static(" ")
yield Button("Substitute", id="pattern_button")
yield Static(" ", classes="two")
# 3
# 4
yield Static("Pattern")
yield Input(type="text", id='pattern_input', classes="two")
yield Static(" ")
# 4
# 5
yield Static(" ", classes="four")
# 5
# 6
yield Static("Media Tags")
yield self.mediaTagsTable
yield Static(" ")
# 6
# 7
yield Static(" ", classes="four")
# 7
# 8
yield Static(" ")
yield Button("Set Default", id="select_default_button")
yield Button("Set Forced", id="select_forced_button")
yield Static(" ")
# 8
# 9
yield Static("Streams")
yield self.tracksTable
yield Static(" ")
@@ -462,7 +489,7 @@ class MediaDetailsScreen(Screen):
kwargs[TrackDescriptor.INDEX_KEY] = int(selected_track_data[0])
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(selected_track_data[1])
kwargs[TrackDescriptor.SUB_INDEX_KEY] = int(selected_track_data[2])
kwargs[TrackDescriptor.CODEC_NAME_KEY] = int(selected_track_data[3])
kwargs[TrackDescriptor.CODEC_KEY] = TrackCodec.fromLabel(selected_track_data[3])
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.fromLabel(selected_track_data[4])
return TrackDescriptor(**kwargs)
@@ -473,11 +500,10 @@ class MediaDetailsScreen(Screen):
return None
def getSelectedShowDescriptor(self):
def getSelectedShowDescriptor(self) -> ShowDescriptor:
try:
# Fetch the currently selected row when 'Enter' is pressed
#selected_row_index = self.table.cursor_row
row_key, col_key = self.showsTable.coordinate_to_cell_key(self.showsTable.cursor_coordinate)
if row_key is not None:
@@ -501,6 +527,11 @@ class MediaDetailsScreen(Screen):
def handle_new_pattern(self, showDescriptor: ShowDescriptor):
if type(showDescriptor) is not ShowDescriptor:
raise TypeError("MediaDetailsScreen.handle_new_pattern(): Argument 'showDescriptor' has to be of type ShowDescriptor")
showRowIndex = self.getRowIndexFromShowId(showDescriptor.getId())
if showRowIndex is None:
show = (showDescriptor.getId(), showDescriptor.getName(), showDescriptor.getYear())
self.showsTable.add_row(*map(str, show))
@@ -508,6 +539,8 @@ class MediaDetailsScreen(Screen):
if showRowIndex is not None:
self.showsTable.move_cursor(row=showRowIndex)
self.removeShow()
patternDescriptor = self.getPatternDescriptorFromInput()
if patternDescriptor:
@@ -524,10 +557,11 @@ class MediaDetailsScreen(Screen):
def action_new_pattern(self):
try:
self.__currentMediaDescriptor.checkConfiguration()
except ValueError:
return
#TODO #427: Fehlermeldung in TUI
# try:
# self.__currentMediaDescriptor.checkConfiguration()
# except ValueError:
# return
selectedShowDescriptor = self.getSelectedShowDescriptor()

View File

@@ -491,13 +491,14 @@ class PatternDetailsScreen(Screen):
trackType = trackDescriptor.getType()
index = trackDescriptor.getIndex()
subIndex = trackDescriptor.getSubIndex()
codec = trackDescriptor.getCodec()
language = trackDescriptor.getLanguage()
title = trackDescriptor.getTitle()
row = (index,
trackType.label(),
subIndex,
" ",
codec.label(),
language.label(),
title,
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
@@ -512,7 +513,10 @@ class PatternDetailsScreen(Screen):
row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
self.tracksTable.update_cell(row_key, self.column_key_track_audio_layout, trackDescriptor.getAudioLayout().label())
self.tracksTable.update_cell(row_key, self.column_key_track_audio_layout,
trackDescriptor.getAudioLayout().label()
if trackDescriptor.getType() == TrackType.AUDIO else ' ')
self.tracksTable.update_cell(row_key, self.column_key_track_language, trackDescriptor.getLanguage().label())
self.tracksTable.update_cell(row_key, self.column_key_track_title, trackDescriptor.getTitle())
self.tracksTable.update_cell(row_key, self.column_key_track_default, 'Yes' if TrackDisposition.DEFAULT in trackDescriptor.getDispositionSet() else 'No')

View File

@@ -400,7 +400,7 @@ class ShowDetailsScreen(Screen):
yield Footer()
def getShowDescriptorFromInput(self):
def getShowDescriptorFromInput(self) -> ShowDescriptor:
kwargs = {}

View File

@@ -29,7 +29,7 @@ class TrackController():
s = self.Session()
track = Track(pattern_id = patId,
track_type = int(trackDescriptor.getType().index()),
codec_name = str(trackDescriptor.getCodec().label()),
codec_name = str(trackDescriptor.getCodec().identifier()),
index = int(trackDescriptor.getIndex()),
source_index = int(trackDescriptor.getSourceIndex()),
disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())),

View File

@@ -292,7 +292,11 @@ class TrackDetailsScreen(Screen):
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(self.query_one("#type_select", Select).value)
kwargs[TrackDescriptor.CODEC_KEY] = self.__trackCodec
if self.__trackType == TrackType.AUDIO:
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.fromLabel(self.query_one("#audio_layout_select", Select).value)
else:
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.LAYOUT_UNDEFINED
trackTags = {}
language = self.query_one("#language_select", Select).value

View File

@@ -2,6 +2,8 @@
. ~/.local/share/ffx.venv/bin/activate
pushd ~/.local/src/ffx/
git checkout main
git pull
pip install --editable .
popd
deactivate