Skip to content

Commit 8f4f019

Browse files
authored
🏷️ types: update return types to use TypedDicts for bangumi, cheese, and ugc_video APIs (#626)
1 parent 219799b commit 8f4f019

10 files changed

Lines changed: 199 additions & 198 deletions

File tree

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ yutto = "yutto.__main__:main"
4545

4646
[dependency-groups]
4747
dev = [
48-
"pyright>=1.1.407",
49-
"ruff>=0.14.6",
50-
"typos>=1.40.0",
51-
"pytest>=9.0.1",
48+
"pyright>=1.1.408",
49+
"ruff>=0.14.11",
50+
"typos>=1.42.0",
51+
"pytest>=9.0.2",
5252
"pytest-rerunfailures>=16.1",
5353
"syrupy>=5.0.0",
5454
"pytest-codspeed>=4.2.0",

src/yutto/api/bangumi.py

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
from yutto.exceptions import NoAccessPermissionError, UnSupportedTypeError
77
from yutto.media.codec import audio_codec_map, video_codec_map
88
from yutto.types import (
9+
AudioUrlMeta,
910
BvId,
1011
CId,
1112
EpisodeId,
1213
SeasonId,
14+
VideoUrlMeta,
1315
format_ids,
1416
)
1517
from yutto.utils.console.logger import Logger
@@ -22,11 +24,9 @@
2224
from httpx import AsyncClient
2325

2426
from yutto.types import (
25-
AudioUrlMeta,
2627
AvId,
2728
MediaId,
2829
MultiLangSubtitle,
29-
VideoUrlMeta,
3030
)
3131
from yutto.utils.fetcher import FetcherContext
3232

@@ -75,22 +75,22 @@ async def get_bangumi_list(ctx: FetcherContext, client: AsyncClient, season_id:
7575
# 如 https://www.bilibili.com/bangumi/play/ep409825 中的「次元发电机采访」
7676
# 和 https://www.bilibili.com/bangumi/play/ep424859 中的「编辑推荐」
7777
section_episodes += section["episodes"]
78-
return {
79-
"title": result["title"],
80-
"pages": [
81-
{
82-
"id": i + 1,
83-
"name": _bangumi_episode_title(item["title"], item["long_title"]),
84-
"cid": CId(str(item["cid"])),
85-
"episode_id": EpisodeId(str(item["id"])),
86-
"avid": BvId(item["bvid"]),
87-
"is_section": i >= len(result["episodes"]),
88-
"is_preview": item["badge"] == "预告", # 并不是一种鲁棒的方式,但目前貌似没有更好的方式了
89-
"metadata": _parse_bangumi_metadata(item),
90-
}
78+
return BangumiList(
79+
title=result["title"],
80+
pages=[
81+
BangumiListItem(
82+
id=i + 1,
83+
name=_bangumi_episode_title(item["title"], item["long_title"]),
84+
cid=CId(str(item["cid"])),
85+
episode_id=EpisodeId(str(item["id"])),
86+
avid=BvId(item["bvid"]),
87+
is_section=i >= len(result["episodes"]),
88+
is_preview=item["badge"] == "预告", # 并不是一种鲁棒的方式,但目前貌似没有更好的方式了
89+
metadata=_parse_bangumi_metadata(item),
90+
)
9191
for i, item in enumerate(result["episodes"] + section_episodes)
9292
],
93-
}
93+
)
9494

9595

9696
async def get_bangumi_playurl(
@@ -113,38 +113,38 @@ async def get_bangumi_playurl(
113113
raise UnSupportedTypeError(f"该视频({format_ids(avid, cid)})尚不支持 DASH 格式")
114114

115115
videos: list[VideoUrlMeta] = [
116-
{
117-
"url": video["base_url"],
118-
"mirrors": video["backup_url"] if video["backup_url"] is not None else [],
119-
"codec": video_codec_map[video["codecid"]],
120-
"width": video["width"],
121-
"height": video["height"],
122-
"quality": video["id"],
123-
}
116+
VideoUrlMeta(
117+
url=video["base_url"],
118+
mirrors=video["backup_url"] if video["backup_url"] is not None else [],
119+
codec=video_codec_map[video["codecid"]],
120+
width=video["width"],
121+
height=video["height"],
122+
quality=video["id"],
123+
)
124124
for video in video_info["dash"]["video"]
125125
]
126126
audios: list[AudioUrlMeta] = [
127-
{
128-
"url": audio["base_url"],
129-
"mirrors": audio["backup_url"] if audio["backup_url"] is not None else [],
130-
"codec": audio_codec_map[audio["codecid"]],
131-
"width": 0,
132-
"height": 0,
133-
"quality": audio["id"],
134-
}
127+
AudioUrlMeta(
128+
url=audio["base_url"],
129+
mirrors=audio["backup_url"] if audio["backup_url"] is not None else [],
130+
codec=audio_codec_map[audio["codecid"]],
131+
width=0,
132+
height=0,
133+
quality=audio["id"],
134+
)
135135
for audio in video_info["dash"]["audio"]
136136
]
137137
if video_info["dash"]["dolby"] is not None and video_info["dash"]["dolby"]["audio"] is not None:
138138
dolby_audios_json = video_info["dash"]["dolby"]["audio"]
139139
audios.extend(
140-
{
141-
"url": dolby_audio_json["base_url"],
142-
"mirrors": dolby_audio_json["backup_url"] if dolby_audio_json["backup_url"] is not None else [],
143-
"codec": "eac3", # TODO: 由于这里的 codecid 仍然是 0,所以无法通过 audio_codec_map 转换,暂时直接硬编码
144-
"width": 0,
145-
"height": 0,
146-
"quality": dolby_audio_json["id"],
147-
}
140+
AudioUrlMeta(
141+
url=dolby_audio_json["base_url"],
142+
mirrors=dolby_audio_json["backup_url"] if dolby_audio_json["backup_url"] is not None else [],
143+
codec="eac3", # TODO: 由于这里的 codecid 仍然是 0,所以无法通过 audio_codec_map 转换,暂时直接硬编码
144+
width=0,
145+
height=0,
146+
quality=dolby_audio_json["id"],
147+
)
148148
for dolby_audio_json in dolby_audios_json
149149
)
150150
return (videos, audios)

src/yutto/api/cheese.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
from yutto.media.codec import audio_codec_map, video_codec_map
77
from yutto.types import (
88
AId,
9+
AudioUrlMeta,
910
CId,
1011
EpisodeId,
1112
SeasonId,
13+
VideoUrlMeta,
1214
format_ids,
1315
)
1416
from yutto.utils.console.logger import Logger
@@ -21,10 +23,8 @@
2123
from httpx import AsyncClient
2224

2325
from yutto.types import (
24-
AudioUrlMeta,
2526
AvId,
2627
MultiLangSubtitle,
27-
VideoUrlMeta,
2828
)
2929
from yutto.utils.fetcher import FetcherContext
3030

@@ -59,20 +59,20 @@ async def get_cheese_list(ctx: FetcherContext, client: AsyncClient, season_id: S
5959
raise NoAccessPermissionError(f"无法解析该课程列表(season_id: {season_id}),原因:{resp_json.get('message')}")
6060
result = resp_json["data"]
6161
section_episodes = result["episodes"]
62-
return {
63-
"title": result["title"],
64-
"pages": [
65-
{
66-
"id": i + 1,
67-
"name": item["title"],
68-
"cid": CId(str(item["cid"])),
69-
"episode_id": EpisodeId(str(item["id"])),
70-
"avid": AId(str(item["aid"])),
71-
"metadata": _parse_cheese_metadata(item),
72-
}
62+
return CheeseList(
63+
title=result["title"],
64+
pages=[
65+
CheeseListItem(
66+
id=i + 1,
67+
name=item["title"],
68+
cid=CId(str(item["cid"])),
69+
episode_id=EpisodeId(str(item["id"])),
70+
avid=AId(str(item["aid"])),
71+
metadata=_parse_cheese_metadata(item),
72+
)
7373
for i, item in enumerate(section_episodes)
7474
],
75-
}
75+
)
7676

7777

7878
async def get_cheese_playurl(
@@ -95,25 +95,25 @@ async def get_cheese_playurl(
9595
raise UnSupportedTypeError(f"该视频({format_ids(avid, cid)})尚不支持 DASH 格式")
9696
return (
9797
[
98-
{
99-
"url": video["base_url"],
100-
"mirrors": video["backup_url"] if video["backup_url"] is not None else [],
101-
"codec": video_codec_map[video["codecid"]],
102-
"width": video["width"],
103-
"height": video["height"],
104-
"quality": video["id"],
105-
}
98+
VideoUrlMeta(
99+
url=video["base_url"],
100+
mirrors=video["backup_url"] if video["backup_url"] is not None else [],
101+
codec=video_codec_map[video["codecid"]],
102+
width=video["width"],
103+
height=video["height"],
104+
quality=video["id"],
105+
)
106106
for video in resp_json["data"]["dash"]["video"]
107107
],
108108
[
109-
{
110-
"url": audio["base_url"],
111-
"mirrors": audio["backup_url"] if audio["backup_url"] is not None else [],
112-
"codec": audio_codec_map[audio["codecid"]],
113-
"width": 0,
114-
"height": 0,
115-
"quality": audio["id"],
116-
}
109+
AudioUrlMeta(
110+
url=audio["base_url"],
111+
mirrors=audio["backup_url"] if audio["backup_url"] is not None else [],
112+
codec=audio_codec_map[audio["codecid"]],
113+
width=0,
114+
height=0,
115+
quality=audio["id"],
116+
)
117117
for audio in resp_json["data"]["dash"]["audio"]
118118
],
119119
)

0 commit comments

Comments
 (0)