From a6be191fbe9501df3c56f1f212994a8f67cb8609 Mon Sep 17 00:00:00 2001 From: oskvr37 Date: Fri, 7 Feb 2025 17:04:21 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20add=20`formatResource`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tiddl/config.py | 1 + tiddl/models/resource.py | 4 +-- tiddl/utils.py | 77 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/tiddl/config.py b/tiddl/config.py index f7684e0..145c22b 100644 --- a/tiddl/config.py +++ b/tiddl/config.py @@ -10,6 +10,7 @@ CONFIG_INDENT = 2 class TemplateConfig(BaseModel): track: str = "{artist} - {title}" + video: str = "{artist} - {title}" album: str = "{album_artist}/{album}/{number:02d}. {title}" playlist: str = "{playlist}/{playlist_number:02d}. {artist} - {title}" diff --git a/tiddl/models/resource.py b/tiddl/models/resource.py index e6b96d5..02d5e38 100644 --- a/tiddl/models/resource.py +++ b/tiddl/models/resource.py @@ -73,7 +73,7 @@ class Video(BaseModel): title: str volumeNumber: int trackNumber: int - releaseDate: str + streamStartDate: Optional[datetime] = None imagePath: Optional[str] = None imageId: str vibrantColor: str @@ -83,7 +83,7 @@ class Video(BaseModel): adSupportedStreamReady: bool djReady: bool stemReady: bool - streamStartDate: str + streamStartDate: Optional[datetime] = None allowStreaming: bool explicit: bool popularity: int diff --git a/tiddl/utils.py b/tiddl/utils.py index 4897080..a72bbb0 100644 --- a/tiddl/utils.py +++ b/tiddl/utils.py @@ -7,10 +7,10 @@ from pydantic import BaseModel from urllib.parse import urlparse from pathlib import Path -from typing import Literal, get_args +from typing import Literal, Union, get_args from tiddl.models.constants import TrackQuality, QUALITY_TO_ARG -from tiddl.models.resource import Track +from tiddl.models.resource import Track, Video ResourceTypeLiteral = Literal["track", "album", "playlist", "artist"] @@ -79,7 +79,9 @@ def formatTrack( "disc": track.volumeNumber, "date": (track.streamStartDate if track.streamStartDate else ""), # i think we can remove year as we are able to format date - "year": track.streamStartDate.strftime("%Y") if track.streamStartDate else "", + "year": track.streamStartDate.strftime("%Y") + if track.streamStartDate + else "", "playlist": sanitizeString(playlist_title), "bpm": track.bpm or "", "quality": QUALITY_TO_ARG[track.audioQuality], @@ -100,6 +102,69 @@ def formatTrack( return formatted_track +def formatResource( + template: str, + resource: Union[Track, Video], + album_artist="", + playlist_title="", + playlist_index=0, +) -> str: + artist = sanitizeString(resource.artist.name) if resource.artist else "" + + features = [ + sanitizeString(item_artist.name) + for item_artist in resource.artists + if item_artist.name != artist + ] + + resource_dict = { + "id": str(resource.id), + "title": sanitizeString(resource.title), + "artist": artist, + "artists": ", ".join(features + [artist]), + "features": ", ".join(features), + "album": sanitizeString(resource.album.title if resource.album else ""), + "number": resource.trackNumber, + "disc": resource.volumeNumber, + "date": (resource.streamStartDate if resource.streamStartDate else ""), + # i think we can remove year as we are able to format date + "year": resource.streamStartDate.strftime("%Y") + if resource.streamStartDate + else "", + "playlist": sanitizeString(playlist_title), + "album_artist": sanitizeString(album_artist), + "playlist_number": playlist_index or 0, + "quality": "", + "version": "", + "bpm": "", + } + + if isinstance(resource, Track): + resource_dict.update( + { + "version": sanitizeString(resource.version or ""), + "quality": QUALITY_TO_ARG[resource.audioQuality], + "bpm": resource.bpm or "", + } + ) + + elif isinstance(resource, Video): + resource_dict.update({"quality": resource.quality}) + + formatted_template = template.format(**resource_dict) + + disallowed_chars = r'[\\:"*?<>|]+' + invalid_chars = re.findall(disallowed_chars, formatted_template) + + if invalid_chars: + raise ValueError( + f"Template '{template}' and formatted resource '{formatted_template}'" + f"contains disallowed characters: {' '.join(sorted(set(invalid_chars)))}" + ) + + return formatted_template + + def trackExists( track_quality: TrackQuality, download_quality: TrackQuality, file_name: Path ): @@ -151,9 +216,9 @@ def convertFileExtension( if is_video: ffmpeg_args["c:v"] = "copy" - ffmpeg.input(str(source_file)).output( - str(output_file), **ffmpeg_args - ).run(overwrite_output=1) + ffmpeg.input(str(source_file)).output(str(output_file), **ffmpeg_args).run( + overwrite_output=1 + ) if remove_source: os.remove(source_file)