diff --git a/src/yutto/__main__.py b/src/yutto/__main__.py index e72965f..e5278e2 100644 --- a/src/yutto/__main__.py +++ b/src/yutto/__main__.py @@ -12,6 +12,7 @@ from typing import TYPE_CHECKING import httpx from biliass import BlockOptions +from yutto._typing import ExtractorOptions from yutto.cli.cli import cli from yutto.exceptions import ErrorCode from yutto.extractor import ( @@ -133,7 +134,23 @@ async def run(ctx: FetcherContext, args_list: list[argparse.Namespace]): # 提取信息,构造解析任务~ for extractor in extractors: if extractor.match(url): - download_list = await extractor(ctx, client, args) + download_list = await extractor( + ctx, + client, + ExtractorOptions( + episodes=args.episodes, + with_section=args.with_section, + require_video=args.require_video, + require_audio=args.require_audio, + require_danmaku=args.require_danmaku, + require_subtitle=args.require_subtitle, + require_metadata=args.require_metadata, + require_cover=args.require_cover, + require_chapter_info=args.require_chapter_info, + danmaku_format=args.danmaku_format, + subpath_template=args.subpath_template, + ), + ) break else: if args.batch: diff --git a/src/yutto/_typing.py b/src/yutto/_typing.py index 90425ec..d4e7c7d 100644 --- a/src/yutto/_typing.py +++ b/src/yutto/_typing.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: from yutto.bilibili_typing.codec import AudioCodec, VideoCodec from yutto.bilibili_typing.quality import AudioQuality, VideoQuality - from yutto.utils.danmaku import DanmakuData, DanmakuOptions + from yutto.utils.danmaku import DanmakuData, DanmakuOptions, DanmakuSaveType from yutto.utils.metadata import ChapterInfoData, MetaData from yutto.utils.subtitle import SubtitleData @@ -211,6 +211,20 @@ class MultiLangSubtitle(TypedDict): lines: SubtitleData +class ExtractorOptions(TypedDict): + episodes: str + with_section: bool + require_video: bool + require_audio: bool + require_danmaku: bool + require_subtitle: bool + require_metadata: bool + require_cover: bool + require_chapter_info: bool + danmaku_format: DanmakuSaveType + subpath_template: str + + class EpisodeData(TypedDict): """剧集数据,包含了一个视频资源的基本信息以及相关资源""" diff --git a/src/yutto/extractor/_abc.py b/src/yutto/extractor/_abc.py index b465b41..19d42d1 100644 --- a/src/yutto/extractor/_abc.py +++ b/src/yutto/extractor/_abc.py @@ -4,11 +4,9 @@ from abc import ABCMeta, abstractmethod from typing import TYPE_CHECKING, TypeVar if TYPE_CHECKING: - import argparse - import httpx - from yutto._typing import EpisodeData + from yutto._typing import EpisodeData, ExtractorOptions from yutto.utils.asynclib import CoroutineWrapper from yutto.utils.fetcher import FetcherContext @@ -27,32 +25,32 @@ class Extractor(metaclass=ABCMeta): @abstractmethod async def __call__( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: raise NotImplementedError class SingleExtractor(Extractor): async def __call__( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: - return [await self.extract(ctx, client, args)] + return [await self.extract(ctx, client, options)] @abstractmethod async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> CoroutineWrapper[EpisodeData | None] | None: raise NotImplementedError class BatchExtractor(Extractor): async def __call__( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: - return await self.extract(ctx, client, args) + return await self.extract(ctx, client, options) @abstractmethod async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: raise NotImplementedError diff --git a/src/yutto/extractor/bangumi.py b/src/yutto/extractor/bangumi.py index 1612710..9f664cb 100644 --- a/src/yutto/extractor/bangumi.py +++ b/src/yutto/extractor/bangumi.py @@ -19,10 +19,9 @@ from yutto.utils.asynclib import CoroutineWrapper from yutto.utils.console.logger import Badge, Logger if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions from yutto.utils.fetcher import FetcherContext @@ -51,7 +50,7 @@ class BangumiExtractor(SingleExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> CoroutineWrapper[EpisodeData | None] | None: season_id = await get_season_id_by_episode_id(ctx, client, self.episode_id) bangumi_list = await get_bangumi_list(ctx, client, season_id) @@ -70,7 +69,7 @@ class BangumiExtractor(SingleExtractor): ctx, client, bangumi_list_item, - args, + options, { "title": bangumi_list["title"], }, diff --git a/src/yutto/extractor/bangumi_batch.py b/src/yutto/extractor/bangumi_batch.py index fbb0afb..5d5dd80 100644 --- a/src/yutto/extractor/bangumi_batch.py +++ b/src/yutto/extractor/bangumi_batch.py @@ -16,10 +16,9 @@ from yutto.utils.asynclib import CoroutineWrapper from yutto.utils.console.logger import Badge, Logger if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions from yutto.utils.fetcher import FetcherContext @@ -73,7 +72,7 @@ class BangumiBatchExtractor(BatchExtractor): self.season_id = await get_season_id_by_media_id(ctx, client, media_id) async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: await self._parse_ids(ctx, client) @@ -81,10 +80,10 @@ class BangumiBatchExtractor(BatchExtractor): Logger.custom(bangumi_list["title"], Badge("番剧", fore="black", back="cyan")) # 如果没有 with_section 则不需要专区内容 bangumi_list["pages"] = list( - filter(lambda item: args.with_section or not item["is_section"], bangumi_list["pages"]) + filter(lambda item: options["with_section"] or not item["is_section"], bangumi_list["pages"]) ) # 选集过滤 - episodes = parse_episodes_selection(args.episodes, len(bangumi_list["pages"])) + episodes = parse_episodes_selection(options["episodes"], len(bangumi_list["pages"])) bangumi_list["pages"] = list(filter(lambda item: item["id"] in episodes, bangumi_list["pages"])) return [ CoroutineWrapper( @@ -92,7 +91,7 @@ class BangumiBatchExtractor(BatchExtractor): ctx, client, bangumi_item, - args, + options, { "title": bangumi_list["title"], }, diff --git a/src/yutto/extractor/cheese.py b/src/yutto/extractor/cheese.py index 7759791..e2509a1 100644 --- a/src/yutto/extractor/cheese.py +++ b/src/yutto/extractor/cheese.py @@ -19,10 +19,9 @@ from yutto.utils.asynclib import CoroutineWrapper from yutto.utils.console.logger import Badge, Logger if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions from yutto.utils.fetcher import FetcherContext @@ -52,7 +51,7 @@ class CheeseExtractor(SingleExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> CoroutineWrapper[EpisodeData | None] | None: season_id = await get_season_id_by_episode_id(ctx, client, self.episode_id) cheese_list = await get_cheese_list(ctx, client, season_id) @@ -72,7 +71,7 @@ class CheeseExtractor(SingleExtractor): client, self.episode_id, cheese_list_item, - args, + options, { "title": cheese_list["title"], }, diff --git a/src/yutto/extractor/cheese_batch.py b/src/yutto/extractor/cheese_batch.py index 54732b1..f08a88d 100644 --- a/src/yutto/extractor/cheese_batch.py +++ b/src/yutto/extractor/cheese_batch.py @@ -12,10 +12,9 @@ from yutto.utils.asynclib import CoroutineWrapper from yutto.utils.console.logger import Badge, Logger if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions from yutto.utils.fetcher import FetcherContext @@ -58,14 +57,14 @@ class CheeseBatchExtractor(BatchExtractor): self.season_id = SeasonId(self._match_result.group("season_id")) async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: await self._parse_ids(ctx, client) cheese_list = await get_cheese_list(ctx, client, self.season_id) Logger.custom(cheese_list["title"], Badge("课程", fore="black", back="cyan")) # 选集过滤 - episodes = parse_episodes_selection(args.episodes, len(cheese_list["pages"])) + episodes = parse_episodes_selection(options["episodes"], len(cheese_list["pages"])) cheese_list["pages"] = list(filter(lambda item: item["id"] in episodes, cheese_list["pages"])) return [ CoroutineWrapper( @@ -74,7 +73,7 @@ class CheeseBatchExtractor(BatchExtractor): client, cheese_item["episode_id"], cheese_item, - args, + options, { "title": cheese_list["title"], }, diff --git a/src/yutto/extractor/collection.py b/src/yutto/extractor/collection.py index fde02ea..a6ca0e2 100644 --- a/src/yutto/extractor/collection.py +++ b/src/yutto/extractor/collection.py @@ -18,10 +18,10 @@ from yutto.utils.fetcher import Fetcher, FetcherContext from yutto.utils.filter import Filter if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions + class CollectionExtractor(BatchExtractor): """视频合集""" @@ -53,7 +53,7 @@ class CollectionExtractor(BatchExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: username, collection_details = await asyncio.gather( get_user_name(ctx, client, self.mid), @@ -65,7 +65,7 @@ class CollectionExtractor(BatchExtractor): ugc_video_info_list: list[tuple[UgcVideoListItem, str, int]] = [] # 选集过滤 - episodes = parse_episodes_selection(args.episodes, len(collection_details["pages"])) + episodes = parse_episodes_selection(options["episodes"], len(collection_details["pages"])) collection_details["pages"] = list(filter(lambda item: item["id"] in episodes, collection_details["pages"])) for item in collection_details["pages"]: @@ -97,7 +97,7 @@ class CollectionExtractor(BatchExtractor): client, ugc_video_item["avid"], ugc_video_item, - args, + options, { # TODO: 关于对于 id 的优化 # TODO: 关于对于 title 的优化(最好使用合集标题,而不是原来的视频标题) diff --git a/src/yutto/extractor/common.py b/src/yutto/extractor/common.py index 08c0340..eb49c85 100644 --- a/src/yutto/extractor/common.py +++ b/src/yutto/extractor/common.py @@ -3,7 +3,7 @@ from __future__ import annotations from pathlib import Path from typing import TYPE_CHECKING -from yutto._typing import AvId, EpisodeData, EpisodeId, format_ids +from yutto._typing import AvId, EpisodeData, EpisodeId, ExtractorOptions, format_ids from yutto.api.bangumi import ( BangumiListItem, get_bangumi_playurl, @@ -34,8 +34,6 @@ from yutto.utils.fetcher import Fetcher, FetcherContext from yutto.utils.metadata import attach_chapter_info if TYPE_CHECKING: - import argparse - import httpx @@ -43,7 +41,7 @@ async def extract_bangumi_data( ctx: FetcherContext, client: httpx.AsyncClient, bangumi_info: BangumiListItem, - args: argparse.Namespace, + options: ExtractorOptions, subpath_variables: PathTemplateVariableDict, auto_subpath_template: str = "{name}", ) -> EpisodeData | None: @@ -55,15 +53,21 @@ async def extract_bangumi_data( if bangumi_info["is_preview"]: Logger.warning(f"视频({format_ids(avid, cid)})是预览视频(疑似未登录或非大会员用户)") videos, audios = ( - await get_bangumi_playurl(ctx, client, avid, cid) if args.require_video or args.require_audio else ([], []) + await get_bangumi_playurl(ctx, client, avid, cid) + if options["require_video"] or options["require_audio"] + else ([], []) ) - subtitles = await get_bangumi_subtitles(ctx, client, avid, cid) if args.require_subtitle else [] + subtitles = await get_bangumi_subtitles(ctx, client, avid, cid) if options["require_subtitle"] else [] danmaku = ( - await get_danmaku(ctx, client, cid, avid, args.danmaku_format) if args.require_danmaku else EmptyDanmakuData + await get_danmaku(ctx, client, cid, avid, options["danmaku_format"]) + if options["require_danmaku"] + else EmptyDanmakuData ) - metadata = bangumi_info["metadata"] if args.require_metadata else None + metadata = bangumi_info["metadata"] if options["require_metadata"] else None cover_data = ( - await Fetcher.fetch_bin(ctx, client, bangumi_info["metadata"]["thumb"]) if args.require_cover else None + await Fetcher.fetch_bin(ctx, client, bangumi_info["metadata"]["thumb"]) + if options["require_cover"] + else None ) subpath_variables_base: PathTemplateVariableDict = { "id": id, @@ -78,7 +82,7 @@ async def extract_bangumi_data( "owner_uid": UNKNOWN, } subpath_variables_base.update(subpath_variables) - path = resolve_path_template(args.subpath_template, auto_subpath_template, subpath_variables_base) + path = resolve_path_template(options["subpath_template"], auto_subpath_template, subpath_variables_base) return EpisodeData( videos=videos, audios=audios, @@ -99,7 +103,7 @@ async def extract_cheese_data( client: httpx.AsyncClient, episode_id: EpisodeId, cheese_info: CheeseListItem, - args: argparse.Namespace, + options: ExtractorOptions, subpath_variables: PathTemplateVariableDict, auto_subpath_template: str = "{name}", ) -> EpisodeData | None: @@ -110,16 +114,18 @@ async def extract_cheese_data( id = cheese_info["id"] videos, audios = ( await get_cheese_playurl(ctx, client, avid, episode_id, cid) - if args.require_video or args.require_audio + if options["require_video"] or options["require_audio"] else ([], []) ) - subtitles = await get_cheese_subtitles(ctx, client, avid, cid) if args.require_subtitle else [] + subtitles = await get_cheese_subtitles(ctx, client, avid, cid) if options["require_subtitle"] else [] danmaku = ( - await get_danmaku(ctx, client, cid, avid, args.danmaku_format) if args.require_danmaku else EmptyDanmakuData + await get_danmaku(ctx, client, cid, avid, options["danmaku_format"]) + if options["require_danmaku"] + else EmptyDanmakuData ) - metadata = cheese_info["metadata"] if args.require_metadata else None + metadata = cheese_info["metadata"] if options["require_metadata"] else None cover_data = ( - await Fetcher.fetch_bin(ctx, client, cheese_info["metadata"]["thumb"]) if args.require_cover else None + await Fetcher.fetch_bin(ctx, client, cheese_info["metadata"]["thumb"]) if options["require_cover"] else None ) subpath_variables_base: PathTemplateVariableDict = { "id": id, @@ -134,7 +140,7 @@ async def extract_cheese_data( "owner_uid": UNKNOWN, } subpath_variables_base.update(subpath_variables) - path = resolve_path_template(args.subpath_template, auto_subpath_template, subpath_variables_base) + path = resolve_path_template(options["subpath_template"], auto_subpath_template, subpath_variables_base) return EpisodeData( videos=videos, audios=audios, @@ -155,7 +161,7 @@ async def extract_ugc_video_data( client: httpx.AsyncClient, avid: AvId, ugc_video_info: UgcVideoListItem, - args: argparse.Namespace, + options: ExtractorOptions, subpath_variables: PathTemplateVariableDict, auto_subpath_template: str = "{title}", ) -> EpisodeData | None: @@ -165,19 +171,25 @@ async def extract_ugc_video_data( id = ugc_video_info["id"] videos, audios = ( await get_ugc_video_playurl(ctx, client, avid, cid) - if args.require_video or args.require_audio + if options["require_video"] or options["require_audio"] else ([], []) ) - subtitles = await get_ugc_video_subtitles(ctx, client, avid, cid) if args.require_subtitle else [] - chapter_info_data = await get_ugc_video_chapters(ctx, client, avid, cid) if args.require_chapter_info else [] - danmaku = ( - await get_danmaku(ctx, client, cid, avid, args.danmaku_format) if args.require_danmaku else EmptyDanmakuData + subtitles = await get_ugc_video_subtitles(ctx, client, avid, cid) if options["require_subtitle"] else [] + chapter_info_data = ( + await get_ugc_video_chapters(ctx, client, avid, cid) if options["require_chapter_info"] else [] ) - metadata = ugc_video_info["metadata"] if args.require_metadata else None + danmaku = ( + await get_danmaku(ctx, client, cid, avid, options["danmaku_format"]) + if options["require_danmaku"] + else EmptyDanmakuData + ) + metadata = ugc_video_info["metadata"] if options["require_metadata"] else None if metadata and chapter_info_data: attach_chapter_info(metadata, chapter_info_data) cover_data = ( - await Fetcher.fetch_bin(ctx, client, ugc_video_info["metadata"]["thumb"]) if args.require_cover else None + await Fetcher.fetch_bin(ctx, client, ugc_video_info["metadata"]["thumb"]) + if options["require_cover"] + else None ) owner_uid: str = ( ugc_video_info["metadata"]["actor"][0]["profile"].split("/")[-1] @@ -200,7 +212,7 @@ async def extract_ugc_video_data( "owner_uid": owner_uid, } subpath_variables_base.update(subpath_variables) - path = resolve_path_template(args.subpath_template, auto_subpath_template, subpath_variables_base) + path = resolve_path_template(options["subpath_template"], auto_subpath_template, subpath_variables_base) return EpisodeData( videos=videos, audios=audios, diff --git a/src/yutto/extractor/favourites.py b/src/yutto/extractor/favourites.py index bdfda4c..67fd152 100644 --- a/src/yutto/extractor/favourites.py +++ b/src/yutto/extractor/favourites.py @@ -16,10 +16,10 @@ from yutto.utils.fetcher import Fetcher, FetcherContext from yutto.utils.filter import Filter if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions + class FavouritesExtractor(BatchExtractor): """用户单一收藏夹""" @@ -38,7 +38,7 @@ class FavouritesExtractor(BatchExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: username, favourite_info = await asyncio.gather( get_user_name(ctx, client, self.mid), @@ -76,7 +76,7 @@ class FavouritesExtractor(BatchExtractor): client, ugc_video_item["avid"], ugc_video_item, - args, + options, { "title": title, "username": username, diff --git a/src/yutto/extractor/series.py b/src/yutto/extractor/series.py index 1bf6505..279666a 100644 --- a/src/yutto/extractor/series.py +++ b/src/yutto/extractor/series.py @@ -16,10 +16,10 @@ from yutto.utils.fetcher import Fetcher, FetcherContext from yutto.utils.filter import Filter if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions + class SeriesExtractor(BatchExtractor): """视频列表""" @@ -46,7 +46,7 @@ class SeriesExtractor(BatchExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: username, series_title = await asyncio.gather( get_user_name(ctx, client, self.mid), get_medialist_title(ctx, client, self.series_id) @@ -80,7 +80,7 @@ class SeriesExtractor(BatchExtractor): client, ugc_video_item["avid"], ugc_video_item, - args, + options, { "series_title": series_title, "username": username, # 虽然默认模板的用不上,但这里可以提供一下 diff --git a/src/yutto/extractor/ugc_video.py b/src/yutto/extractor/ugc_video.py index 0759182..b762ecc 100644 --- a/src/yutto/extractor/ugc_video.py +++ b/src/yutto/extractor/ugc_video.py @@ -17,10 +17,9 @@ from yutto.utils.asynclib import CoroutineWrapper from yutto.utils.console.logger import Badge, Logger if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions from yutto.utils.fetcher import FetcherContext @@ -73,7 +72,7 @@ class UgcVideoExtractor(SingleExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> CoroutineWrapper[EpisodeData | None] | None: try: ugc_video_list = await get_ugc_video_list(ctx, client, self.avid) @@ -85,7 +84,7 @@ class UgcVideoExtractor(SingleExtractor): client, self.avid, ugc_video_list["pages"][self.page - 1], - args, + options, { "title": ugc_video_list["title"], "pubdate": ugc_video_list["pubdate"], diff --git a/src/yutto/extractor/ugc_video_batch.py b/src/yutto/extractor/ugc_video_batch.py index 15b596c..3754212 100644 --- a/src/yutto/extractor/ugc_video_batch.py +++ b/src/yutto/extractor/ugc_video_batch.py @@ -13,10 +13,9 @@ from yutto.utils.asynclib import CoroutineWrapper from yutto.utils.console.logger import Badge, Logger if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions from yutto.utils.fetcher import FetcherContext @@ -65,7 +64,7 @@ class UgcVideoBatchExtractor(BatchExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: try: ugc_video_list = await get_ugc_video_list(ctx, client, self.avid) @@ -76,7 +75,7 @@ class UgcVideoBatchExtractor(BatchExtractor): return [] # 选集过滤 - episodes = parse_episodes_selection(args.episodes, len(ugc_video_list["pages"])) + episodes = parse_episodes_selection(options["episodes"], len(ugc_video_list["pages"])) ugc_video_list["pages"] = list(filter(lambda item: item["id"] in episodes, ugc_video_list["pages"])) return [ @@ -86,7 +85,7 @@ class UgcVideoBatchExtractor(BatchExtractor): client, ugc_video_item["avid"], ugc_video_item, - args, + options, { "title": ugc_video_list["title"], "pubdate": ugc_video_list["pubdate"], diff --git a/src/yutto/extractor/user_all_favourites.py b/src/yutto/extractor/user_all_favourites.py index ef46bb0..78d3779 100644 --- a/src/yutto/extractor/user_all_favourites.py +++ b/src/yutto/extractor/user_all_favourites.py @@ -15,10 +15,10 @@ from yutto.utils.fetcher import Fetcher, FetcherContext from yutto.utils.filter import Filter if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions + class UserAllFavouritesExtractor(BatchExtractor): """用户所有收藏夹""" @@ -35,7 +35,7 @@ class UserAllFavouritesExtractor(BatchExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: username = await get_user_name(ctx, client, self.mid) Logger.custom(username, Badge("用户收藏夹", fore="black", back="cyan")) @@ -72,7 +72,7 @@ class UserAllFavouritesExtractor(BatchExtractor): client, ugc_video_item["avid"], ugc_video_item, - args, + options, { "title": title, "username": username, diff --git a/src/yutto/extractor/user_all_ugc_videos.py b/src/yutto/extractor/user_all_ugc_videos.py index a646b16..cbf27ee 100644 --- a/src/yutto/extractor/user_all_ugc_videos.py +++ b/src/yutto/extractor/user_all_ugc_videos.py @@ -15,10 +15,10 @@ from yutto.utils.fetcher import Fetcher, FetcherContext from yutto.utils.filter import Filter if TYPE_CHECKING: - import argparse - import httpx + from yutto._typing import ExtractorOptions + class UserAllUgcVideosExtractor(BatchExtractor): """UP 主个人空间全部投稿视频""" @@ -35,7 +35,7 @@ class UserAllUgcVideosExtractor(BatchExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: username = await get_user_name(ctx, client, self.mid) Logger.custom(username, Badge("UP 主投稿视频", fore="black", back="cyan")) @@ -67,7 +67,7 @@ class UserAllUgcVideosExtractor(BatchExtractor): client, ugc_video_item["avid"], ugc_video_item, - args, + options, { "title": title, "username": username, diff --git a/src/yutto/extractor/user_watch_later.py b/src/yutto/extractor/user_watch_later.py index f89bfa1..bb4381e 100644 --- a/src/yutto/extractor/user_watch_later.py +++ b/src/yutto/extractor/user_watch_later.py @@ -14,11 +14,9 @@ from yutto.utils.fetcher import Fetcher, FetcherContext from yutto.utils.filter import Filter if TYPE_CHECKING: - import argparse - import httpx - from yutto._typing import EpisodeData + from yutto._typing import EpisodeData, ExtractorOptions class UserWatchLaterExtractor(BatchExtractor): @@ -34,7 +32,7 @@ class UserWatchLaterExtractor(BatchExtractor): return False async def extract( - self, ctx: FetcherContext, client: httpx.AsyncClient, args: argparse.Namespace + self, ctx: FetcherContext, client: httpx.AsyncClient, options: ExtractorOptions ) -> list[CoroutineWrapper[EpisodeData | None] | None]: Logger.custom("当前用户", Badge("稍后再看", fore="black", back="cyan")) @@ -73,7 +71,7 @@ class UserWatchLaterExtractor(BatchExtractor): client, ugc_video_item["avid"], ugc_video_item, - args, + options, { "title": title, "username": "",