qqmusic-api-python 0.2.0__py3-none-any.whl → 0.2.2__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.
- qqmusic_api/__init__.py +1 -1
- qqmusic_api/album.py +4 -4
- qqmusic_api/login.py +2 -3
- qqmusic_api/login_utils.py +7 -8
- qqmusic_api/lyric.py +9 -10
- qqmusic_api/singer.py +2 -2
- qqmusic_api/song.py +15 -15
- qqmusic_api/user.py +1 -3
- qqmusic_api/utils/common.py +3 -4
- qqmusic_api/utils/network.py +8 -7
- qqmusic_api/utils/session.py +4 -4
- qqmusic_api/utils/tripledes.py +1 -2
- {qqmusic_api_python-0.2.0.dist-info → qqmusic_api_python-0.2.2.dist-info}/METADATA +3 -3
- {qqmusic_api_python-0.2.0.dist-info → qqmusic_api_python-0.2.2.dist-info}/RECORD +16 -16
- {qqmusic_api_python-0.2.0.dist-info → qqmusic_api_python-0.2.2.dist-info}/WHEEL +0 -0
- {qqmusic_api_python-0.2.0.dist-info → qqmusic_api_python-0.2.2.dist-info}/licenses/LICENSE +0 -0
qqmusic_api/__init__.py
CHANGED
qqmusic_api/album.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""专辑相关 API"""
|
|
2
2
|
|
|
3
|
-
from typing import Literal
|
|
3
|
+
from typing import Literal
|
|
4
4
|
|
|
5
5
|
from .utils.common import get_api
|
|
6
6
|
from .utils.network import Api
|
|
@@ -34,8 +34,8 @@ class Album:
|
|
|
34
34
|
def __init__(
|
|
35
35
|
self,
|
|
36
36
|
*,
|
|
37
|
-
mid:
|
|
38
|
-
id:
|
|
37
|
+
mid: str | None = None,
|
|
38
|
+
id: int | None = None,
|
|
39
39
|
):
|
|
40
40
|
"""初始化专辑类
|
|
41
41
|
|
|
@@ -50,7 +50,7 @@ class Album:
|
|
|
50
50
|
raise ValueError("mid or id must be provided")
|
|
51
51
|
self.mid = mid or ""
|
|
52
52
|
self.id = id or 0
|
|
53
|
-
self._info:
|
|
53
|
+
self._info: dict | None = None
|
|
54
54
|
|
|
55
55
|
async def get_mid(self) -> str:
|
|
56
56
|
"""获取专辑 mid
|
qqmusic_api/login.py
CHANGED
|
@@ -5,7 +5,6 @@ import re
|
|
|
5
5
|
import time
|
|
6
6
|
import uuid
|
|
7
7
|
from enum import Enum, auto
|
|
8
|
-
from typing import Optional
|
|
9
8
|
|
|
10
9
|
import httpx
|
|
11
10
|
|
|
@@ -130,7 +129,7 @@ class QQLoginApi:
|
|
|
130
129
|
return qrsig, res.read()
|
|
131
130
|
|
|
132
131
|
@staticmethod
|
|
133
|
-
async def check_qrcode_state(qrsig: str) -> tuple[QrCodeLoginEvents,
|
|
132
|
+
async def check_qrcode_state(qrsig: str) -> tuple[QrCodeLoginEvents, Credential | None]:
|
|
134
133
|
"""检测二维码状态
|
|
135
134
|
|
|
136
135
|
Args:
|
|
@@ -299,7 +298,7 @@ class WXLoginApi:
|
|
|
299
298
|
return uuid, qrcode_data
|
|
300
299
|
|
|
301
300
|
@staticmethod
|
|
302
|
-
async def check_qrcode_state(uuid: str) -> tuple[QrCodeLoginEvents,
|
|
301
|
+
async def check_qrcode_state(uuid: str) -> tuple[QrCodeLoginEvents, Credential | None]:
|
|
303
302
|
"""检测二维码状态
|
|
304
303
|
|
|
305
304
|
Args:
|
qqmusic_api/login_utils.py
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import sys
|
|
7
7
|
from abc import ABC, abstractmethod
|
|
8
|
-
from typing import Optional
|
|
9
8
|
|
|
10
9
|
from .exceptions.api_exception import LoginError
|
|
11
10
|
|
|
@@ -26,7 +25,7 @@ class Login(ABC):
|
|
|
26
25
|
"""
|
|
27
26
|
|
|
28
27
|
def __init__(self) -> None:
|
|
29
|
-
self.credential:
|
|
28
|
+
self.credential: Credential | None = None
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
class QRCodeLogin(Login):
|
|
@@ -34,8 +33,8 @@ class QRCodeLogin(Login):
|
|
|
34
33
|
|
|
35
34
|
def __init__(self) -> None:
|
|
36
35
|
super().__init__()
|
|
37
|
-
self._state:
|
|
38
|
-
self._qrcode_data:
|
|
36
|
+
self._state: QrCodeLoginEvents | None = None
|
|
37
|
+
self._qrcode_data: bytes | None = None
|
|
39
38
|
|
|
40
39
|
@abstractmethod
|
|
41
40
|
async def get_qrcode(self) -> bytes:
|
|
@@ -46,7 +45,7 @@ class QRCodeLogin(Login):
|
|
|
46
45
|
"""
|
|
47
46
|
|
|
48
47
|
@abstractmethod
|
|
49
|
-
async def check_qrcode_state(self) -> tuple[QrCodeLoginEvents,
|
|
48
|
+
async def check_qrcode_state(self) -> tuple[QrCodeLoginEvents, Credential | None]:
|
|
50
49
|
"""检测二维码状态
|
|
51
50
|
|
|
52
51
|
Returns:
|
|
@@ -69,7 +68,7 @@ class QQLogin(QRCodeLogin):
|
|
|
69
68
|
return self._qrcode_data
|
|
70
69
|
|
|
71
70
|
@override
|
|
72
|
-
async def check_qrcode_state(self) -> tuple[QrCodeLoginEvents,
|
|
71
|
+
async def check_qrcode_state(self) -> tuple[QrCodeLoginEvents, Credential | None]:
|
|
73
72
|
if self._state == QrCodeLoginEvents.DONE and self.credential:
|
|
74
73
|
return self._state, self.credential
|
|
75
74
|
if not self._qrsig:
|
|
@@ -94,7 +93,7 @@ class WXLogin(QRCodeLogin):
|
|
|
94
93
|
return self._qrcode_data
|
|
95
94
|
|
|
96
95
|
@override
|
|
97
|
-
async def check_qrcode_state(self) -> tuple[QrCodeLoginEvents,
|
|
96
|
+
async def check_qrcode_state(self) -> tuple[QrCodeLoginEvents, Credential | None]:
|
|
98
97
|
if self._state == QrCodeLoginEvents.DONE and self.credential:
|
|
99
98
|
return self._state, self.credential
|
|
100
99
|
if not self._uuid:
|
|
@@ -118,7 +117,7 @@ class PhoneLogin(Login):
|
|
|
118
117
|
self.phone = phone
|
|
119
118
|
self.area_code = area_code
|
|
120
119
|
self.auth_url = ""
|
|
121
|
-
self._state:
|
|
120
|
+
self._state: PhoneLoginEvents | None = None
|
|
122
121
|
self.error_msg = ""
|
|
123
122
|
|
|
124
123
|
async def send_authcode(self) -> PhoneLoginEvents:
|
qqmusic_api/lyric.py
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"""歌词 API"""
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
from typing import Optional
|
|
3
|
+
import re
|
|
5
4
|
|
|
6
5
|
from .utils.common import get_api, qrc_decrypt
|
|
7
6
|
from .utils.network import Api
|
|
8
7
|
|
|
9
8
|
API = get_api("lyric")
|
|
10
9
|
|
|
10
|
+
QRC_PATTERN = re.compile(r'<Lyric_.* LyricType=".*" LyricContent="(?P<content>.*?)"/>', re.DOTALL)
|
|
11
|
+
|
|
11
12
|
|
|
12
13
|
async def get_lyric(
|
|
13
14
|
*,
|
|
14
|
-
mid:
|
|
15
|
-
id:
|
|
15
|
+
mid: str | None = None,
|
|
16
|
+
id: int | None = None,
|
|
16
17
|
qrc: bool = False,
|
|
17
18
|
trans: bool = False,
|
|
18
19
|
roma: bool = False,
|
|
@@ -53,14 +54,12 @@ async def get_lyric(
|
|
|
53
54
|
res = await Api(**API["info"]).update_params(**params).result
|
|
54
55
|
|
|
55
56
|
lyric = qrc_decrypt(res["lyric"])
|
|
57
|
+
|
|
56
58
|
|
|
57
59
|
if lyric and qrc:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
lyric = lyric_info[0].attrib.get("LyricContent", lyric)
|
|
62
|
-
except Exception:
|
|
63
|
-
pass
|
|
60
|
+
m_qrc = QRC_PATTERN.search(lyric)
|
|
61
|
+
if m_qrc and m_qrc.group("content"):
|
|
62
|
+
lyric = m_qrc.group("content")
|
|
64
63
|
|
|
65
64
|
return {
|
|
66
65
|
"lyric": lyric,
|
qqmusic_api/singer.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""歌手相关 API"""
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from typing import Literal
|
|
4
|
+
from typing import Literal
|
|
5
5
|
|
|
6
6
|
from .utils.common import get_api
|
|
7
7
|
from .utils.network import Api
|
|
@@ -151,7 +151,7 @@ class Singer:
|
|
|
151
151
|
mid: 歌手 mid
|
|
152
152
|
"""
|
|
153
153
|
self.mid = mid
|
|
154
|
-
self._info:
|
|
154
|
+
self._info: dict | None = None
|
|
155
155
|
|
|
156
156
|
async def get_info(self) -> dict:
|
|
157
157
|
"""获取歌手信息
|
qqmusic_api/song.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from enum import Enum
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import overload
|
|
6
6
|
|
|
7
7
|
from .utils.common import get_api, get_guid
|
|
8
8
|
from .utils.credential import Credential
|
|
@@ -11,7 +11,7 @@ from .utils.network import Api
|
|
|
11
11
|
API = get_api("song")
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
async def query_song(value:
|
|
14
|
+
async def query_song(value: list[str] | list[int]) -> list[dict]:
|
|
15
15
|
"""根据 id 或 mid 获取歌曲信息
|
|
16
16
|
|
|
17
17
|
Args:
|
|
@@ -115,7 +115,7 @@ class EncryptedSongFileType(BaseSongFileType):
|
|
|
115
115
|
async def get_song_urls(
|
|
116
116
|
mid: list[str],
|
|
117
117
|
file_type: SongFileType = SongFileType.MP3_128,
|
|
118
|
-
credential:
|
|
118
|
+
credential: Credential | None = None,
|
|
119
119
|
) -> dict[str, str]: ...
|
|
120
120
|
|
|
121
121
|
|
|
@@ -123,15 +123,15 @@ async def get_song_urls(
|
|
|
123
123
|
async def get_song_urls(
|
|
124
124
|
mid: list[str],
|
|
125
125
|
file_type: EncryptedSongFileType,
|
|
126
|
-
credential:
|
|
126
|
+
credential: Credential | None = None,
|
|
127
127
|
) -> dict[str, tuple[str, str]]: ...
|
|
128
128
|
|
|
129
129
|
|
|
130
130
|
async def get_song_urls(
|
|
131
131
|
mid: list[str],
|
|
132
|
-
file_type:
|
|
133
|
-
credential:
|
|
134
|
-
) ->
|
|
132
|
+
file_type: EncryptedSongFileType | SongFileType = SongFileType.MP3_128,
|
|
133
|
+
credential: Credential | None = None,
|
|
134
|
+
) -> dict[str, str] | dict[str, tuple[str, str]]:
|
|
135
135
|
"""获取歌曲文件链接
|
|
136
136
|
|
|
137
137
|
Tips:
|
|
@@ -218,8 +218,8 @@ class Song:
|
|
|
218
218
|
def __init__(
|
|
219
219
|
self,
|
|
220
220
|
*,
|
|
221
|
-
mid:
|
|
222
|
-
id:
|
|
221
|
+
mid: str | None = None,
|
|
222
|
+
id: int | None = None,
|
|
223
223
|
):
|
|
224
224
|
"""初始化歌曲类
|
|
225
225
|
|
|
@@ -234,7 +234,7 @@ class Song:
|
|
|
234
234
|
raise ValueError("mid or id must be provided")
|
|
235
235
|
self.mid = mid or ""
|
|
236
236
|
self.id = id or 0
|
|
237
|
-
self._info:
|
|
237
|
+
self._info: dict | None = None
|
|
238
238
|
|
|
239
239
|
async def get_mid(self) -> str:
|
|
240
240
|
"""获取歌曲 mid
|
|
@@ -347,21 +347,21 @@ class Song:
|
|
|
347
347
|
async def get_url(
|
|
348
348
|
self,
|
|
349
349
|
file_type: SongFileType = SongFileType.MP3_128,
|
|
350
|
-
credential:
|
|
350
|
+
credential: Credential | None = None,
|
|
351
351
|
) -> str: ...
|
|
352
352
|
|
|
353
353
|
@overload
|
|
354
354
|
async def get_url(
|
|
355
355
|
self,
|
|
356
356
|
file_type: EncryptedSongFileType,
|
|
357
|
-
credential:
|
|
357
|
+
credential: Credential | None = None,
|
|
358
358
|
) -> tuple[str, str]: ...
|
|
359
359
|
|
|
360
360
|
async def get_url(
|
|
361
361
|
self,
|
|
362
|
-
file_type:
|
|
363
|
-
credential:
|
|
364
|
-
) ->
|
|
362
|
+
file_type: SongFileType | EncryptedSongFileType = SongFileType.MP3_128,
|
|
363
|
+
credential: Credential | None = None,
|
|
364
|
+
) -> str | tuple[str, str]:
|
|
365
365
|
"""获取歌曲文件链接
|
|
366
366
|
|
|
367
367
|
Tips:
|
qqmusic_api/user.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""用户相关 API"""
|
|
2
2
|
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
3
|
from .exceptions import ResponseCodeError
|
|
6
4
|
from .utils.common import get_api
|
|
7
5
|
from .utils.credential import Credential
|
|
@@ -88,7 +86,7 @@ class User:
|
|
|
88
86
|
credential: 账号凭证
|
|
89
87
|
"""
|
|
90
88
|
|
|
91
|
-
def __init__(self, euin: str, credential:
|
|
89
|
+
def __init__(self, euin: str, credential: Credential | None = None):
|
|
92
90
|
"""初始化用户类
|
|
93
91
|
|
|
94
92
|
传入有效 credential 获取他人的信息会更完整但会留痕,且部分 API 不会验证
|
qqmusic_api/utils/common.py
CHANGED
|
@@ -6,12 +6,11 @@ import os
|
|
|
6
6
|
import random
|
|
7
7
|
import time
|
|
8
8
|
import zlib
|
|
9
|
-
from typing import Union
|
|
10
9
|
|
|
11
10
|
from .tripledes import DECRYPT, tripledes_crypt, tripledes_key_setup
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
def calc_md5(*strings:
|
|
13
|
+
def calc_md5(*strings: str | bytes) -> str:
|
|
15
14
|
"""计算 MD5 值"""
|
|
16
15
|
md5 = hashlib.md5()
|
|
17
16
|
for item in strings:
|
|
@@ -78,7 +77,7 @@ def get_searchID() -> str:
|
|
|
78
77
|
return str(t + n + r)
|
|
79
78
|
|
|
80
79
|
|
|
81
|
-
def qrc_decrypt(encrypted_qrc:
|
|
80
|
+
def qrc_decrypt(encrypted_qrc: str | bytearray | bytes) -> str:
|
|
82
81
|
"""QRC 解码
|
|
83
82
|
|
|
84
83
|
Args:
|
|
@@ -96,7 +95,7 @@ def qrc_decrypt(encrypted_qrc: Union[str, bytearray, bytes]) -> str:
|
|
|
96
95
|
# 将输入转为 bytearray 格式
|
|
97
96
|
if isinstance(encrypted_qrc, str):
|
|
98
97
|
encrypted_qrc = bytearray.fromhex(encrypted_qrc)
|
|
99
|
-
elif isinstance(encrypted_qrc,
|
|
98
|
+
elif isinstance(encrypted_qrc, bytearray | bytes):
|
|
100
99
|
encrypted_qrc = bytearray(encrypted_qrc)
|
|
101
100
|
else:
|
|
102
101
|
raise ValueError("无效的加密数据类型")
|
qqmusic_api/utils/network.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import sys
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
|
-
from typing import Any, Literal
|
|
6
|
+
from typing import Any, Literal
|
|
7
7
|
|
|
8
8
|
import httpx
|
|
9
9
|
|
|
@@ -60,7 +60,7 @@ class Api:
|
|
|
60
60
|
self.data = {k: None for k in self.data}
|
|
61
61
|
self.params = {k: None for k in self.params}
|
|
62
62
|
self.extra_common = {k: None for k in self.extra_common}
|
|
63
|
-
self._result:
|
|
63
|
+
self._result: dict | None = None
|
|
64
64
|
self._session = get_session()
|
|
65
65
|
self._cookies = httpx.Cookies()
|
|
66
66
|
|
|
@@ -191,7 +191,7 @@ class Api:
|
|
|
191
191
|
|
|
192
192
|
config = {
|
|
193
193
|
"url": self.url,
|
|
194
|
-
"method":
|
|
194
|
+
"method": "POST" if self.module else self.method,
|
|
195
195
|
"params": self.params,
|
|
196
196
|
"headers": self.headers,
|
|
197
197
|
}
|
|
@@ -212,11 +212,12 @@ class Api:
|
|
|
212
212
|
)
|
|
213
213
|
|
|
214
214
|
resp = await self._session.request(**config)
|
|
215
|
-
|
|
215
|
+
if not self.ignore_code:
|
|
216
|
+
resp.raise_for_status()
|
|
216
217
|
self._session.cookies.clear()
|
|
217
218
|
return resp
|
|
218
219
|
|
|
219
|
-
def _process_response(self, resp: httpx.Response) ->
|
|
220
|
+
def _process_response(self, resp: httpx.Response) -> None | str | dict:
|
|
220
221
|
"""处理响应"""
|
|
221
222
|
content_length = resp.headers.get("Content-Length")
|
|
222
223
|
if content_length and int(content_length) == 0:
|
|
@@ -226,7 +227,7 @@ class Api:
|
|
|
226
227
|
except json.decoder.JSONDecodeError:
|
|
227
228
|
return resp.text
|
|
228
229
|
|
|
229
|
-
async def fetch(self) ->
|
|
230
|
+
async def fetch(self) -> None | str | dict:
|
|
230
231
|
"""发起请求并处理响应"""
|
|
231
232
|
return self._process_response(await self.request())
|
|
232
233
|
|
|
@@ -261,8 +262,8 @@ class Api:
|
|
|
261
262
|
# 是否忽略响应代码
|
|
262
263
|
if self.ignore_code:
|
|
263
264
|
return resp
|
|
264
|
-
code = resp["code"]
|
|
265
265
|
|
|
266
|
+
code = resp["code"]
|
|
266
267
|
if self.module:
|
|
267
268
|
logger.debug(
|
|
268
269
|
"API %s.%s: %s",
|
qqmusic_api/utils/session.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from collections import deque
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import TypedDict
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
8
8
|
|
|
@@ -27,7 +27,7 @@ class Session(httpx.AsyncClient):
|
|
|
27
27
|
HOST = "y.qq.com"
|
|
28
28
|
UA_DEFAULT = "Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.54"
|
|
29
29
|
|
|
30
|
-
def __init__(self, *, credential:
|
|
30
|
+
def __init__(self, *, credential: Credential | None = None, enable_sign: bool = False, **kwargs) -> None:
|
|
31
31
|
super().__init__(**kwargs)
|
|
32
32
|
self.credential = credential or Credential()
|
|
33
33
|
self.headers = httpx.Headers(
|
|
@@ -112,7 +112,7 @@ class SessionManager:
|
|
|
112
112
|
if self.context_stack.get(loop):
|
|
113
113
|
self.context_stack[loop].pop()
|
|
114
114
|
|
|
115
|
-
def create_session(self, credential:
|
|
115
|
+
def create_session(self, credential: Credential | None = None, enable_sign: bool = False) -> Session:
|
|
116
116
|
"""创建新的 Session"""
|
|
117
117
|
session = Session(credential=credential, enable_sign=enable_sign)
|
|
118
118
|
self.session_pool[get_loop()] = session
|
|
@@ -139,7 +139,7 @@ def set_session(session: Session) -> None:
|
|
|
139
139
|
session_manager.set(session)
|
|
140
140
|
|
|
141
141
|
|
|
142
|
-
def create_session(credential:
|
|
142
|
+
def create_session(credential: Credential | None = None, enable_sign: bool = False) -> Session:
|
|
143
143
|
"""创建新的 Session
|
|
144
144
|
|
|
145
145
|
Args:
|
qqmusic_api/utils/tripledes.py
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
# SPDX-FileCopyrightText: Copyright (c) 2024 沉默の金 <cmzj@cmzj.org>
|
|
11
11
|
# SPDX-License-Identifier: GPL-3.0-only
|
|
12
|
-
from typing import Union
|
|
13
12
|
|
|
14
13
|
ENCRYPT = 1
|
|
15
14
|
DECRYPT = 0
|
|
@@ -65,7 +64,7 @@ sbox = (
|
|
|
65
64
|
) # fmt: skip
|
|
66
65
|
|
|
67
66
|
|
|
68
|
-
def bitnum(a:
|
|
67
|
+
def bitnum(a: bytearray | bytes, b: int, c: int) -> int:
|
|
69
68
|
"""从字节串中提取指定位置的位,并左移指定偏移量
|
|
70
69
|
|
|
71
70
|
Args:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qqmusic-api-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: QQ音乐API封装库
|
|
5
5
|
Project-URL: homepage, https://luren-dc.github.io/QQMusicApi/
|
|
6
6
|
Project-URL: repository, https://github.com/luren-dc/QQMusicApi
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.9
|
|
21
21
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
-
Requires-Python: >=3.
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
24
|
Requires-Dist: cryptography<44.0.1,>=44.0.0
|
|
25
25
|
Requires-Dist: httpx>=0.27.0
|
|
26
26
|
Requires-Dist: typing-extensions>=4.12.2
|
|
@@ -31,7 +31,7 @@ Description-Content-Type: text/markdown
|
|
|
31
31
|
<img src="https://socialify.git.ci/luren-dc/QQMusicApi/image?description=1&font=Source%20Code%20Pro&language=1&logo=https%3A%2F%2Fy.qq.com%2Fmediastyle%2Fmod%2Fmobile%2Fimg%2Flogo.svg&name=1&pattern=Overlapping%20Hexagons&theme=Auto">
|
|
32
32
|
</a>
|
|
33
33
|
<a href="https://www.python.org">
|
|
34
|
-
<img src="https://img.shields.io/badge/Python-3.
|
|
34
|
+
<img src="https://img.shields.io/badge/Python-3.10|3.11|3.12-blue" alt="Python">
|
|
35
35
|
</a>
|
|
36
36
|
<a href="https://github.com/luren-dc/QQMusicApi?tab=MIT-1-ov-file">
|
|
37
37
|
<img src="https://img.shields.io/github/license/luren-dc/QQMusicApi" alt="GitHub license">
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
qqmusic_api/__init__.py,sha256=
|
|
2
|
-
qqmusic_api/album.py,sha256=
|
|
3
|
-
qqmusic_api/login.py,sha256=
|
|
4
|
-
qqmusic_api/login_utils.py,sha256=
|
|
5
|
-
qqmusic_api/lyric.py,sha256=
|
|
1
|
+
qqmusic_api/__init__.py,sha256=MsB0ijfLk7SvlC28_k-NqeSxN8wu_hRx62qg_7yNKBA,620
|
|
2
|
+
qqmusic_api/album.py,sha256=cHasufexbQwQoqUWcF2C0-9ELtoyKMxjk7BNkQ5rCO8,2205
|
|
3
|
+
qqmusic_api/login.py,sha256=zRUPcmAZ5LiUfO9uShJfZ5Xc4n2bCxe55kDxLpknB0k,13289
|
|
4
|
+
qqmusic_api/login_utils.py,sha256=_sObteyghUSDSHCkAeFHQrgpf7FO_5I_YyQKIts-3Vg,4153
|
|
5
|
+
qqmusic_api/lyric.py,sha256=TCVi8tJ_so8-S14be6e6B2pDYFLw94sKKF5C7MZ0hU4,1563
|
|
6
6
|
qqmusic_api/mv.py,sha256=FUpOFphGsui6I1rPe4Z2B6dTbKF_lCUE1lQSD_igWmk,2833
|
|
7
7
|
qqmusic_api/search.py,sha256=V4sfFt-xmc7wKgYxN_hSSFKL8mISoDZ5BxXj0RuxY6U,3214
|
|
8
|
-
qqmusic_api/singer.py,sha256=
|
|
9
|
-
qqmusic_api/song.py,sha256=
|
|
8
|
+
qqmusic_api/singer.py,sha256=YPBjh0s6vUX7Gy03jOqJcJ47DgPZp1hVRE7w767PvG0,4688
|
|
9
|
+
qqmusic_api/song.py,sha256=bpQQYJ8TVwWSLCaFPUgwLGTOL5py3NeqJqX_ggwy9Wg,10631
|
|
10
10
|
qqmusic_api/songlist.py,sha256=v-M1pgshcP5md3Q2wEtHrRNPCXq_Ki9feNQzoPGMRFY,1400
|
|
11
11
|
qqmusic_api/top.py,sha256=ItnA9jjB_X3tgIMycLo-j5wd_Y4pGJa5D4CJ8NeaUpU,1111
|
|
12
|
-
qqmusic_api/user.py,sha256=
|
|
12
|
+
qqmusic_api/user.py,sha256=uwz2ji06bLXI00VGqhulhuGRkNkbr2wxAwcFE0BpisA,7437
|
|
13
13
|
qqmusic_api/data/file_type.json,sha256=9elRs6M4X-urNFUbLIg3YQ0z4mjjbtw3FEH_jDN0FgY,739
|
|
14
14
|
qqmusic_api/data/search_type.json,sha256=bw7GZcY6BhAsMl4I6q-21r74wT7rbeSf_sdHLjCMSpw,136
|
|
15
15
|
qqmusic_api/data/api/album.json,sha256=oUAhieL2GNw8WS2ersujJobn4_J-MngFSeEElORKvyU,535
|
|
@@ -25,16 +25,16 @@ qqmusic_api/data/api/user.json,sha256=03wmzKQWcdPLuubwhHQA-YheYSQYV-3Vm9K2oZUM6N
|
|
|
25
25
|
qqmusic_api/exceptions/__init__.py,sha256=KMohYPXJBcxigc1dpAioTPmPUHAQgOKXR4bkmv50EIQ,328
|
|
26
26
|
qqmusic_api/exceptions/api_exception.py,sha256=CTex5NMVNk42oJE0ADFFtAFWK4smchkgPTgRyRHb7O4,1609
|
|
27
27
|
qqmusic_api/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
qqmusic_api/utils/common.py,sha256=
|
|
28
|
+
qqmusic_api/utils/common.py,sha256=8CED56S_x4ojRZE3JZSLUFv_RQrSOhaQx8M7CxI_yC4,2649
|
|
29
29
|
qqmusic_api/utils/credential.py,sha256=hd6vbriajonG2YXYJPC-Z2-dnRVDQnrY4dJ5ABoZRZs,4391
|
|
30
30
|
qqmusic_api/utils/device.py,sha256=6IfMPsI3ZU4PAUYPMERL-mN20bueR_Ku5wxm8_rDh2A,2866
|
|
31
|
-
qqmusic_api/utils/network.py,sha256=
|
|
31
|
+
qqmusic_api/utils/network.py,sha256=aSRBeQ2BSc2is0R7QnaPd0eYG74kWRx2MCOviNqB5XY,8895
|
|
32
32
|
qqmusic_api/utils/qimei.py,sha256=pM7mF3pto-ylu3uYSpYF6Uh0b6b4qLEGnkJQXiLm87k,5473
|
|
33
|
-
qqmusic_api/utils/session.py,sha256=
|
|
33
|
+
qqmusic_api/utils/session.py,sha256=wPe8kQ31WFCLhzwGGBzJPjDDAiS65E1DQ4Q54FYBLfU,5388
|
|
34
34
|
qqmusic_api/utils/sign.py,sha256=774CzI1WNHSh0CVkgY1MZLjgj7R5WVX8Q3ZUyU70lbk,1395
|
|
35
35
|
qqmusic_api/utils/sync.py,sha256=av7Z4sdL5myf8ceR-pn26_31cvkN5h9D7-iE4Q0OrTs,741
|
|
36
|
-
qqmusic_api/utils/tripledes.py,sha256=
|
|
37
|
-
qqmusic_api_python-0.2.
|
|
38
|
-
qqmusic_api_python-0.2.
|
|
39
|
-
qqmusic_api_python-0.2.
|
|
40
|
-
qqmusic_api_python-0.2.
|
|
36
|
+
qqmusic_api/utils/tripledes.py,sha256=v_ivJ64MD3AZ8soN_7wx_3wL0rSBXCDeqe0GyOHrXLk,15852
|
|
37
|
+
qqmusic_api_python-0.2.2.dist-info/METADATA,sha256=Fb1e1k5LC1RYbU65ZJ-Z8d3tI-rsZkefEdJB9NZOt3I,3849
|
|
38
|
+
qqmusic_api_python-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
39
|
+
qqmusic_api_python-0.2.2.dist-info/licenses/LICENSE,sha256=dWHDhxdkwc4EVZ0xMf13_qTkjzPqbI1YL_1OzmZxaxU,1062
|
|
40
|
+
qqmusic_api_python-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|