twitch-dl/twitchdl/commands/clips.py

110 lines
3.1 KiB
Python
Raw Normal View History

2021-01-07 08:34:14 +00:00
import re
import sys
2021-01-07 08:34:14 +00:00
from os import path
2024-08-28 08:59:23 +00:00
from pathlib import Path
2024-08-28 12:16:49 +00:00
from typing import Callable, Generator, List, Optional
2021-01-07 08:34:14 +00:00
2024-04-04 06:20:10 +00:00
import click
2021-01-07 08:34:14 +00:00
from twitchdl import twitch, utils
from twitchdl.commands.download import get_clip_authenticated_url
2024-08-28 12:16:49 +00:00
from twitchdl.entities import VideoQuality
2024-08-28 09:07:25 +00:00
from twitchdl.http import download_file
2024-04-06 08:43:12 +00:00
from twitchdl.output import green, print_clip, print_clip_compact, print_json, print_paged, yellow
from twitchdl.twitch import Clip, ClipsPeriod
2021-01-07 08:34:14 +00:00
2024-03-23 09:50:42 +00:00
def clips(
channel_name: str,
*,
all: bool = False,
2024-04-06 08:43:12 +00:00
compact: bool = False,
2024-03-23 09:50:42 +00:00
download: bool = False,
json: bool = False,
limit: Optional[int] = None,
pager: Optional[int] = None,
period: ClipsPeriod = "all_time",
target_dir: Path = Path(),
2024-03-23 09:50:42 +00:00
):
2024-04-06 08:43:12 +00:00
# Set different defaults for limit for compact display
default_limit = 40 if compact else 10
# Ignore --limit if --pager or --all are given
2024-04-06 08:43:12 +00:00
limit = sys.maxsize if all or pager else (limit or default_limit)
2024-03-23 09:50:42 +00:00
generator = twitch.channel_clips_generator(channel_name, period, limit)
2024-03-23 09:50:42 +00:00
if json:
return print_json(list(generator))
2021-05-18 12:25:49 +00:00
2024-03-23 09:50:42 +00:00
if download:
return _download_clips(target_dir, generator)
2024-04-06 08:43:12 +00:00
print_fn = print_clip_compact if compact else print_clip
2021-05-18 12:25:49 +00:00
2024-04-06 08:43:12 +00:00
if pager:
return print_paged("Clips", generator, print_fn, pager)
2021-01-07 08:34:14 +00:00
2024-04-06 08:43:12 +00:00
return _print_all(generator, print_fn, all)
2021-01-07 08:34:14 +00:00
2024-08-28 12:16:49 +00:00
def _target_filename(clip: Clip, video_qualities: List[VideoQuality]):
url = video_qualities[0]["sourceURL"]
2021-01-07 08:34:14 +00:00
_, ext = path.splitext(url)
ext = ext.lstrip(".")
match = re.search(r"^(\d{4})-(\d{2})-(\d{2})T", clip["createdAt"])
2024-03-23 09:50:42 +00:00
if not match:
raise ValueError(f"Failed parsing date from: {clip['createdAt']}")
2021-01-07 08:34:14 +00:00
date = "".join(match.groups())
2024-04-04 06:20:10 +00:00
name = "_".join(
[
date,
clip["id"],
clip["broadcaster"]["login"],
utils.slugify(clip["title"]),
]
)
2021-01-07 08:34:14 +00:00
2024-03-28 11:06:50 +00:00
return f"{name}.{ext}"
2021-01-07 08:34:14 +00:00
def _download_clips(target_dir: Path, generator: Generator[Clip, None, None]):
if not target_dir.exists():
target_dir.mkdir(parents=True, exist_ok=True)
for clip in generator:
2024-08-28 12:16:49 +00:00
# videoQualities can be null in some circumstances, see:
# https://github.com/ihabunek/twitch-dl/issues/160
if not clip["videoQualities"]:
continue
target = target_dir / _target_filename(clip, clip["videoQualities"])
2021-05-18 12:23:56 +00:00
2024-08-28 08:59:23 +00:00
if target.exists():
click.echo(f"Already downloaded: {green(target)}")
else:
try:
url = get_clip_authenticated_url(clip["slug"], "source")
click.echo(f"Downloading: {yellow(target)}")
download_file(url, target)
except Exception as ex:
click.secho(ex, err=True, fg="red")
2021-05-18 12:23:56 +00:00
2021-01-07 08:34:14 +00:00
2024-04-06 08:43:12 +00:00
def _print_all(
generator: Generator[Clip, None, None],
print_fn: Callable[[Clip], None],
all: bool,
):
for clip in generator:
2024-04-06 08:43:12 +00:00
print_fn(clip)
2021-05-18 12:23:56 +00:00
2024-03-23 09:50:42 +00:00
if not all:
click.secho(
2024-04-04 06:20:10 +00:00
"\nThere may be more clips. "
+ "Increase the --limit, use --all or --pager to see the rest.",
dim=True,
)