bpi-py 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bpi/__init__.py +29 -0
- bpi/_core/__init__.py +1 -0
- bpi/_core/params.py +21 -0
- bpi/_core/response.py +51 -0
- bpi/_generated/__init__.py +1 -0
- bpi/_generated/audio_client.py +217 -0
- bpi/_generated/audio_models.py +320 -0
- bpi/_generated/bangumi_client.py +68 -0
- bpi/_generated/bangumi_models.py +602 -0
- bpi/_generated/cheese_client.py +49 -0
- bpi/_generated/cheese_models.py +198 -0
- bpi/_generated/login_client.py +41 -0
- bpi/_generated/login_models.py +49 -0
- bpi/_generated/user_client.py +257 -0
- bpi/_generated/user_models.py +455 -0
- bpi/_generated/video_client.py +250 -0
- bpi/_generated/video_models.py +577 -0
- bpi/activity/__init__.py +4 -0
- bpi/activity/client.py +45 -0
- bpi/activity/models.py +42 -0
- bpi/activity/params.py +29 -0
- bpi/article/__init__.py +29 -0
- bpi/article/client.py +93 -0
- bpi/article/models.py +391 -0
- bpi/article/params.py +54 -0
- bpi/audio/__init__.py +58 -0
- bpi/audio/actions.py +111 -0
- bpi/audio/client.py +9 -0
- bpi/bangumi/__init__.py +18 -0
- bpi/bangumi/actions.py +34 -0
- bpi/bangumi/client.py +54 -0
- bpi/bangumi/models.py +55 -0
- bpi/cheese/__init__.py +3 -0
- bpi/cheese/client.py +51 -0
- bpi/cheese/models.py +120 -0
- bpi/client.py +410 -0
- bpi/clientinfo/__init__.py +4 -0
- bpi/clientinfo/client.py +43 -0
- bpi/clientinfo/models.py +11 -0
- bpi/comment/__init__.py +14 -0
- bpi/comment/client.py +139 -0
- bpi/comment/models.py +332 -0
- bpi/comment/params.py +176 -0
- bpi/creativecenter/__init__.py +63 -0
- bpi/creativecenter/client.py +344 -0
- bpi/creativecenter/models.py +526 -0
- bpi/creativecenter/params.py +237 -0
- bpi/danmaku/__init__.py +19 -0
- bpi/danmaku/client.py +219 -0
- bpi/danmaku/models.py +124 -0
- bpi/danmaku/params.py +238 -0
- bpi/dynamic/__init__.py +21 -0
- bpi/dynamic/client.py +285 -0
- bpi/dynamic/models.py +373 -0
- bpi/dynamic/params.py +161 -0
- bpi/electric/__init__.py +29 -0
- bpi/electric/client.py +181 -0
- bpi/electric/models.py +305 -0
- bpi/electric/params.py +139 -0
- bpi/errors.py +92 -0
- bpi/fav/__init__.py +41 -0
- bpi/fav/client.py +212 -0
- bpi/fav/models.py +196 -0
- bpi/fav/params.py +155 -0
- bpi/historytoview/__init__.py +24 -0
- bpi/historytoview/client.py +97 -0
- bpi/historytoview/models.py +176 -0
- bpi/historytoview/params.py +102 -0
- bpi/live/__init__.py +45 -0
- bpi/live/client.py +653 -0
- bpi/live/models.py +676 -0
- bpi/live/params.py +84 -0
- bpi/login/__init__.py +29 -0
- bpi/login/client.py +174 -0
- bpi/login/models.py +107 -0
- bpi/login/params.py +75 -0
- bpi/manga/__init__.py +25 -0
- bpi/manga/client.py +177 -0
- bpi/manga/models.py +116 -0
- bpi/manga/params.py +69 -0
- bpi/message/__init__.py +13 -0
- bpi/message/client.py +119 -0
- bpi/message/models.py +113 -0
- bpi/message/params.py +71 -0
- bpi/misc/__init__.py +13 -0
- bpi/misc/client.py +78 -0
- bpi/misc/models.py +44 -0
- bpi/misc/params.py +31 -0
- bpi/misc/sign.py +28 -0
- bpi/note/__init__.py +25 -0
- bpi/note/client.py +118 -0
- bpi/note/models.py +142 -0
- bpi/note/params.py +88 -0
- bpi/opus/__init__.py +5 -0
- bpi/opus/client.py +33 -0
- bpi/opus/models.py +29 -0
- bpi/opus/params.py +42 -0
- bpi/py.typed +0 -0
- bpi/search/__init__.py +58 -0
- bpi/search/client.py +156 -0
- bpi/search/models.py +316 -0
- bpi/search/params.py +160 -0
- bpi/session.py +42 -0
- bpi/sign/__init__.py +1 -0
- bpi/sign/wbi.py +107 -0
- bpi/user/__init__.py +3 -0
- bpi/user/actions.py +185 -0
- bpi/user/client.py +9 -0
- bpi/user/models.py +31 -0
- bpi/video/__init__.py +41 -0
- bpi/video/actions.py +277 -0
- bpi/video/client.py +64 -0
- bpi/video/models.py +135 -0
- bpi/video_ranking/__init__.py +24 -0
- bpi/video_ranking/client.py +132 -0
- bpi/video_ranking/models.py +101 -0
- bpi/video_ranking/params.py +108 -0
- bpi/vip/__init__.py +23 -0
- bpi/vip/client.py +50 -0
- bpi/vip/models.py +108 -0
- bpi/vip/params.py +13 -0
- bpi/wallet/__init__.py +4 -0
- bpi/wallet/client.py +56 -0
- bpi/wallet/models.py +18 -0
- bpi/web_widget/__init__.py +11 -0
- bpi/web_widget/client.py +44 -0
- bpi/web_widget/models.py +86 -0
- bpi/web_widget/params.py +9 -0
- bpi_py-0.3.0.dist-info/METADATA +290 -0
- bpi_py-0.3.0.dist-info/RECORD +132 -0
- bpi_py-0.3.0.dist-info/WHEEL +4 -0
- bpi_py-0.3.0.dist-info/licenses/LICENSE +21 -0
bpi/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from .client import AsyncBpiClient
|
|
2
|
+
from .errors import (
|
|
3
|
+
ApiError,
|
|
4
|
+
AuthenticationError,
|
|
5
|
+
BpiError,
|
|
6
|
+
ClientClosedError,
|
|
7
|
+
HttpStatusError,
|
|
8
|
+
InvalidParameterError,
|
|
9
|
+
MissingDataError,
|
|
10
|
+
ResponseDecodeError,
|
|
11
|
+
TransportError,
|
|
12
|
+
UnsupportedResponseError,
|
|
13
|
+
)
|
|
14
|
+
from .session import Account
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"Account",
|
|
18
|
+
"ApiError",
|
|
19
|
+
"AsyncBpiClient",
|
|
20
|
+
"AuthenticationError",
|
|
21
|
+
"BpiError",
|
|
22
|
+
"ClientClosedError",
|
|
23
|
+
"HttpStatusError",
|
|
24
|
+
"InvalidParameterError",
|
|
25
|
+
"MissingDataError",
|
|
26
|
+
"ResponseDecodeError",
|
|
27
|
+
"TransportError",
|
|
28
|
+
"UnsupportedResponseError",
|
|
29
|
+
]
|
bpi/_core/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Internal request and decoding implementation."""
|
bpi/_core/params.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Shared parameter validation for handwritten and generated read methods."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from bpi.errors import InvalidParameterError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def integer(value: int, name: str, minimum: int = 1) -> str:
|
|
9
|
+
if type(value) is not int or value < minimum:
|
|
10
|
+
raise InvalidParameterError(f"{name} must be an integer >= {minimum}")
|
|
11
|
+
return str(value)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def video_id(aid: int | None, bvid: str | None, *, play: bool = False) -> dict[str, str]:
|
|
15
|
+
if (aid is None) == (bvid is None):
|
|
16
|
+
raise InvalidParameterError("Provide exactly one of aid or bvid")
|
|
17
|
+
if aid is not None:
|
|
18
|
+
return {"avid" if play else "aid": integer(aid, "aid")}
|
|
19
|
+
if not isinstance(bvid, str) or not re.fullmatch(r"BV[0-9A-Za-z]{10}", bvid):
|
|
20
|
+
raise InvalidParameterError("bvid must be a 12-character BV identifier")
|
|
21
|
+
return {"bvid": bvid}
|
bpi/_core/response.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, TypeVar
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError
|
|
7
|
+
|
|
8
|
+
from bpi.errors import ApiError, AuthenticationError, MissingDataError, ResponseDecodeError
|
|
9
|
+
|
|
10
|
+
T = TypeVar("T")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ResponseModel(BaseModel):
|
|
14
|
+
model_config = ConfigDict(
|
|
15
|
+
extra="ignore", strict=True, populate_by_name=True, hide_input_in_errors=True
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def envelope(body: bytes, *, allow_anonymous_wbi: bool = False) -> dict[str, Any]:
|
|
20
|
+
try:
|
|
21
|
+
raw = json.loads(body)
|
|
22
|
+
except (ValueError, UnicodeError):
|
|
23
|
+
raise ResponseDecodeError(body) from None
|
|
24
|
+
if not isinstance(raw, dict):
|
|
25
|
+
raise ResponseDecodeError(body)
|
|
26
|
+
code = raw.get("code", raw.get("errno"))
|
|
27
|
+
if type(code) is not int:
|
|
28
|
+
raise ResponseDecodeError(body)
|
|
29
|
+
if code != 0 and not (allow_anonymous_wbi and code == -101):
|
|
30
|
+
message = raw.get("message", raw.get("msg", raw.get("showMsg", "")))
|
|
31
|
+
error_type = AuthenticationError if ApiError(code).requires_login() else ApiError
|
|
32
|
+
raise error_type(code, message if isinstance(message, str) else "")
|
|
33
|
+
return raw
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def decode_payload(
|
|
37
|
+
body: bytes,
|
|
38
|
+
adapter: TypeAdapter[T],
|
|
39
|
+
*,
|
|
40
|
+
allow_anonymous_wbi: bool = False,
|
|
41
|
+
allow_missing: bool = False,
|
|
42
|
+
) -> T:
|
|
43
|
+
raw = envelope(body, allow_anonymous_wbi=allow_anonymous_wbi)
|
|
44
|
+
value = raw.get("data", raw.get("result"))
|
|
45
|
+
if value is None and not allow_missing:
|
|
46
|
+
raise MissingDataError("Successful response has no payload")
|
|
47
|
+
try:
|
|
48
|
+
return adapter.validate_python(value)
|
|
49
|
+
except ValidationError:
|
|
50
|
+
# Suppress the default chain: ValidationError may contain account or response input.
|
|
51
|
+
raise ResponseDecodeError(body) from None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Generated read methods and models; see migration/batch-3.json."""
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Generated by tools.migration.generate; edit migration/batch-*.json or the generator.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from pydantic import ConfigDict, TypeAdapter
|
|
7
|
+
|
|
8
|
+
from bpi._core.params import integer
|
|
9
|
+
from bpi.errors import InvalidParameterError
|
|
10
|
+
|
|
11
|
+
from .audio_models import (
|
|
12
|
+
AudioCollection,
|
|
13
|
+
AudioCollectionsListData,
|
|
14
|
+
AudioHotMenuData,
|
|
15
|
+
AudioInfoData,
|
|
16
|
+
AudioMemberType,
|
|
17
|
+
AudioRankDetailData,
|
|
18
|
+
AudioRankMenuData,
|
|
19
|
+
AudioRankMusicListData,
|
|
20
|
+
AudioRankPeriodData,
|
|
21
|
+
AudioStatusNumberData,
|
|
22
|
+
AudioStreamUrlData,
|
|
23
|
+
AudioStreamUrlWebData,
|
|
24
|
+
AudioTag,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from bpi.client import AsyncBpiClient
|
|
29
|
+
|
|
30
|
+
_INFO = TypeAdapter(AudioInfoData)
|
|
31
|
+
_TAGS = TypeAdapter(list[AudioTag])
|
|
32
|
+
_MEMBERS = TypeAdapter(list[AudioMemberType])
|
|
33
|
+
_LYRIC = TypeAdapter(str, config=ConfigDict(strict=True))
|
|
34
|
+
_STATUS_NUMBER = TypeAdapter(AudioStatusNumberData)
|
|
35
|
+
_COLLECTION_STATUS = TypeAdapter(bool, config=ConfigDict(strict=True))
|
|
36
|
+
_COIN_COUNT = TypeAdapter(int, config=ConfigDict(strict=True))
|
|
37
|
+
_STREAM_URL_WEB = TypeAdapter(AudioStreamUrlWebData)
|
|
38
|
+
_STREAM_URL = TypeAdapter(AudioStreamUrlData)
|
|
39
|
+
_COLLECTIONS_LIST = TypeAdapter(AudioCollectionsListData)
|
|
40
|
+
_COLLECTION_INFO: TypeAdapter[AudioCollection | None] = TypeAdapter(AudioCollection | None)
|
|
41
|
+
_HOT_MENU = TypeAdapter(AudioHotMenuData)
|
|
42
|
+
_RANK_MENU = TypeAdapter(AudioRankMenuData)
|
|
43
|
+
_RANK_PERIOD = TypeAdapter(AudioRankPeriodData)
|
|
44
|
+
_RANK_DETAIL = TypeAdapter(AudioRankDetailData)
|
|
45
|
+
_RANK_MUSIC_LIST = TypeAdapter(AudioRankMusicListData)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class AudioReadMethods:
|
|
49
|
+
def __init__(self, client: AsyncBpiClient) -> None:
|
|
50
|
+
self._client = client
|
|
51
|
+
|
|
52
|
+
async def info(self, *, sid: int) -> AudioInfoData:
|
|
53
|
+
"""audio.info; public-read."""
|
|
54
|
+
params: dict[str, str] = {}
|
|
55
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
56
|
+
return await self._client._get_payload(
|
|
57
|
+
"/audio/music-service-c/web/song/info", params, _INFO, host="www.bilibili.com"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
async def tags(self, *, sid: int) -> list[AudioTag]:
|
|
61
|
+
"""audio.tags; public-read."""
|
|
62
|
+
params: dict[str, str] = {}
|
|
63
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
64
|
+
return await self._client._get_payload(
|
|
65
|
+
"/audio/music-service-c/web/tag/song", params, _TAGS, host="www.bilibili.com"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
async def members(self, *, sid: int) -> list[AudioMemberType]:
|
|
69
|
+
"""audio.members; public-read."""
|
|
70
|
+
params: dict[str, str] = {}
|
|
71
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
72
|
+
return await self._client._get_payload(
|
|
73
|
+
"/audio/music-service-c/web/member/song", params, _MEMBERS, host="www.bilibili.com"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
async def lyric(self, *, sid: int) -> str:
|
|
77
|
+
"""audio.lyric; public-read."""
|
|
78
|
+
params: dict[str, str] = {}
|
|
79
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
80
|
+
return await self._client._get_payload(
|
|
81
|
+
"/audio/music-service-c/web/song/lyric", params, _LYRIC, host="www.bilibili.com"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
async def status_number(self, *, sid: int) -> AudioStatusNumberData:
|
|
85
|
+
"""audio.status_number; public-read."""
|
|
86
|
+
params: dict[str, str] = {}
|
|
87
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
88
|
+
return await self._client._get_payload(
|
|
89
|
+
"/audio/music-service-c/web/stat/song", params, _STATUS_NUMBER, host="www.bilibili.com"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
async def collection_status(self, *, sid: int) -> bool:
|
|
93
|
+
"""audio.collection_status; authenticated-read."""
|
|
94
|
+
params: dict[str, str] = {}
|
|
95
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
96
|
+
return await self._client._get_payload(
|
|
97
|
+
"/audio/music-service-c/web/collections/songs-coll",
|
|
98
|
+
params,
|
|
99
|
+
_COLLECTION_STATUS,
|
|
100
|
+
host="www.bilibili.com",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
async def coin_count(self, *, sid: int) -> int:
|
|
104
|
+
"""audio.coin_count; authenticated-read."""
|
|
105
|
+
params: dict[str, str] = {}
|
|
106
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
107
|
+
return await self._client._get_payload(
|
|
108
|
+
"/audio/music-service-c/web/coin/audio", params, _COIN_COUNT, host="www.bilibili.com"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
async def stream_url_web(
|
|
112
|
+
self, *, sid: int, quality: int = 2, privilege: int = 2
|
|
113
|
+
) -> AudioStreamUrlWebData:
|
|
114
|
+
"""audio.stream_url_web; public-read."""
|
|
115
|
+
params: dict[str, str] = {}
|
|
116
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
117
|
+
params["quality"] = integer(quality, "quality", 0)
|
|
118
|
+
if quality not in [0, 1, 2, 3]:
|
|
119
|
+
raise InvalidParameterError("Unsupported quality")
|
|
120
|
+
params["privilege"] = integer(privilege, "privilege", 1)
|
|
121
|
+
return await self._client._get_payload(
|
|
122
|
+
"/audio/music-service-c/web/url", params, _STREAM_URL_WEB, host="www.bilibili.com"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
async def stream_url(
|
|
126
|
+
self,
|
|
127
|
+
*,
|
|
128
|
+
song_id: int,
|
|
129
|
+
quality: int,
|
|
130
|
+
privilege: int = 2,
|
|
131
|
+
mid: int = 2,
|
|
132
|
+
platform: str = "android",
|
|
133
|
+
) -> AudioStreamUrlData:
|
|
134
|
+
"""audio.stream_url; public-read."""
|
|
135
|
+
params: dict[str, str] = {}
|
|
136
|
+
params["songid"] = integer(song_id, "song_id", 1)
|
|
137
|
+
params["quality"] = integer(quality, "quality", 0)
|
|
138
|
+
if quality not in [0, 1, 2, 3]:
|
|
139
|
+
raise InvalidParameterError("Unsupported quality")
|
|
140
|
+
params["privilege"] = integer(privilege, "privilege", 1)
|
|
141
|
+
params["mid"] = integer(mid, "mid", 1)
|
|
142
|
+
if not isinstance(platform, str):
|
|
143
|
+
raise InvalidParameterError("platform must be a string")
|
|
144
|
+
params["platform"] = platform
|
|
145
|
+
params["platform"] = platform.strip()
|
|
146
|
+
if not params["platform"]:
|
|
147
|
+
raise InvalidParameterError("platform cannot be blank")
|
|
148
|
+
return await self._client._get_payload("/audio/music-service-c/url", params, _STREAM_URL)
|
|
149
|
+
|
|
150
|
+
async def collections_list(self, *, page: int, page_size: int) -> AudioCollectionsListData:
|
|
151
|
+
"""audio.collections_list; authenticated-read."""
|
|
152
|
+
params: dict[str, str] = {}
|
|
153
|
+
params["pn"] = integer(page, "page", 1)
|
|
154
|
+
params["ps"] = integer(page_size, "page_size", 1)
|
|
155
|
+
return await self._client._get_payload(
|
|
156
|
+
"/audio/music-service-c/web/collections/list",
|
|
157
|
+
params,
|
|
158
|
+
_COLLECTIONS_LIST,
|
|
159
|
+
host="www.bilibili.com",
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
async def collection_info(self, *, sid: int) -> AudioCollection | None:
|
|
163
|
+
"""audio.collection_info; authenticated-read."""
|
|
164
|
+
params: dict[str, str] = {}
|
|
165
|
+
params["sid"] = integer(sid, "sid", 1)
|
|
166
|
+
return await self._client._get_payload(
|
|
167
|
+
"/audio/music-service-c/web/collections/info",
|
|
168
|
+
params,
|
|
169
|
+
_COLLECTION_INFO,
|
|
170
|
+
host="www.bilibili.com",
|
|
171
|
+
optional=True,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
async def hot_menu(self, *, page: int, page_size: int) -> AudioHotMenuData:
|
|
175
|
+
"""audio.hot_menu; public-read."""
|
|
176
|
+
params: dict[str, str] = {}
|
|
177
|
+
params["pn"] = integer(page, "page", 1)
|
|
178
|
+
params["ps"] = integer(page_size, "page_size", 1)
|
|
179
|
+
return await self._client._get_payload(
|
|
180
|
+
"/audio/music-service-c/web/menu/hit", params, _HOT_MENU, host="www.bilibili.com"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
async def rank_menu(self, *, page: int, page_size: int) -> AudioRankMenuData:
|
|
184
|
+
"""audio.rank_menu; public-read."""
|
|
185
|
+
params: dict[str, str] = {}
|
|
186
|
+
params["pn"] = integer(page, "page", 1)
|
|
187
|
+
params["ps"] = integer(page_size, "page_size", 1)
|
|
188
|
+
return await self._client._get_payload(
|
|
189
|
+
"/audio/music-service-c/web/menu/rank", params, _RANK_MENU, host="www.bilibili.com"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
async def rank_period(self, *, list_type: int) -> AudioRankPeriodData:
|
|
193
|
+
"""audio.rank_period; public-read."""
|
|
194
|
+
params: dict[str, str] = {}
|
|
195
|
+
params["list_type"] = integer(list_type, "list_type", 1)
|
|
196
|
+
params["csrf"] = self._client._csrf(host="api.bilibili.com", optional=True)
|
|
197
|
+
return await self._client._get_payload(
|
|
198
|
+
"/x/copyright-music-publicity/toplist/all_period", params, _RANK_PERIOD
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
async def rank_detail(self, *, list_id: int) -> AudioRankDetailData:
|
|
202
|
+
"""audio.rank_detail; public-read."""
|
|
203
|
+
params: dict[str, str] = {}
|
|
204
|
+
params["list_id"] = integer(list_id, "list_id", 1)
|
|
205
|
+
params["csrf"] = self._client._csrf(host="api.bilibili.com", optional=True)
|
|
206
|
+
return await self._client._get_payload(
|
|
207
|
+
"/x/copyright-music-publicity/toplist/detail", params, _RANK_DETAIL
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
async def rank_music_list(self, *, list_id: int) -> AudioRankMusicListData:
|
|
211
|
+
"""audio.rank_music_list; public-read."""
|
|
212
|
+
params: dict[str, str] = {}
|
|
213
|
+
params["list_id"] = integer(list_id, "list_id", 1)
|
|
214
|
+
params["csrf"] = self._client._csrf(host="api.bilibili.com", optional=True)
|
|
215
|
+
return await self._client._get_payload(
|
|
216
|
+
"/x/copyright-music-publicity/toplist/music_list", params, _RANK_MUSIC_LIST
|
|
217
|
+
)
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# Generated by tools.migration.generate; edit migration/batch-*.json or the generator.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import builtins
|
|
5
|
+
|
|
6
|
+
from pydantic import Field, JsonValue
|
|
7
|
+
|
|
8
|
+
from bpi._core.response import ResponseModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AudioStatistic(ResponseModel):
|
|
12
|
+
"""Source: src/audio/info.rs:66:AudioStatistic."""
|
|
13
|
+
|
|
14
|
+
sid: int
|
|
15
|
+
play: int
|
|
16
|
+
collect: int
|
|
17
|
+
comment: int
|
|
18
|
+
share: int
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AudioVipInfo(ResponseModel):
|
|
22
|
+
"""Source: src/audio/info.rs:81:AudioVipInfo."""
|
|
23
|
+
|
|
24
|
+
type: int
|
|
25
|
+
status: int
|
|
26
|
+
due_date: int
|
|
27
|
+
vip_pay_type: int
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AudioInfoData(ResponseModel):
|
|
31
|
+
"""Source: src/audio/info.rs:9:AudioInfoData."""
|
|
32
|
+
|
|
33
|
+
id: int
|
|
34
|
+
uid: int
|
|
35
|
+
uname: str
|
|
36
|
+
author: str
|
|
37
|
+
title: str
|
|
38
|
+
cover: str
|
|
39
|
+
intro: str
|
|
40
|
+
lyric: str
|
|
41
|
+
crtype: int
|
|
42
|
+
duration: int
|
|
43
|
+
passtime: int
|
|
44
|
+
curtime: int
|
|
45
|
+
aid: int
|
|
46
|
+
bvid: str
|
|
47
|
+
cid: int
|
|
48
|
+
msid: int
|
|
49
|
+
attr: int
|
|
50
|
+
limit: int
|
|
51
|
+
activity_id: int = Field(alias="activityId")
|
|
52
|
+
limitdesc: str
|
|
53
|
+
ctime: JsonValue | None = Field(default=None)
|
|
54
|
+
statistic: AudioStatistic
|
|
55
|
+
vip_info: AudioVipInfo = Field(alias="vipInfo")
|
|
56
|
+
collect_ids: list[int] = Field(alias="collectIds")
|
|
57
|
+
coin_num: int
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AudioTag(ResponseModel):
|
|
61
|
+
"""Source: src/audio/info.rs:94:AudioTag."""
|
|
62
|
+
|
|
63
|
+
type: str
|
|
64
|
+
subtype: int
|
|
65
|
+
key: int
|
|
66
|
+
info: str
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class AudioMember(ResponseModel):
|
|
70
|
+
"""Source: src/audio/info.rs:116:AudioMember."""
|
|
71
|
+
|
|
72
|
+
mid: int
|
|
73
|
+
name: str
|
|
74
|
+
member_id: int
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class AudioMemberType(ResponseModel):
|
|
78
|
+
"""Source: src/audio/info.rs:107:AudioMemberType."""
|
|
79
|
+
|
|
80
|
+
list: builtins.list[AudioMember]
|
|
81
|
+
type: int
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class AudioStatusNumberData(ResponseModel):
|
|
85
|
+
"""Source: src/audio/status_number.rs:7:AudioStatusNumberData."""
|
|
86
|
+
|
|
87
|
+
sid: int
|
|
88
|
+
play: int
|
|
89
|
+
collect: int
|
|
90
|
+
comment: int
|
|
91
|
+
share: int
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class AudioStreamUrlWebData(ResponseModel):
|
|
95
|
+
"""Source: src/audio/musicstream_url.rs:26:AudioStreamUrlWebData."""
|
|
96
|
+
|
|
97
|
+
sid: int
|
|
98
|
+
type: int
|
|
99
|
+
info: str
|
|
100
|
+
timeout: int
|
|
101
|
+
size: int
|
|
102
|
+
cdns: list[str]
|
|
103
|
+
qualities: JsonValue | None = Field(default=None)
|
|
104
|
+
title: str
|
|
105
|
+
cover: str
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class AudioQualityInfo(ResponseModel):
|
|
109
|
+
"""Source: src/audio/musicstream_url.rs:52:AudioQualityInfo."""
|
|
110
|
+
|
|
111
|
+
type: int
|
|
112
|
+
desc: str
|
|
113
|
+
size: int
|
|
114
|
+
bps: str
|
|
115
|
+
tag: str
|
|
116
|
+
require: int
|
|
117
|
+
requiredesc: str
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class AudioStreamUrlData(ResponseModel):
|
|
121
|
+
"""Source: src/audio/musicstream_url.rs:39:AudioStreamUrlData."""
|
|
122
|
+
|
|
123
|
+
sid: int
|
|
124
|
+
type: int
|
|
125
|
+
info: str
|
|
126
|
+
timeout: int
|
|
127
|
+
size: int
|
|
128
|
+
cdns: list[str]
|
|
129
|
+
qualities: list[AudioQualityInfo]
|
|
130
|
+
title: str
|
|
131
|
+
cover: str
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class AudioCollectionStatistic(ResponseModel):
|
|
135
|
+
"""Source: src/audio/music_list.rs:42:AudioCollectionStatistic."""
|
|
136
|
+
|
|
137
|
+
sid: int
|
|
138
|
+
play: int
|
|
139
|
+
collect: int
|
|
140
|
+
comment: int | None = Field(default=None)
|
|
141
|
+
share: int
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class AudioCollection(ResponseModel):
|
|
145
|
+
"""Source: src/audio/music_list.rs:24:AudioCollection."""
|
|
146
|
+
|
|
147
|
+
id: int
|
|
148
|
+
uid: int
|
|
149
|
+
uname: str
|
|
150
|
+
title: str
|
|
151
|
+
type: int
|
|
152
|
+
published: int
|
|
153
|
+
cover: str
|
|
154
|
+
ctime: int
|
|
155
|
+
song: int
|
|
156
|
+
desc: str
|
|
157
|
+
sids: list[int]
|
|
158
|
+
menu_id: int = Field(alias="menuId")
|
|
159
|
+
statistic: AudioCollectionStatistic
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class AudioCollectionsListData(ResponseModel):
|
|
163
|
+
"""Source: src/audio/music_list.rs:7:AudioCollectionsListData."""
|
|
164
|
+
|
|
165
|
+
cur_page: int = Field(alias="curPage")
|
|
166
|
+
page_count: int = Field(alias="pageCount")
|
|
167
|
+
total_size: int = Field(alias="totalSize")
|
|
168
|
+
page_size: int = Field(alias="pageSize")
|
|
169
|
+
data: list[AudioCollection]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class AudioHotMenuStatistic(ResponseModel):
|
|
173
|
+
"""Source: src/audio/music_list.rs:104:AudioHotMenuStatistic."""
|
|
174
|
+
|
|
175
|
+
sid: int
|
|
176
|
+
play: int
|
|
177
|
+
collect: int
|
|
178
|
+
comment: int
|
|
179
|
+
share: int
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class AudioHotMenu(ResponseModel):
|
|
183
|
+
"""Source: src/audio/music_list.rs:68:AudioHotMenu."""
|
|
184
|
+
|
|
185
|
+
menu_id: int = Field(alias="menuId")
|
|
186
|
+
uid: int
|
|
187
|
+
uname: str
|
|
188
|
+
title: str
|
|
189
|
+
cover: str
|
|
190
|
+
intro: str
|
|
191
|
+
type: int
|
|
192
|
+
off: int
|
|
193
|
+
ctime: int
|
|
194
|
+
curtime: int
|
|
195
|
+
statistic: AudioHotMenuStatistic
|
|
196
|
+
snum: int
|
|
197
|
+
attr: int
|
|
198
|
+
is_default: int = Field(alias="isDefault")
|
|
199
|
+
collection_id: int = Field(alias="collectionId")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class AudioHotMenuData(ResponseModel):
|
|
203
|
+
"""Source: src/audio/music_list.rs:51:AudioHotMenuData."""
|
|
204
|
+
|
|
205
|
+
cur_page: int = Field(alias="curPage")
|
|
206
|
+
page_count: int = Field(alias="pageCount")
|
|
207
|
+
total_size: int = Field(alias="totalSize")
|
|
208
|
+
page_size: int = Field(alias="pageSize")
|
|
209
|
+
data: list[AudioHotMenu]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class AudioRankMenuStatistic(ResponseModel):
|
|
213
|
+
"""Source: src/audio/music_list.rs:168:AudioRankMenuStatistic."""
|
|
214
|
+
|
|
215
|
+
sid: int
|
|
216
|
+
play: int
|
|
217
|
+
collect: int
|
|
218
|
+
comment: int
|
|
219
|
+
share: int
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class AudioRankItem(ResponseModel):
|
|
223
|
+
"""Source: src/audio/music_list.rs:177:AudioRankItem."""
|
|
224
|
+
|
|
225
|
+
id: int
|
|
226
|
+
title: str
|
|
227
|
+
duration: int
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class AudioRankMenu(ResponseModel):
|
|
231
|
+
"""Source: src/audio/music_list.rs:130:AudioRankMenu."""
|
|
232
|
+
|
|
233
|
+
menu_id: int = Field(alias="menuId")
|
|
234
|
+
uid: int
|
|
235
|
+
uname: str
|
|
236
|
+
title: str
|
|
237
|
+
cover: str
|
|
238
|
+
intro: str
|
|
239
|
+
type: int
|
|
240
|
+
off: int
|
|
241
|
+
ctime: int
|
|
242
|
+
curtime: int
|
|
243
|
+
statistic: AudioRankMenuStatistic
|
|
244
|
+
snum: int
|
|
245
|
+
attr: int
|
|
246
|
+
is_default: int = Field(alias="isDefault")
|
|
247
|
+
collection_id: int = Field(alias="collectionId")
|
|
248
|
+
audios: list[AudioRankItem]
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class AudioRankMenuData(ResponseModel):
|
|
252
|
+
"""Source: src/audio/music_list.rs:113:AudioRankMenuData."""
|
|
253
|
+
|
|
254
|
+
cur_page: int = Field(alias="curPage")
|
|
255
|
+
page_count: int = Field(alias="pageCount")
|
|
256
|
+
total_size: int = Field(alias="totalSize")
|
|
257
|
+
page_size: int = Field(alias="pageSize")
|
|
258
|
+
data: list[AudioRankMenu]
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class AudioRankPeriod(ResponseModel):
|
|
262
|
+
"""Source: src/audio/rank.rs:20:AudioRankPeriod."""
|
|
263
|
+
|
|
264
|
+
id: int = Field(alias="ID")
|
|
265
|
+
priod: int
|
|
266
|
+
publish_time: int
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class AudioRankPeriodData(ResponseModel):
|
|
270
|
+
"""Source: src/audio/rank.rs:15:AudioRankPeriodData."""
|
|
271
|
+
|
|
272
|
+
list: dict[str, list[AudioRankPeriod]]
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class AudioRankDetailData(ResponseModel):
|
|
276
|
+
"""Source: src/audio/rank.rs:28:AudioRankDetailData."""
|
|
277
|
+
|
|
278
|
+
listen_fid: int
|
|
279
|
+
all_fid: int
|
|
280
|
+
fav_mid: int
|
|
281
|
+
cover_url: str
|
|
282
|
+
is_subscribe: bool
|
|
283
|
+
listen_count: int
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class AudioRankMusicItem(ResponseModel):
|
|
287
|
+
"""Source: src/audio/rank.rs:43:AudioRankMusicItem."""
|
|
288
|
+
|
|
289
|
+
music_id: str
|
|
290
|
+
music_title: str
|
|
291
|
+
singer: str
|
|
292
|
+
album: str
|
|
293
|
+
mv_aid: int
|
|
294
|
+
mv_bvid: str
|
|
295
|
+
mv_cover: str
|
|
296
|
+
heat: int
|
|
297
|
+
rank: int
|
|
298
|
+
can_listen: bool
|
|
299
|
+
recommendation: str
|
|
300
|
+
creation_aid: int
|
|
301
|
+
creation_bvid: str
|
|
302
|
+
creation_cover: str
|
|
303
|
+
creation_title: str
|
|
304
|
+
creation_up: int
|
|
305
|
+
creation_nickname: str
|
|
306
|
+
creation_duration: int
|
|
307
|
+
creation_play: int
|
|
308
|
+
creation_reason: str
|
|
309
|
+
achievements: list[str]
|
|
310
|
+
material_id: int
|
|
311
|
+
material_use_num: int
|
|
312
|
+
material_duration: int
|
|
313
|
+
material_show: int
|
|
314
|
+
song_type: int
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class AudioRankMusicListData(ResponseModel):
|
|
318
|
+
"""Source: src/audio/rank.rs:38:AudioRankMusicListData."""
|
|
319
|
+
|
|
320
|
+
list: builtins.list[AudioRankMusicItem]
|