Skip to content

Commit

Permalink
- allow for calling downloaders also as a string instead of passing t…
Browse files Browse the repository at this point in the history
…he object
  • Loading branch information
EchterAlsFake committed Jan 1, 2025
1 parent 0c953ab commit a389fd6
Showing 1 changed file with 47 additions and 34 deletions.
81 changes: 47 additions & 34 deletions src/phub/objects/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Video:
def __init__(self, client: Client, url: str, change_title_language: bool = False) -> None:
'''
Initialise a new video object.
Args:
client (Client): The parent client.
url (str): The video URL.
Expand Down Expand Up @@ -71,15 +71,15 @@ def __repr__(self) -> str:
def refresh(self, page: bool = True, data: bool = True) -> None:
'''
Refresh video data.
Args:
page (bool): Whether to refresh the video page.
data (bool): Whether to refresh the video data.
'''

logger.info('Refreshing %s cache', self)

# Clear saved video page and data
# Clear saved video page and data
if page: self.page = None
if data: self.data.clear()

Expand All @@ -92,18 +92,18 @@ def refresh(self, page: bool = True, data: bool = True) -> None:
def fetch(self, key: str) -> Any:
'''
Lazily fetch some data.
key format:
data@<dkey> => Get key from API
data@<dkey> => Get key from API
page@<pkey> => Scrape key from page
<dkey>|<pkey> => Choose considering cache
Args:
key (str): The key to fetch.
Returns:
Any: The fetched or cached object.
'''

# Multiple keys handle
Expand All @@ -116,7 +116,7 @@ def fetch(self, key: str) -> Any:
else:
key = 'data@' + datakey

# If key is already cached
# If key is already cached
if key in self.data:
return self.data.get(key)

Expand Down Expand Up @@ -151,11 +151,11 @@ def dictify(self,
recursive: bool = False) -> dict:
'''
Convert the object to a dictionary.
Args:
keys (str): The data keys to include.
recursive (bool): Whether to allow other PHUB objects to dictify.
Returns:
dict: A dict version of the object.
'''
Expand All @@ -171,10 +171,10 @@ def dictify(self,
def get_M3U_URL(self, quality: Quality) -> str:
'''
The URL of the master M3U file.
Args:
quality (Quality): The video quality.
Returns:
str: The M3U url.
'''
Expand All @@ -193,10 +193,10 @@ def get_M3U_URL(self, quality: Quality) -> str:
def get_segments(self, quality: Quality) -> Iterator[str]:
'''
Get the video segment URLs.
Args:
quality (Quality): The video quality.
Returns:
Iterator: A segment URL iterator.
'''
Expand Down Expand Up @@ -227,12 +227,12 @@ def download(self,
path: Union[str, os.PathLike],
quality: Quality | str = 'best',
*,
downloader: Callable = download.default,
downloader: Union[Callable, str] = download.default,
display: Callable[[int, int], None] = display.default(),
convert: bool = False) -> str:
'''
Download the video to a file.
Args:
path (PathLike): The download path.
quality (Quality | str | int): The video quality.
Expand All @@ -250,13 +250,26 @@ def download(self,

logger.info('Starting download for %s at %s', self, path)

# Call the backend
downloader(
video=self,
quality=quality,
callback=display,
path=path
)
if isinstance(downloader, str):
if downloader == "default":
download.default(video=self, quality=quality, path=path, callback=display)

elif downloader == "threaded":
threaded_download = download.threaded(max_workers=20, timeout=10)
threaded_download(video=self, quality=quality, path=path, callback=display)

elif downloader == "FFMPEG":
download.FFMPEG(video=self, quality=quality, path=path, callback=display)

else:
# Call the backend
downloader(
video=self,
quality=quality,
callback=display,
path=path
)

if convert:
FFMPEG_COMMAND = consts.FFMPEG_EXECUTABLE + ' -i "{input}" -bsf:a aac_adtstoasc -y -c copy {output} -quiet'
os.rename(path, path + ".tmp")
Expand All @@ -269,18 +282,18 @@ def download(self,
def get_direct_url(self, quality: Quality) -> str:
'''
Get the direct video URL given a specific quality.
Args:
quality (Quality): The video quality.
Returns:
str: The direct url.
'''

from ..utils import Quality
qual = Quality(quality)

# Get remote
# Get remote
sources = self.fetch('page@mediaDefinitions')
remote = [s for s in sources if 'remote' in s][0]['videoUrl']

Expand All @@ -297,7 +310,7 @@ def _assert_internal_success(self, res: dict) -> None:
Assert an internal response has succeeded.
Args:
res (dict): The rerquest json response.
res (dict): The rerquest json response.
'''

if 'success' in res and not res['success']:
Expand All @@ -309,13 +322,13 @@ def _as_query(self) -> dict[str, str]:
Simulate a query to gain access to more data.
If the video object is yielded by a query, this property
will be overriden by the query data.
Warning - This will make a lot of requests and can fake
some properties (like watched).
'''

# Now I really don't want people to use this without knowing what it
# really does
# really does
if not self.ALLOW_QUERY_SIMULATION:

# Personnalised error for the JSONQuery
Expand Down Expand Up @@ -379,7 +392,7 @@ def _as_query(self) -> dict[str, str]:
def like(self, toggle: bool = True) -> None:
'''
Set the video like value.
Args:
toggle (bool): The toggle value.
'''
Expand All @@ -394,7 +407,7 @@ def like(self, toggle: bool = True) -> None:
def favorite(self, toggle: bool = True) -> None:
'''
Set video as favorite or not.
Args:
toggle (bool): The toggle value.
'''
Expand All @@ -410,7 +423,7 @@ def favorite(self, toggle: bool = True) -> None:
def watch_later(self, toggle: bool = True) -> None:
'''
Add or remove the video to the watch later playlist.
Args:
toggle (bool): The toggle value.
'''
Expand Down Expand Up @@ -438,7 +451,7 @@ def id(self) -> str:
if pt := self.data.get('page@playbackTracking'):
return pt.get('video_id')

# Use thumbnail URL
# Use thumbnail URL
return consts.re.get_thumb_id(self.image.url)

@cached_property
Expand Down

0 comments on commit a389fd6

Please sign in to comment.