[BACKEND] Refactor entry classes (#228)
This commit is contained in:
parent
5488501bed
commit
c7e9380fe0
5 changed files with 72 additions and 76 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from typing import final
|
||||||
|
|
||||||
|
|
||||||
class BaseEntry(ABC):
|
class BaseEntry(ABC):
|
||||||
|
|
@ -9,6 +11,9 @@ class BaseEntry(ABC):
|
||||||
Abstract entry object to represent anything download from ytdl (playlist metadata, media, etc).
|
Abstract entry object to represent anything download from ytdl (playlist metadata, media, etc).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# The ytdl extractor type that the entry represents
|
||||||
|
entry_extractor: str
|
||||||
|
|
||||||
def __init__(self, entry_dict: Dict, working_directory: str):
|
def __init__(self, entry_dict: Dict, working_directory: str):
|
||||||
"""
|
"""
|
||||||
Initialize the entry using ytdl metadata
|
Initialize the entry using ytdl metadata
|
||||||
|
|
@ -75,3 +80,33 @@ class BaseEntry(ABC):
|
||||||
|
|
||||||
self._additional_variables = dict(self._additional_variables, **variables_to_add)
|
self._additional_variables = dict(self._additional_variables, **variables_to_add)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def _added_variables(self) -> Dict[str, str]:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Dict of variables added to this entry
|
||||||
|
"""
|
||||||
|
return self._additional_variables
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def source_variables(cls) -> List[str]:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
List of all source variables
|
||||||
|
"""
|
||||||
|
property_names = [prop for prop in dir(cls) if isinstance(getattr(cls, prop), property)]
|
||||||
|
return property_names
|
||||||
|
|
||||||
|
@final
|
||||||
|
def to_dict(self) -> Dict[str, str]:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Dictionary containing all variables
|
||||||
|
"""
|
||||||
|
source_variable_dict = {
|
||||||
|
source_var: getattr(self, source_var) for source_var in self.source_variables()
|
||||||
|
}
|
||||||
|
return dict(source_variable_dict, **self._added_variables())
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ import copy
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import final
|
from typing import final
|
||||||
|
|
||||||
from ytdl_sub.entries.base_entry import BaseEntry
|
from ytdl_sub.entries.base_entry import BaseEntry
|
||||||
|
from ytdl_sub.entries.variables.entry_variables import BaseEntryVariables
|
||||||
from ytdl_sub.entries.variables.entry_variables import EntryVariables
|
from ytdl_sub.entries.variables.entry_variables import EntryVariables
|
||||||
from ytdl_sub.validators.audo_codec_validator import AUDIO_CODEC_EXTS
|
from ytdl_sub.validators.audo_codec_validator import AUDIO_CODEC_EXTS
|
||||||
|
|
||||||
|
|
@ -16,9 +16,6 @@ class Entry(EntryVariables, BaseEntry):
|
||||||
Entry object to represent a single media object returned from yt-dlp.
|
Entry object to represent a single media object returned from yt-dlp.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The ytdl extractor type that the entry represents
|
|
||||||
entry_extractor: str
|
|
||||||
|
|
||||||
def get_download_file_name(self) -> str:
|
def get_download_file_name(self) -> str:
|
||||||
"""
|
"""
|
||||||
Returns
|
Returns
|
||||||
|
|
@ -107,11 +104,26 @@ class Entry(EntryVariables, BaseEntry):
|
||||||
|
|
||||||
return file_exists
|
return file_exists
|
||||||
|
|
||||||
@final
|
|
||||||
def to_dict(self) -> Dict[str, str]:
|
class ParentEntry(BaseEntryVariables, BaseEntry):
|
||||||
|
"""
|
||||||
|
Entry to represent parent entry objects like a Channel or Playlist
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _get_thumbnail_url(self, thumbnail_id: str) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
|
Downloads a specific thumbnail from a YTDL entry's thumbnail list
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
thumbnail_id:
|
||||||
|
Id of the thumbnail defined in the parent's thumbnail
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
The variables in dictionary format
|
Desired thumbnail url if it exists. None if it does not.
|
||||||
"""
|
"""
|
||||||
return self._to_dict()
|
for thumbnail in self.kwargs_get("thumbnails", []):
|
||||||
|
if thumbnail["id"] == thumbnail_id:
|
||||||
|
return thumbnail["url"]
|
||||||
|
return None
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from ytdl_sub.entries.entry import Entry
|
from ytdl_sub.entries.entry import Entry
|
||||||
|
from ytdl_sub.entries.entry import ParentEntry
|
||||||
from ytdl_sub.entries.variables.soundcloud_variables import SoundcloudVariables
|
from ytdl_sub.entries.variables.soundcloud_variables import SoundcloudVariables
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -84,7 +85,7 @@ class SoundcloudAlbumTrack(SoundcloudTrack):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudAlbum(Entry):
|
class SoundcloudAlbum(ParentEntry):
|
||||||
"""
|
"""
|
||||||
Entry object to represent a Soundcloud album.
|
Entry object to represent a Soundcloud album.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
from typing import Dict
|
|
||||||
from typing import List
|
|
||||||
from typing import final
|
|
||||||
|
|
||||||
from yt_dlp.utils import sanitize_filename
|
from yt_dlp.utils import sanitize_filename
|
||||||
|
|
||||||
from ytdl_sub.entries.base_entry import BaseEntry
|
from ytdl_sub.entries.base_entry import BaseEntry
|
||||||
|
|
@ -18,7 +14,7 @@ def _pad(num: int, width: int = 2):
|
||||||
_days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
_days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||||
|
|
||||||
|
|
||||||
class SourceVariables:
|
class BaseEntryVariables:
|
||||||
"""
|
"""
|
||||||
Source variables are ``{variables}`` that contain metadata from downloaded media.
|
Source variables are ``{variables}`` that contain metadata from downloaded media.
|
||||||
These variables can be used with fields that expect
|
These variables can be used with fields that expect
|
||||||
|
|
@ -47,38 +43,6 @@ class SourceVariables:
|
||||||
"""
|
"""
|
||||||
return self.kwargs("extractor")
|
return self.kwargs("extractor")
|
||||||
|
|
||||||
def _added_variables(self: BaseEntry) -> Dict[str, str]:
|
|
||||||
"""
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Dict of variables added to this entry
|
|
||||||
"""
|
|
||||||
return self._additional_variables
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def source_variables(cls) -> List[str]:
|
|
||||||
"""
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
List of all source variables
|
|
||||||
"""
|
|
||||||
property_names = [prop for prop in dir(cls) if isinstance(getattr(cls, prop), property)]
|
|
||||||
return property_names
|
|
||||||
|
|
||||||
@final
|
|
||||||
def _to_dict(self) -> Dict[str, str]:
|
|
||||||
"""
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Dictionary containing all variables
|
|
||||||
"""
|
|
||||||
source_variable_dict = {
|
|
||||||
source_var: getattr(self, source_var) for source_var in self.source_variables()
|
|
||||||
}
|
|
||||||
return dict(source_variable_dict, **self._added_variables())
|
|
||||||
|
|
||||||
|
|
||||||
class EntryVariables(SourceVariables):
|
|
||||||
@property
|
@property
|
||||||
def title(self: BaseEntry) -> str:
|
def title(self: BaseEntry) -> str:
|
||||||
"""
|
"""
|
||||||
|
|
@ -109,6 +73,18 @@ class EntryVariables(SourceVariables):
|
||||||
"""
|
"""
|
||||||
return self.kwargs("webpage_url")
|
return self.kwargs("webpage_url")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def info_json_ext(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The "info.json" extension
|
||||||
|
"""
|
||||||
|
return "info.json"
|
||||||
|
|
||||||
|
|
||||||
|
class EntryVariables(BaseEntryVariables):
|
||||||
@property
|
@property
|
||||||
def ext(self: BaseEntry) -> str:
|
def ext(self: BaseEntry) -> str:
|
||||||
"""
|
"""
|
||||||
|
|
@ -314,13 +290,3 @@ class EntryVariables(SourceVariables):
|
||||||
The uploaded date formatted as YYYY-MM-DD
|
The uploaded date formatted as YYYY-MM-DD
|
||||||
"""
|
"""
|
||||||
return f"{self.upload_year}-{self.upload_month_padded}-{self.upload_day_padded}"
|
return f"{self.upload_year}-{self.upload_month_padded}-{self.upload_day_padded}"
|
||||||
|
|
||||||
@property
|
|
||||||
def info_json_ext(self) -> str:
|
|
||||||
"""
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
str
|
|
||||||
The "info.json" extension
|
|
||||||
"""
|
|
||||||
return "info.json"
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import os.path
|
import os.path
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from ytdl_sub.entries.entry import Entry
|
from ytdl_sub.entries.entry import Entry
|
||||||
|
from ytdl_sub.entries.entry import ParentEntry
|
||||||
from ytdl_sub.entries.variables.youtube_variables import YoutubeVideoVariables
|
from ytdl_sub.entries.variables.youtube_variables import YoutubeVideoVariables
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,27 +46,9 @@ class YoutubePlaylistVideo(YoutubeVideo):
|
||||||
return self.kwargs("playlist_count")
|
return self.kwargs("playlist_count")
|
||||||
|
|
||||||
|
|
||||||
class YoutubeChannel(Entry):
|
class YoutubeChannel(ParentEntry):
|
||||||
entry_extractor = "youtube:tab"
|
entry_extractor = "youtube:tab"
|
||||||
|
|
||||||
def _get_thumbnail_url(self, thumbnail_id: str) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
Downloads a specific thumbnail from a YTDL entry's thumbnail list
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
thumbnail_id:
|
|
||||||
Id of the thumbnail defined in the channel's thumbnail
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Desired thumbnail url if it exists. None if it does not.
|
|
||||||
"""
|
|
||||||
for thumbnail in self.kwargs("thumbnails"):
|
|
||||||
if thumbnail["id"] == thumbnail_id:
|
|
||||||
return thumbnail["url"]
|
|
||||||
return None
|
|
||||||
|
|
||||||
def avatar_thumbnail_url(self) -> str:
|
def avatar_thumbnail_url(self) -> str:
|
||||||
"""
|
"""
|
||||||
Returns
|
Returns
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue