diff --git a/twitchdl/commands/download.py b/twitchdl/commands/download.py index 1fc5dc3..877fcaa 100644 --- a/twitchdl/commands/download.py +++ b/twitchdl/commands/download.py @@ -1,6 +1,5 @@ import asyncio import platform -import click import httpx import m3u8 import os @@ -16,7 +15,7 @@ from urllib.parse import urlparse, urlencode from twitchdl import twitch, utils from twitchdl.download import download_file -from twitchdl.entities import DownloadOptions +from twitchdl.entities import Data, DownloadOptions from twitchdl.exceptions import ConsoleError from twitchdl.http import download_all from twitchdl.output import print_out @@ -115,16 +114,16 @@ def _concat_vods(vod_paths: list[str], target: str): raise ConsoleError(f"Joining files failed: {result.stderr}") -def _video_target_filename(video, args: DownloadOptions): +def get_video_substitutions(video: Data, format: str) -> Data: date, time = video['publishedAt'].split("T") game = video["game"]["name"] if video["game"] else "Unknown" - subs = { + return { "channel": video["creator"]["displayName"], "channel_login": video["creator"]["login"], "date": date, "datetime": video["publishedAt"], - "format": args.format, + "format": format, "game": game, "game_slug": utils.slugify(game), "id": video["id"], @@ -133,6 +132,10 @@ def _video_target_filename(video, args: DownloadOptions): "title_slug": utils.slugify(video["title"]), } + +def _video_target_filename(video: Data, args: DownloadOptions): + subs = get_video_substitutions(video, args.format) + try: return args.output.format(**subs) except KeyError as e: diff --git a/twitchdl/commands/info.py b/twitchdl/commands/info.py index 914567e..cf0bb64 100644 --- a/twitchdl/commands/info.py +++ b/twitchdl/commands/info.py @@ -1,10 +1,11 @@ import m3u8 from twitchdl import utils, twitch +from twitchdl.commands.download import get_video_substitutions from twitchdl.exceptions import ConsoleError from twitchdl.output import print_video, print_clip, print_json, print_out, print_log -def info(id: str, *, json: bool = False): +def info(id: str, *, json: bool = False, format="mkv"): video_id = utils.parse_video_identifier(id) if video_id: print_log("Fetching video...") @@ -22,10 +23,16 @@ def info(id: str, *, json: bool = False): print_log("Fetching chapters...") chapters = twitch.get_video_chapters(video_id) + substitutions = get_video_substitutions(video, format) + if json: video_json(video, playlists, chapters) else: video_info(video, playlists, chapters) + + print_out("\nOutput format placeholders:") + for k, v in substitutions.items(): + print(f" * {k} = {v}") return clip_slug = utils.parse_clip_identifier(id) diff --git a/twitchdl/entities.py b/twitchdl/entities.py index 83ad080..78c744e 100644 --- a/twitchdl/entities.py +++ b/twitchdl/entities.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from typing import Any @dataclass @@ -17,3 +18,8 @@ class DownloadOptions: rate_limit: str | None start: int | None max_workers: int + + +# Type for annotating decoded JSON +# TODO: make data classes for common structs +Data = dict[str, Any]