qqmusic-api-python 0.1.6__tar.gz → 0.1.7__tar.gz
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.
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/PKG-INFO +1 -1
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/pyproject.toml +1 -1
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/__init__.py +3 -2
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/album.py +4 -3
- qqmusic_api_python-0.1.7/qqmusic_api/data/api/lyric.json +25 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/song.json +11 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/file_type.json +4 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/login.py +2 -2
- qqmusic_api_python-0.1.7/qqmusic_api/lyric.py +68 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/search.py +6 -6
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/singer.py +3 -3
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/song.py +92 -30
- qqmusic_api_python-0.1.7/qqmusic_api/utils/tripledes.py +1089 -0
- qqmusic_api_python-0.1.7/qqmusic_api/utils/utils.py +95 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_song.py +2 -1
- qqmusic_api_python-0.1.6/qqmusic_api/utils/utils.py +0 -52
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/LICENSE +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/README.md +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/album.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/login.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/mv.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/search.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/singer.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/songlist.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/api/top.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/data/search_type.json +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/exceptions/ApiException.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/exceptions/CredentialNoMusicidException.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/exceptions/CredentialNoMusickeyException.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/exceptions/CredentialNoRefreshkeyException.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/exceptions/LoginException.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/exceptions/ResponseCodeException.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/exceptions/__init__.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/mv.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/songlist.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/top.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/utils/__init__.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/utils/credential.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/utils/network.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/utils/qimei.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/qqmusic_api/utils/sync.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/__init__.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/conftest.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_album.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_login.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_mv.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_qimei.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_search.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_singer.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_songlist.py +0 -0
- {qqmusic_api_python-0.1.6 → qqmusic_api_python-0.1.7}/tests/test_top.py +0 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
from . import album, login, mv, search, singer, song, songlist, top
|
|
1
|
+
from . import album, login, lyric, mv, search, singer, song, songlist, top
|
|
2
2
|
from .utils.credential import Credential
|
|
3
3
|
from .utils.network import get_session, set_session
|
|
4
4
|
from .utils.sync import sync
|
|
5
5
|
|
|
6
|
-
__version__ = "0.1.
|
|
6
|
+
__version__ = "0.1.7"
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
9
|
"album",
|
|
10
10
|
"Credential",
|
|
11
11
|
"get_session",
|
|
12
12
|
"login",
|
|
13
|
+
"lyric",
|
|
13
14
|
"mv",
|
|
14
15
|
"search",
|
|
15
16
|
"set_session",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"info": {
|
|
3
|
+
"module": "music.musichallSong.PlayLyricInfo",
|
|
4
|
+
"method": "GetPlayLyricInfo",
|
|
5
|
+
"params": {
|
|
6
|
+
"ct": "int 11",
|
|
7
|
+
"cv": "int 13020508",
|
|
8
|
+
"lrc_t": "int 0",
|
|
9
|
+
"roma": "int 是否返回罗马歌词",
|
|
10
|
+
"roma_t": "int 0",
|
|
11
|
+
"trans": "int 是否返回翻译歌词",
|
|
12
|
+
"trans_t": "int 0",
|
|
13
|
+
"type": "int 1",
|
|
14
|
+
"albumName": "str 专辑名字",
|
|
15
|
+
"crypt": "int 是否加密歌词",
|
|
16
|
+
"qrc": "int 是否返回 qrc",
|
|
17
|
+
"qrc_t": "int 0",
|
|
18
|
+
"singerName": "str 歌手名字(取第一个)",
|
|
19
|
+
"songId": "int 歌曲 id",
|
|
20
|
+
"songMid": "str 歌曲 mid",
|
|
21
|
+
"songName": "str 歌曲名字"
|
|
22
|
+
},
|
|
23
|
+
"comment": "获取歌曲歌词信息"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -81,6 +81,17 @@
|
|
|
81
81
|
},
|
|
82
82
|
"comment": "获取歌曲制作团队"
|
|
83
83
|
},
|
|
84
|
+
"evkey": {
|
|
85
|
+
"module": "music.vkey.GetEVkey",
|
|
86
|
+
"method": "CgiGetEVkey",
|
|
87
|
+
"params": {
|
|
88
|
+
"filename": "[f'{file_type.s}{_}{_}{file_type.e}' for _ in mid]",
|
|
89
|
+
"guid": "str 随机32位字符串",
|
|
90
|
+
"songmid": "list mid 列表",
|
|
91
|
+
"songtype": "[1 for _ in range(len(mid))]"
|
|
92
|
+
},
|
|
93
|
+
"comment": "获取加密文件链接"
|
|
94
|
+
},
|
|
84
95
|
"play_url": {
|
|
85
96
|
"module": "music.vkey.GetVkey",
|
|
86
97
|
"method": "UrlGetVkey",
|
|
@@ -273,8 +273,8 @@ class QQLogin(QRCodeLogin):
|
|
|
273
273
|
)
|
|
274
274
|
location = res.headers.get("Location", "")
|
|
275
275
|
code = re.findall(r"(?<=code=)(.+?)(?=&)", location)[0]
|
|
276
|
-
|
|
277
|
-
self.credential = Credential.from_cookies(
|
|
276
|
+
response = await Api(**API["QQ_login"]).update_params(code=code).update_extra_common(tmeLoginType="2").result
|
|
277
|
+
self.credential = Credential.from_cookies(response)
|
|
278
278
|
return self.credential
|
|
279
279
|
|
|
280
280
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""歌词 API"""
|
|
2
|
+
|
|
3
|
+
import xml.etree.ElementTree as ET
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from .utils.network import Api
|
|
7
|
+
from .utils.utils import get_api, qrc_decrypt
|
|
8
|
+
|
|
9
|
+
API = get_api("lyric")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def get_lyric(
|
|
13
|
+
*,
|
|
14
|
+
mid: Optional[str] = None,
|
|
15
|
+
id: Optional[int] = None,
|
|
16
|
+
qrc: bool = False,
|
|
17
|
+
trans: bool = False,
|
|
18
|
+
roma: bool = False,
|
|
19
|
+
) -> dict[str, str]:
|
|
20
|
+
"""获取歌词
|
|
21
|
+
|
|
22
|
+
Note:
|
|
23
|
+
歌曲 mid 和 id,两者至少提供一个
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
mid: 歌曲 mid
|
|
27
|
+
id: 歌曲 id
|
|
28
|
+
qrc: 是否返回逐字歌词
|
|
29
|
+
trans: 是否返回翻译歌词
|
|
30
|
+
roma: 是否返回罗马歌词
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
{"lyric": 歌词或逐字歌词, "trans": 翻译歌词, "roma": 罗马歌词}
|
|
34
|
+
"""
|
|
35
|
+
if mid is None and id is None:
|
|
36
|
+
raise ValueError("mid or id must be provided")
|
|
37
|
+
|
|
38
|
+
params = {
|
|
39
|
+
"crypt": 1,
|
|
40
|
+
"ct": 11,
|
|
41
|
+
"cv": 13020508,
|
|
42
|
+
"lrc_t": 0,
|
|
43
|
+
"qrc": qrc,
|
|
44
|
+
"qrc_t": 0,
|
|
45
|
+
"roma": roma,
|
|
46
|
+
"roma_t": 0,
|
|
47
|
+
"songId": id,
|
|
48
|
+
"songMid": mid,
|
|
49
|
+
"trans": trans,
|
|
50
|
+
"trans_t": 0,
|
|
51
|
+
"type": 1,
|
|
52
|
+
}
|
|
53
|
+
res = await Api(**API["info"]).update_params(**params).result
|
|
54
|
+
|
|
55
|
+
lyric = qrc_decrypt(res["lyric"])
|
|
56
|
+
|
|
57
|
+
if lyric and qrc:
|
|
58
|
+
tree = ET.fromstring(lyric)
|
|
59
|
+
try:
|
|
60
|
+
lyric = tree.find(".//Lyric_0").attrib.get("LyricContent", "") # type: ignore
|
|
61
|
+
except AttributeError:
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
"lyric": lyric,
|
|
66
|
+
"trans": qrc_decrypt(res["trans"]),
|
|
67
|
+
"roma": qrc_decrypt(res["roma"]),
|
|
68
|
+
}
|
|
@@ -85,8 +85,8 @@ async def general_search(
|
|
|
85
85
|
|
|
86
86
|
Args:
|
|
87
87
|
keyword: 关键词
|
|
88
|
-
page:
|
|
89
|
-
highlight:
|
|
88
|
+
page: 页码
|
|
89
|
+
highlight: 是否高亮关键词
|
|
90
90
|
|
|
91
91
|
Returns:
|
|
92
92
|
包含直接结果,歌曲,歌手,专辑,歌单,mv等.
|
|
@@ -114,10 +114,10 @@ async def search_by_type(
|
|
|
114
114
|
|
|
115
115
|
Args:
|
|
116
116
|
keyword: 关键词
|
|
117
|
-
search_type:
|
|
118
|
-
num:
|
|
119
|
-
page:
|
|
120
|
-
highlight:
|
|
117
|
+
search_type: 搜索类型
|
|
118
|
+
num: 返回数量
|
|
119
|
+
page: 页码
|
|
120
|
+
highlight: 是否高亮关键词
|
|
121
121
|
|
|
122
122
|
Returns:
|
|
123
123
|
搜索结果
|
|
@@ -19,6 +19,7 @@ class SongFileType(Enum):
|
|
|
19
19
|
+ NEW_1: 臻品全景声
|
|
20
20
|
+ NEW_2: 臻品音质2.0
|
|
21
21
|
+ FLAC: 无损音频压缩格式
|
|
22
|
+
+ OGG_320: OGG 格式,320kbps,size_new[3]
|
|
22
23
|
+ OGG_192: OGG 格式,192kbps
|
|
23
24
|
+ OGG_96: OGG 格式,96kbps
|
|
24
25
|
+ MP3_320: MP3 格式,320kbps
|
|
@@ -26,13 +27,13 @@ class SongFileType(Enum):
|
|
|
26
27
|
+ ACC_192: AAC 格式,192kbps
|
|
27
28
|
+ ACC_96: AAC 格式,96kbps
|
|
28
29
|
+ ACC_48: AAC 格式,48kbps
|
|
29
|
-
+ TRY: 试听文件
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
32
|
NEW_0 = ("AI00", ".flac")
|
|
33
33
|
NEW_1 = ("Q000", ".flac")
|
|
34
34
|
NEW_2 = ("Q001", ".flac")
|
|
35
35
|
FLAC = ("F000", ".flac")
|
|
36
|
+
OGG_320 = ("O800", ".ogg")
|
|
36
37
|
OGG_192 = ("O600", ".ogg")
|
|
37
38
|
OGG_96 = ("O400", ".ogg")
|
|
38
39
|
MP3_320 = ("M800", ".mp3")
|
|
@@ -40,7 +41,6 @@ class SongFileType(Enum):
|
|
|
40
41
|
ACC_192 = ("C600", ".m4a")
|
|
41
42
|
ACC_96 = ("C400", ".m4a")
|
|
42
43
|
ACC_48 = ("C200", ".m4a")
|
|
43
|
-
TRY = ("RS02", ".mp3")
|
|
44
44
|
|
|
45
45
|
def __init__(self, start_code: str, extension: str):
|
|
46
46
|
self.__start_code = start_code
|
|
@@ -55,15 +55,37 @@ class SongFileType(Enum):
|
|
|
55
55
|
return self.__extension
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
class
|
|
59
|
-
"""
|
|
58
|
+
class EncryptedSongFileType(Enum):
|
|
59
|
+
"""加密歌曲文件类型
|
|
60
60
|
|
|
61
|
-
+
|
|
62
|
-
+
|
|
61
|
+
+ NEW_0: 臻品母带2.0
|
|
62
|
+
+ NEW_1: 臻品全景声
|
|
63
|
+
+ NEW_2: 臻品音质2.0
|
|
64
|
+
+ FLAC: 无损音频压缩格式
|
|
65
|
+
+ OGG_320: OGG 格式,320kbps,size_new[3]
|
|
66
|
+
+ OGG_192: OGG 格式,192kbps
|
|
67
|
+
+ OGG_96: OGG 格式,96kbps
|
|
63
68
|
"""
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
NEW_0 = ("AIM0", ".mflac")
|
|
71
|
+
NEW_1 = ("Q0M0", ".mflac")
|
|
72
|
+
NEW_2 = ("Q0M1", ".mflac")
|
|
73
|
+
FLAC = ("F0M0", ".mflac")
|
|
74
|
+
OGG_320 = ("O800", ".mgg")
|
|
75
|
+
OGG_192 = ("O6M0", ".mgg")
|
|
76
|
+
OGG_96 = ("O4M0", ".mgg")
|
|
77
|
+
|
|
78
|
+
def __init__(self, start_code: str, extension: str):
|
|
79
|
+
self.__start_code = start_code
|
|
80
|
+
self.__extension = extension
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def s(self) -> str: # noqa : D102
|
|
84
|
+
return self.__start_code
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def e(self) -> str: # noqa: D102
|
|
88
|
+
return self.__extension
|
|
67
89
|
|
|
68
90
|
|
|
69
91
|
class Song:
|
|
@@ -80,9 +102,10 @@ class Song:
|
|
|
80
102
|
mid: Optional[str] = None,
|
|
81
103
|
id: Optional[int] = None,
|
|
82
104
|
):
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
"""初始化歌曲类
|
|
106
|
+
|
|
107
|
+
Note:
|
|
108
|
+
歌曲 mid 和 id,两者至少提供一个
|
|
86
109
|
|
|
87
110
|
Args:
|
|
88
111
|
mid: 歌曲 mid
|
|
@@ -167,9 +190,15 @@ class Song:
|
|
|
167
190
|
Returns:
|
|
168
191
|
MV信息
|
|
169
192
|
"""
|
|
170
|
-
return (
|
|
171
|
-
"
|
|
172
|
-
|
|
193
|
+
return (
|
|
194
|
+
await Api(**API["mv"])
|
|
195
|
+
.update_params(
|
|
196
|
+
songid=str(await self.get_id()),
|
|
197
|
+
songtype=1,
|
|
198
|
+
lastvid=0,
|
|
199
|
+
)
|
|
200
|
+
.result
|
|
201
|
+
)["list"]
|
|
173
202
|
|
|
174
203
|
async def get_other_version(self) -> list[dict]:
|
|
175
204
|
"""获取歌曲其他版本
|
|
@@ -197,21 +226,19 @@ class Song:
|
|
|
197
226
|
|
|
198
227
|
async def get_url(
|
|
199
228
|
self,
|
|
200
|
-
file_type: SongFileType = SongFileType.MP3_128,
|
|
201
|
-
url_type: UrlType = UrlType.PLAY,
|
|
229
|
+
file_type: Union[SongFileType, EncryptedSongFileType] = SongFileType.MP3_128,
|
|
202
230
|
credential: Optional[Credential] = None,
|
|
203
231
|
) -> str:
|
|
204
232
|
"""获取歌曲文件链接
|
|
205
233
|
|
|
206
234
|
Args:
|
|
207
|
-
file_type:
|
|
208
|
-
|
|
209
|
-
credential: 账号凭证. Defaults to None
|
|
235
|
+
file_type: 歌曲文件类型
|
|
236
|
+
credential: 账号凭证
|
|
210
237
|
|
|
211
238
|
Returns:
|
|
212
239
|
链接字典
|
|
213
240
|
"""
|
|
214
|
-
return (await get_song_urls([await self.get_mid()], file_type,
|
|
241
|
+
return (await get_song_urls([await self.get_mid()], file_type, credential))[self.mid][0]
|
|
215
242
|
|
|
216
243
|
|
|
217
244
|
async def query_song(value: Union[list[str], list[int]]) -> list[dict]:
|
|
@@ -242,26 +269,26 @@ async def query_song(value: Union[list[str], list[int]]) -> list[dict]:
|
|
|
242
269
|
|
|
243
270
|
async def get_song_urls(
|
|
244
271
|
mid: list[str],
|
|
245
|
-
file_type: SongFileType = SongFileType.MP3_128,
|
|
246
|
-
url_type: UrlType = UrlType.PLAY,
|
|
272
|
+
file_type: Union[EncryptedSongFileType, SongFileType] = SongFileType.MP3_128,
|
|
247
273
|
credential: Optional[Credential] = None,
|
|
248
|
-
) -> dict[str, str]:
|
|
274
|
+
) -> Union[dict[str, str], dict[str, tuple[str, str]]]:
|
|
249
275
|
"""获取歌曲文件链接
|
|
250
276
|
|
|
251
277
|
Args:
|
|
252
278
|
mid: 歌曲 mid
|
|
253
|
-
file_type:
|
|
254
|
-
|
|
255
|
-
credential: Credential 类. Defaluts to None
|
|
279
|
+
file_type: 歌曲文件类型
|
|
280
|
+
credential: Credential 类
|
|
256
281
|
|
|
257
282
|
Returns:
|
|
258
|
-
|
|
283
|
+
返回链接字典,加密歌曲返回 `ekey` 用于解密
|
|
259
284
|
"""
|
|
285
|
+
encrypted = isinstance(file_type, EncryptedSongFileType)
|
|
260
286
|
# 分割 id,单次最大请求100
|
|
261
287
|
mid_list = [mid[i : i + 100] for i in range(0, len(mid), 100)]
|
|
262
288
|
# 选择文件域名
|
|
263
|
-
domain = "https://isure.stream.qqmusic.qq.com/"
|
|
264
|
-
|
|
289
|
+
domain = "https://isure.stream.qqmusic.qq.com/"
|
|
290
|
+
api_data = API["play_url"] if not encrypted else API["evkey"]
|
|
291
|
+
api = Api(**api_data, credential=credential or Credential())
|
|
265
292
|
urls = {}
|
|
266
293
|
|
|
267
294
|
async def get_song_url(mid):
|
|
@@ -278,7 +305,42 @@ async def get_song_urls(
|
|
|
278
305
|
data = res["midurlinfo"]
|
|
279
306
|
for info in data:
|
|
280
307
|
song_url = domain + info["wifiurl"] if info["wifiurl"] else ""
|
|
281
|
-
|
|
308
|
+
if not encrypted:
|
|
309
|
+
urls[info["songmid"]] = song_url
|
|
310
|
+
else:
|
|
311
|
+
urls[info["songmid"]] = (song_url, info["ekey"])
|
|
282
312
|
|
|
283
313
|
await asyncio.gather(*[asyncio.create_task(get_song_url(mid)) for mid in mid_list])
|
|
284
314
|
return urls
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
async def get_try_url(mid: str, vs: str) -> Optional[str]:
|
|
318
|
+
"""获取试听文件链接
|
|
319
|
+
|
|
320
|
+
Tips:
|
|
321
|
+
使用 `size_try` 字段判断是否存在试听文件
|
|
322
|
+
参数 `vs` 请传入歌曲信息 `vs` 字段第一个
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
mid: 歌曲 mid
|
|
326
|
+
vs: 歌曲 vs
|
|
327
|
+
|
|
328
|
+
Returns:
|
|
329
|
+
试听文件链接
|
|
330
|
+
"""
|
|
331
|
+
res = await (
|
|
332
|
+
Api(**API["play_url"])
|
|
333
|
+
.update_params(
|
|
334
|
+
filename=[f"RS02{vs}.mp3"],
|
|
335
|
+
guid="".join(
|
|
336
|
+
random.choices("abedf1234567890", k=32),
|
|
337
|
+
),
|
|
338
|
+
songmid=[mid],
|
|
339
|
+
songtype=[1],
|
|
340
|
+
)
|
|
341
|
+
.result
|
|
342
|
+
)
|
|
343
|
+
if url := res["midurlinfo"][0]["wifiurl"]:
|
|
344
|
+
return f"https://isure.stream.qqmusic.qq.com/{url}"
|
|
345
|
+
else:
|
|
346
|
+
return None
|