From 7c12af960bbdb96be64e10e168cc2dff30d80916 Mon Sep 17 00:00:00 2001 From: WorldObservationLog Date: Sat, 4 May 2024 21:24:41 +0800 Subject: [PATCH] fix: validation error when missing some fields of metadata --- src/metadata.py | 36 +++++---- src/models/album_meta.py | 152 ++++++++++++++++++------------------ src/models/playlist_meta.py | 138 ++++++++++++++++---------------- src/models/song_data.py | 148 +++++++++++++++++------------------ src/models/song_lyrics.py | 16 ++-- src/models/tracks_meta.py | 66 ++++++++-------- 6 files changed, 280 insertions(+), 276 deletions(-) diff --git a/src/metadata.py b/src/metadata.py index dbd969b..d7ce150 100644 --- a/src/metadata.py +++ b/src/metadata.py @@ -1,3 +1,5 @@ +from typing import Optional + from pydantic import BaseModel from src.api import get_cover @@ -6,27 +8,29 @@ from src.utils import ttml_convent_to_lrc class SongMetadata(BaseModel): - title: str - artist: str - album_artist: str - album: str - composer: str - genre: str - created: str - track: str - tracknum: int - disk: int - lyrics: str + title: Optional[str] = None + artist: Optional[str] = None + album_artist: Optional[str] = None + album: Optional[str] = None + composer: Optional[str] = None + genre: Optional[str] = None + created: Optional[str] = None + track: Optional[str] = None + tracknum: Optional[int] = None + disk: Optional[int] = None + lyrics: Optional[str] = None cover: bytes = None - cover_url: str - copyright: str - record_company: str - upc: str - isrc: str + cover_url: Optional[str] = None + copyright: Optional[str] = None + record_company: Optional[str] = None + upc: Optional[str] = None + isrc: Optional[str] = None def to_itags_params(self, embed_metadata: list[str], cover_format: str): tags = [] for key, value in self.model_dump().items(): + if not value: + continue if key in embed_metadata and value: if key == "cover": continue diff --git a/src/models/album_meta.py b/src/models/album_meta.py index dca36bf..6dffdc5 100644 --- a/src/models/album_meta.py +++ b/src/models/album_meta.py @@ -1,106 +1,106 @@ from __future__ import annotations -from typing import List +from typing import List, Optional from pydantic import BaseModel, Field class Artwork(BaseModel): - width: int - url: str - height: int - textColor3: str - textColor2: str - textColor4: str - textColor1: str - bgColor: str - hasP3: bool + width: Optional[int] = None + url: Optional[str] = None + height: Optional[int] = None + textColor3: Optional[str] = None + textColor2: Optional[str] = None + textColor4: Optional[str] = None + textColor1: Optional[str] = None + bgColor: Optional[str] = None + hasP3: Optional[bool] = None class PlayParams(BaseModel): - id: str - kind: str + id: Optional[str] = None + kind: Optional[str] = None class Attributes(BaseModel): - copyright: str - genreNames: List[str] - releaseDate: str - upc: str - isMasteredForItunes: bool + copyright: Optional[str] = None + genreNames: List[Optional[str]] = None + releaseDate: Optional[str] = None + upc: Optional[str] = None + isMasteredForItunes: Optional[bool] = None artwork: Artwork - url: str + url: Optional[str] = None playParams: PlayParams - recordLabel: str - isCompilation: bool - trackCount: int - isPrerelease: bool - audioTraits: List[str] - isSingle: bool - name: str - artistName: str - isComplete: bool + recordLabel: Optional[str] = None + isCompilation: Optional[bool] = None + trackCount: Optional[int] = None + isPrerelease: Optional[bool] = None + audioTraits: List[Optional[str]] = None + isSingle: Optional[bool] = None + name: Optional[str] = None + artistName: Optional[str] = None + isComplete: Optional[bool] = None class Artwork1(BaseModel): - width: int - url: str - height: int - textColor3: str - textColor2: str - textColor4: str - textColor1: str - bgColor: str - hasP3: bool + width: Optional[int] = None + url: Optional[str] = None + height: Optional[int] = None + textColor3: Optional[str] = None + textColor2: Optional[str] = None + textColor4: Optional[str] = None + textColor1: Optional[str] = None + bgColor: Optional[str] = None + hasP3: Optional[bool] = None class PlayParams1(BaseModel): - id: str - kind: str + id: Optional[str] = None + kind: Optional[str] = None class Preview(BaseModel): - url: str + url: Optional[str] = None class Attributes1(BaseModel): - hasTimeSyncedLyrics: bool - albumName: str - genreNames: List[str] - trackNumber: int - durationInMillis: int - releaseDate: str - isVocalAttenuationAllowed: bool - isMasteredForItunes: bool - isrc: str + hasTimeSyncedLyrics: Optional[bool] = None + albumName: Optional[str] = None + genreNames: List[Optional[str]] = None + trackNumber: Optional[int] = None + durationInMillis: Optional[int] = None + releaseDate: Optional[str] = None + isVocalAttenuationAllowed: Optional[bool] = None + isMasteredForItunes: Optional[bool] = None + isrc: Optional[str] = None artwork: Artwork1 - composerName: str - audioLocale: str + composerName: Optional[str] = None + audioLocale: Optional[str] = None playParams: PlayParams1 - url: str - discNumber: int - hasCredits: bool - isAppleDigitalMaster: bool - hasLyrics: bool - audioTraits: List[str] - name: str + url: Optional[str] = None + discNumber: Optional[int] = None + hasCredits: Optional[bool] = None + isAppleDigitalMaster: Optional[bool] = None + hasLyrics: Optional[bool] = None + audioTraits: List[Optional[str]] = None + name: Optional[str] = None previews: List[Preview] - artistName: str + artistName: Optional[str] = None class Attributes2(BaseModel): - name: str + name: Optional[str] = None class Datum2(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes2 class Artists(BaseModel): - href: str + href: Optional[str] = None data: List[Datum2] @@ -109,36 +109,36 @@ class Relationships1(BaseModel): class Datum1(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes1 relationships: Relationships1 class Tracks(BaseModel): - href: str + href: Optional[str] = None data: List[Datum1] class Attributes3(BaseModel): - name: str + name: Optional[str] = None class Datum3(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes3 class Artists1(BaseModel): - href: str + href: Optional[str] = None data: List[Datum3] class RecordLabels(BaseModel): - href: str + href: Optional[str] = None data: List @@ -149,9 +149,9 @@ class Relationships(BaseModel): class Datum(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes relationships: Relationships diff --git a/src/models/playlist_meta.py b/src/models/playlist_meta.py index 3d58837..751e85e 100644 --- a/src/models/playlist_meta.py +++ b/src/models/playlist_meta.py @@ -6,110 +6,110 @@ from pydantic import BaseModel class Description(BaseModel): - standard: str - short: str + standard: Optional[str] = None + short: Optional[str] = None class Artwork(BaseModel): - width: int - url: str - height: int - textColor3: str - textColor2: str - textColor4: str - textColor1: str - bgColor: str - hasP3: bool + width: Optional[int] = None + url: Optional[str] = None + height: Optional[int] = None + textColor3: Optional[str] = None + textColor2: Optional[str] = None + textColor4: Optional[str] = None + textColor1: Optional[str] = None + bgColor: Optional[str] = None + hasP3: Optional[bool] = None class PlayParams(BaseModel): - id: str - kind: str - versionHash: str + id: Optional[str] = None + kind: Optional[str] = None + versionHash: Optional[str] = None class EditorialNotes(BaseModel): - name: str - standard: str - short: str + name: Optional[str] = None + standard: Optional[str] = None + short: Optional[str] = None class Attributes(BaseModel): - lastModifiedDate: str - supportsSing: bool + lastModifiedDate: Optional[str] = None + supportsSing: Optional[bool] = None description: Description artwork: Artwork playParams: PlayParams - url: str - hasCollaboration: bool - curatorName: str + url: Optional[str] = None + hasCollaboration: Optional[bool] = None + curatorName: Optional[str] = None audioTraits: List - name: str - isChart: bool - playlistType: str + name: Optional[str] = None + isChart: Optional[bool] = None + playlistType: Optional[str] = None editorialNotes: EditorialNotes artistName: Optional[str] = None class Artwork1(BaseModel): - width: int - url: str - height: int - textColor3: str - textColor2: str - textColor4: str - textColor1: str - bgColor: str - hasP3: bool + width: Optional[int] = None + url: Optional[str] = None + height: Optional[int] = None + textColor3: Optional[str] = None + textColor2: Optional[str] = None + textColor4: Optional[str] = None + textColor1: Optional[str] = None + bgColor: Optional[str] = None + hasP3: Optional[bool] = None class PlayParams1(BaseModel): - id: str - kind: str + id: Optional[str] = None + kind: Optional[str] = None class Preview(BaseModel): - url: str + url: Optional[str] = None class Attributes1(BaseModel): - albumName: str - hasTimeSyncedLyrics: bool - genreNames: List[str] - trackNumber: int - releaseDate: str - durationInMillis: int - isVocalAttenuationAllowed: bool - isMasteredForItunes: bool - isrc: str + albumName: Optional[str] = None + hasTimeSyncedLyrics: Optional[bool] = None + genreNames: List[Optional[str]] = None + trackNumber: Optional[int] = None + releaseDate: Optional[str] = None + durationInMillis: Optional[int] = None + isVocalAttenuationAllowed: Optional[bool] = None + isMasteredForItunes: Optional[bool] = None + isrc: Optional[str] = None artwork: Artwork1 - composerName: str - audioLocale: str - url: str + composerName: Optional[str] = None + audioLocale: Optional[str] = None + url: Optional[str] = None playParams: PlayParams1 - discNumber: int - hasCredits: bool - hasLyrics: bool - isAppleDigitalMaster: bool - audioTraits: List[str] - name: str + discNumber: Optional[int] = None + hasCredits: Optional[bool] = None + hasLyrics: Optional[bool] = None + isAppleDigitalMaster: Optional[bool] = None + audioTraits: List[Optional[str]] = None + name: Optional[str] = None previews: List[Preview] - artistName: str + artistName: Optional[str] = None class Attributes2(BaseModel): - name: str + name: Optional[str] = None class Datum2(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes2 class Artists(BaseModel): - href: str + href: Optional[str] = None data: List[Datum2] @@ -118,16 +118,16 @@ class Relationships1(BaseModel): class Datum1(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes1 relationships: Relationships1 class Tracks(BaseModel): - href: str - next: Optional[str] = None + href: Optional[str] = None + next: Optional[Optional[str]] = None data: List[Datum1] @@ -136,9 +136,9 @@ class Relationships(BaseModel): class Datum(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes relationships: Relationships diff --git a/src/models/song_data.py b/src/models/song_data.py index 99f514b..9584d6f 100644 --- a/src/models/song_data.py +++ b/src/models/song_data.py @@ -1,122 +1,122 @@ from __future__ import annotations -from typing import List +from typing import List, Optional from pydantic import BaseModel class Artwork(BaseModel): - width: int - url: str - height: int - textColor3: str - textColor2: str - textColor4: str - textColor1: str - bgColor: str - hasP3: bool + width: Optional[int] = None + url: Optional[str] = None + height: Optional[int] = None + textColor3: Optional[str] = None + textColor2: Optional[str] = None + textColor4: Optional[str] = None + textColor1: Optional[str] = None + bgColor: Optional[str] = None + hasP3: Optional[bool] = None class PlayParams(BaseModel): - id: str - kind: str + id: Optional[str] = None + kind: Optional[str] = None class Preview(BaseModel): - url: str + url: Optional[str] = None class ExtendedAssetUrls(BaseModel): - plus: str - lightweight: str - superLightweight: str - lightweightPlus: str - enhancedHls: str + plus: Optional[str] = None + lightweight: Optional[str] = None + superLightweight: Optional[str] = None + lightweightPlus: Optional[str] = None + enhancedHls: Optional[str] = None class Attributes(BaseModel): - hasTimeSyncedLyrics: bool - albumName: str - genreNames: List[str] - trackNumber: int - durationInMillis: int - releaseDate: str - isVocalAttenuationAllowed: bool - isMasteredForItunes: bool - isrc: str + hasTimeSyncedLyrics: Optional[bool] = None + albumName: Optional[str] = None + genreNames: List[Optional[str]] = None + trackNumber: Optional[int] = None + durationInMillis: Optional[int] = None + releaseDate: Optional[str] = None + isVocalAttenuationAllowed: Optional[bool] = None + isMasteredForItunes: Optional[bool] = None + isrc: Optional[str] = None artwork: Artwork - composerName: str - audioLocale: str - url: str + composerName: Optional[str] = None + audioLocale: Optional[str] = None + url: Optional[str] = None playParams: PlayParams - discNumber: int - hasCredits: bool - isAppleDigitalMaster: bool - hasLyrics: bool - audioTraits: List[str] - name: str + discNumber: Optional[int] = None + hasCredits: Optional[bool] = None + isAppleDigitalMaster: Optional[bool] = None + hasLyrics: Optional[bool] = None + audioTraits: List[Optional[str]] = None + name: Optional[str] = None previews: List[Preview] - artistName: str + artistName: Optional[str] = None extendedAssetUrls: ExtendedAssetUrls class Artwork1(BaseModel): - width: int - url: str - height: int - textColor3: str - textColor2: str - textColor4: str - textColor1: str - bgColor: str - hasP3: bool + width: Optional[int] = None + url: Optional[str] = None + height: Optional[int] = None + textColor3: Optional[str] = None + textColor2: Optional[str] = None + textColor4: Optional[str] = None + textColor1: Optional[str] = None + bgColor: Optional[str] = None + hasP3: Optional[bool] = None class PlayParams1(BaseModel): - id: str - kind: str + id: Optional[str] = None + kind: Optional[str] = None class Attributes1(BaseModel): - copyright: str - genreNames: List[str] - releaseDate: str - isMasteredForItunes: bool - upc: str + copyright: Optional[str] = None + genreNames: List[Optional[str]] = None + releaseDate: Optional[str] = None + isMasteredForItunes: Optional[bool] = None + upc: Optional[str] = None artwork: Artwork1 - url: str + url: Optional[str] = None playParams: PlayParams1 - recordLabel: str - isCompilation: bool - trackCount: int - isPrerelease: bool - audioTraits: List[str] - isSingle: bool - name: str - artistName: str - isComplete: bool + recordLabel: Optional[str] = None + isCompilation: Optional[bool] = None + trackCount: Optional[int] = None + isPrerelease: Optional[bool] = None + audioTraits: List[Optional[str]] = None + isSingle: Optional[bool] = None + name: Optional[str] = None + artistName: Optional[str] = None + isComplete: Optional[bool] = None class Datum1(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes1 class Albums(BaseModel): - href: str + href: Optional[str] = None data: List[Datum1] class Datum2(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None class Artists(BaseModel): - href: str + href: Optional[str] = None data: List[Datum2] @@ -126,9 +126,9 @@ class Relationships(BaseModel): class Datum(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes relationships: Relationships diff --git a/src/models/song_lyrics.py b/src/models/song_lyrics.py index 45b920c..753792c 100644 --- a/src/models/song_lyrics.py +++ b/src/models/song_lyrics.py @@ -1,23 +1,23 @@ -from typing import List +from typing import List, Optional from pydantic import BaseModel class PlayParams(BaseModel): - id: str - kind: str - catalogId: str - displayType: int + id: Optional[str] = None + kind: Optional[str] = None + catalogId: Optional[str] = None + displayType: Optional[int] = None class Attributes(BaseModel): - ttml: str + ttml: Optional[str] = None playParams: PlayParams class Datum(BaseModel): - id: str - type: str + id: Optional[str] = None + type: Optional[str] = None attributes: Attributes diff --git a/src/models/tracks_meta.py b/src/models/tracks_meta.py index 3987b31..220cacb 100644 --- a/src/models/tracks_meta.py +++ b/src/models/tracks_meta.py @@ -6,55 +6,55 @@ from pydantic import BaseModel class Artwork(BaseModel): - width: int - url: str - height: int - textColor3: str - textColor2: str - textColor4: str - textColor1: str - bgColor: str - hasP3: bool + width: Optional[int] = None + url: Optional[str] = None + height: Optional[int] = None + textColor3: Optional[str] = None + textColor2: Optional[str] = None + textColor4: Optional[str] = None + textColor1: Optional[str] = None + bgColor: Optional[str] = None + hasP3: Optional[bool] = None class PlayParams(BaseModel): - id: str - kind: str + id: Optional[str] = None + kind: Optional[str] = None class Preview(BaseModel): - url: str + url: Optional[str] = None class Attributes(BaseModel): - hasTimeSyncedLyrics: bool - albumName: str - genreNames: List[str] - trackNumber: int - releaseDate: str - durationInMillis: int - isVocalAttenuationAllowed: bool - isMasteredForItunes: bool - isrc: str + hasTimeSyncedLyrics: Optional[bool] = None + albumName: Optional[str] = None + genreNames: List[Optional[str]] = None + trackNumber: Optional[int] = None + releaseDate: Optional[str] = None + durationInMillis: Optional[int] = None + isVocalAttenuationAllowed: Optional[bool] = None + isMasteredForItunes: Optional[bool] = None + isrc: Optional[str] = None artwork: Artwork composerName: Optional[str] = None - audioLocale: str - url: str + audioLocale: Optional[str] = None + url: Optional[str] = None playParams: PlayParams - discNumber: int - hasCredits: bool - isAppleDigitalMaster: bool - hasLyrics: bool - audioTraits: List[str] - name: str + discNumber: Optional[int] = None + hasCredits: Optional[bool] = None + isAppleDigitalMaster: Optional[bool] = None + hasLyrics: Optional[bool] = None + audioTraits: Optional[str] = None + name: Optional[str] = None previews: List[Preview] - artistName: str + artistName: Optional[str] = None class Datum(BaseModel): - id: str - type: str - href: str + id: Optional[str] = None + type: Optional[str] = None + href: Optional[str] = None attributes: Attributes