p115client 0.0.5.10.6__tar.gz → 0.0.5.10.8__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.
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/PKG-INFO +4 -4
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/client.py +422 -115
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/const.py +1 -1
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/exception.py +8 -2
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/iterdir.py +0 -6
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/pyproject.toml +3 -3
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/readme.md +1 -1
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/LICENSE +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/__init__.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/_upload.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/py.typed +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/__init__.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/attr.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/download.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/edit.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/export_dir.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/fs_files.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/history.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/life.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/pool.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/request.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/upload.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/util.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/tool/xys.py +0 -0
- {p115client-0.0.5.10.6 → p115client-0.0.5.10.8}/p115client/type.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: p115client
|
3
|
-
Version: 0.0.5.10.
|
3
|
+
Version: 0.0.5.10.8
|
4
4
|
Summary: Python 115 webdisk client.
|
5
5
|
Home-page: https://github.com/ChenyangGao/p115client
|
6
6
|
License: MIT
|
@@ -23,8 +23,8 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
23
|
Requires-Dist: aiofile
|
24
24
|
Requires-Dist: ed2k (>=0.0.2.1)
|
25
25
|
Requires-Dist: http_response (>=0.0.2.2)
|
26
|
-
Requires-Dist: httpx
|
27
|
-
Requires-Dist: httpx_request (>=0.1.
|
26
|
+
Requires-Dist: httpx (>=0.28)
|
27
|
+
Requires-Dist: httpx_request (>=0.1.4)
|
28
28
|
Requires-Dist: iter_collect (>=0.0.5.1)
|
29
29
|
Requires-Dist: multidict
|
30
30
|
Requires-Dist: orjson
|
@@ -247,7 +247,7 @@ class MyCustom115Client(P115Client):
|
|
247
247
|
|
248
248
|
### 3. 检查响应
|
249
249
|
|
250
|
-
接口被调用后,如果返回的是 dict 类型的数据(说明原本是 JSON),则可以用 `p115client.check_response` 执行检查。首先会查看其中名为 "state" 的键的对应值,如果为 True、1 或不存在,则原样返回被检查的数据;否则,"state" 的对应值大概是 False 或 0,说明有问题出现,会根据实际情况抛出一个异常,但都是 `
|
250
|
+
接口被调用后,如果返回的是 dict 类型的数据(说明原本是 JSON),则可以用 `p115client.check_response` 执行检查。首先会查看其中名为 "state" 的键的对应值,如果为 True、1 或不存在,则原样返回被检查的数据;否则,"state" 的对应值大概是 False 或 0,说明有问题出现,会根据实际情况抛出一个异常,但都是 `p115client.P115OSError` 的实例。
|
251
251
|
|
252
252
|
```python
|
253
253
|
from p115client import check_response
|
@@ -65,8 +65,8 @@ from yarl import URL
|
|
65
65
|
|
66
66
|
from .const import CLASS_TO_TYPE, CLIENT_API_MAP, SSOENT_TO_APP, SUFFIX_TO_TYPE, errno
|
67
67
|
from .exception import (
|
68
|
-
AuthenticationError, BusyOSError, DataError, LoginError,
|
69
|
-
P115OSError, OperationalError, P115Warning, P115FileExistsError,
|
68
|
+
AuthenticationError, BusyOSError, DataError, LoginError, OpenAppAuthLimitExceeded,
|
69
|
+
NotSupportedError, P115OSError, OperationalError, P115Warning, P115FileExistsError,
|
70
70
|
P115FileNotFoundError, P115IsADirectoryError,
|
71
71
|
)
|
72
72
|
from .type import RequestKeywords, MultipartResumeData, P115Cookies, P115URL
|
@@ -339,6 +339,10 @@ def get_first(m: Mapping, /, *keys, default=None):
|
|
339
339
|
return default
|
340
340
|
|
341
341
|
|
342
|
+
def contains_any(m: Mapping, /, *keys):
|
343
|
+
return any(k in m for k in keys)
|
344
|
+
|
345
|
+
|
342
346
|
@overload
|
343
347
|
def check_response(resp: dict, /) -> dict:
|
344
348
|
...
|
@@ -525,7 +529,7 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
|
|
525
529
|
raise OperationalError(errno.EINVAL, resp)
|
526
530
|
# {"state": 0, "errno": 40140122, "error": "超出授权应用个数上限"}
|
527
531
|
case 40140122:
|
528
|
-
raise
|
532
|
+
raise OpenAppAuthLimitExceeded(errno.EDQUOT, resp)
|
529
533
|
# {"state": 0, "errno": 40140123, "error": "access_token 格式错误(防篡改)"}
|
530
534
|
case 40140123:
|
531
535
|
raise OperationalError(errno.EINVAL, resp)
|
@@ -1286,6 +1290,8 @@ class ClientRequestMixin:
|
|
1286
1290
|
payload: str | dict,
|
1287
1291
|
/,
|
1288
1292
|
request: None | Callable = None,
|
1293
|
+
app: str = "web",
|
1294
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1289
1295
|
*,
|
1290
1296
|
async_: Literal[False] = False,
|
1291
1297
|
**request_kwargs,
|
@@ -1297,6 +1303,8 @@ class ClientRequestMixin:
|
|
1297
1303
|
payload: str | dict,
|
1298
1304
|
/,
|
1299
1305
|
request: None | Callable = None,
|
1306
|
+
app: str = "web",
|
1307
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1300
1308
|
*,
|
1301
1309
|
async_: Literal[True],
|
1302
1310
|
**request_kwargs,
|
@@ -1307,6 +1315,8 @@ class ClientRequestMixin:
|
|
1307
1315
|
payload: str | dict,
|
1308
1316
|
/,
|
1309
1317
|
request: None | Callable = None,
|
1318
|
+
app: str = "web",
|
1319
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1310
1320
|
*,
|
1311
1321
|
async_: Literal[False, True] = False,
|
1312
1322
|
**request_kwargs,
|
@@ -1319,7 +1329,7 @@ class ClientRequestMixin:
|
|
1319
1329
|
|
1320
1330
|
:return: 图片的二进制数据(PNG 图片)
|
1321
1331
|
"""
|
1322
|
-
api = "
|
1332
|
+
api = complete_api(f"/api/1.0/{app}/1.0/qrcode", base_url=base_url)
|
1323
1333
|
if isinstance(payload, str):
|
1324
1334
|
payload = {"uid": payload}
|
1325
1335
|
request_kwargs.setdefault("parse", False)
|
@@ -1334,6 +1344,7 @@ class ClientRequestMixin:
|
|
1334
1344
|
payload: str | dict,
|
1335
1345
|
/,
|
1336
1346
|
request: None | Callable = None,
|
1347
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1337
1348
|
*,
|
1338
1349
|
async_: Literal[False] = False,
|
1339
1350
|
**request_kwargs,
|
@@ -1345,6 +1356,7 @@ class ClientRequestMixin:
|
|
1345
1356
|
payload: str | dict,
|
1346
1357
|
/,
|
1347
1358
|
request: None | Callable = None,
|
1359
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1348
1360
|
*,
|
1349
1361
|
async_: Literal[True],
|
1350
1362
|
**request_kwargs,
|
@@ -1355,6 +1367,7 @@ class ClientRequestMixin:
|
|
1355
1367
|
payload: str | dict,
|
1356
1368
|
/,
|
1357
1369
|
request: None | Callable = None,
|
1370
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1358
1371
|
*,
|
1359
1372
|
async_: Literal[False, True] = False,
|
1360
1373
|
**request_kwargs,
|
@@ -1371,7 +1384,7 @@ class ClientRequestMixin:
|
|
1371
1384
|
- uid: str
|
1372
1385
|
- code_verifier: str = <default> 💡 默认字符串是 64 个 "0"
|
1373
1386
|
"""
|
1374
|
-
api = "
|
1387
|
+
api = complete_api("/open/deviceCodeToToken", base_url=base_url)
|
1375
1388
|
if isinstance(payload, str):
|
1376
1389
|
payload = {"uid": payload, "code_verifier": _default_code_verifier}
|
1377
1390
|
request_kwargs.setdefault("parse", default_parse)
|
@@ -1386,6 +1399,7 @@ class ClientRequestMixin:
|
|
1386
1399
|
payload: str | dict,
|
1387
1400
|
/,
|
1388
1401
|
request: None | Callable = None,
|
1402
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1389
1403
|
*,
|
1390
1404
|
async_: Literal[False] = False,
|
1391
1405
|
**request_kwargs,
|
@@ -1397,6 +1411,7 @@ class ClientRequestMixin:
|
|
1397
1411
|
payload: str | dict,
|
1398
1412
|
/,
|
1399
1413
|
request: None | Callable = None,
|
1414
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1400
1415
|
*,
|
1401
1416
|
async_: Literal[True],
|
1402
1417
|
**request_kwargs,
|
@@ -1407,6 +1422,7 @@ class ClientRequestMixin:
|
|
1407
1422
|
payload: str | dict,
|
1408
1423
|
/,
|
1409
1424
|
request: None | Callable = None,
|
1425
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1410
1426
|
*,
|
1411
1427
|
async_: Literal[False, True] = False,
|
1412
1428
|
**request_kwargs,
|
@@ -1422,7 +1438,7 @@ class ClientRequestMixin:
|
|
1422
1438
|
:payload:
|
1423
1439
|
- refresh_token: str
|
1424
1440
|
"""
|
1425
|
-
api = "
|
1441
|
+
api = complete_api("/open/refreshToken", base_url=base_url)
|
1426
1442
|
if isinstance(payload, str):
|
1427
1443
|
payload = {"refresh_token": payload}
|
1428
1444
|
request_kwargs.setdefault("parse", default_parse)
|
@@ -1432,53 +1448,137 @@ class ClientRequestMixin:
|
|
1432
1448
|
return request(url=api, method="POST", data=payload, **request_kwargs)
|
1433
1449
|
|
1434
1450
|
@overload
|
1435
|
-
|
1451
|
+
def login_qrcode_scan(
|
1452
|
+
self,
|
1453
|
+
payload: str | dict,
|
1454
|
+
/,
|
1455
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1456
|
+
*,
|
1457
|
+
async_: Literal[False] = False,
|
1458
|
+
**request_kwargs,
|
1459
|
+
) -> dict:
|
1460
|
+
...
|
1461
|
+
@overload
|
1462
|
+
def login_qrcode_scan(
|
1463
|
+
self,
|
1464
|
+
payload: str | dict,
|
1465
|
+
/,
|
1466
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1467
|
+
*,
|
1468
|
+
async_: Literal[True],
|
1469
|
+
**request_kwargs,
|
1470
|
+
) -> Coroutine[Any, Any, dict]:
|
1471
|
+
...
|
1472
|
+
def login_qrcode_scan(
|
1473
|
+
self,
|
1474
|
+
payload: str | dict,
|
1475
|
+
/,
|
1476
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1477
|
+
*,
|
1478
|
+
async_: Literal[False, True] = False,
|
1479
|
+
**request_kwargs,
|
1480
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
1481
|
+
"""扫描二维码,payload 数据取自 `login_qrcode_token` 接口响应
|
1482
|
+
|
1483
|
+
GET https://qrcodeapi.115.com/api/2.0/prompt.php
|
1484
|
+
|
1485
|
+
:payload:
|
1486
|
+
- uid: str
|
1487
|
+
"""
|
1488
|
+
api = complete_api("/api/2.0/prompt.php", base_url=base_url)
|
1489
|
+
if isinstance(payload, str):
|
1490
|
+
payload = {"uid": payload}
|
1491
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
1492
|
+
|
1493
|
+
@overload
|
1436
1494
|
def login_qrcode_scan_cancel(
|
1495
|
+
self,
|
1437
1496
|
payload: str | dict,
|
1438
1497
|
/,
|
1439
|
-
|
1498
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1440
1499
|
*,
|
1441
1500
|
async_: Literal[False] = False,
|
1442
1501
|
**request_kwargs,
|
1443
1502
|
) -> dict:
|
1444
1503
|
...
|
1445
1504
|
@overload
|
1446
|
-
@staticmethod
|
1447
1505
|
def login_qrcode_scan_cancel(
|
1506
|
+
self,
|
1448
1507
|
payload: str | dict,
|
1449
1508
|
/,
|
1450
|
-
|
1509
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1451
1510
|
*,
|
1452
1511
|
async_: Literal[True],
|
1453
1512
|
**request_kwargs,
|
1454
1513
|
) -> Coroutine[Any, Any, dict]:
|
1455
1514
|
...
|
1456
|
-
@staticmethod
|
1457
1515
|
def login_qrcode_scan_cancel(
|
1516
|
+
self,
|
1458
1517
|
payload: str | dict,
|
1459
1518
|
/,
|
1460
|
-
|
1519
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1461
1520
|
*,
|
1462
1521
|
async_: Literal[False, True] = False,
|
1463
1522
|
**request_kwargs,
|
1464
1523
|
) -> dict | Coroutine[Any, Any, dict]:
|
1465
1524
|
"""取消扫描二维码,payload 数据取自 `login_qrcode_scan` 接口响应
|
1466
1525
|
|
1467
|
-
GET https://
|
1526
|
+
GET https://qrcodeapi.115.com/api/2.0/cancel.php
|
1468
1527
|
|
1469
1528
|
:payload:
|
1470
1529
|
- key: str
|
1471
1530
|
- uid: str
|
1472
1531
|
- client: int = 0
|
1473
1532
|
"""
|
1474
|
-
api = "
|
1533
|
+
api = complete_api("/api/2.0/cancel.php", base_url=base_url)
|
1475
1534
|
if isinstance(payload, str):
|
1476
1535
|
payload = {"key": payload, "uid": payload, "client": 0}
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1536
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
1537
|
+
|
1538
|
+
@overload
|
1539
|
+
def login_qrcode_scan_confirm(
|
1540
|
+
self,
|
1541
|
+
payload: str | dict,
|
1542
|
+
/,
|
1543
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1544
|
+
*,
|
1545
|
+
async_: Literal[False] = False,
|
1546
|
+
**request_kwargs,
|
1547
|
+
) -> dict:
|
1548
|
+
...
|
1549
|
+
@overload
|
1550
|
+
def login_qrcode_scan_confirm(
|
1551
|
+
self,
|
1552
|
+
payload: str | dict,
|
1553
|
+
/,
|
1554
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1555
|
+
*,
|
1556
|
+
async_: Literal[True],
|
1557
|
+
**request_kwargs,
|
1558
|
+
) -> Coroutine[Any, Any, dict]:
|
1559
|
+
...
|
1560
|
+
def login_qrcode_scan_confirm(
|
1561
|
+
self,
|
1562
|
+
payload: str | dict,
|
1563
|
+
/,
|
1564
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1565
|
+
*,
|
1566
|
+
async_: Literal[False, True] = False,
|
1567
|
+
**request_kwargs,
|
1568
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
1569
|
+
"""确认扫描二维码,payload 数据取自 `login_qrcode_scan` 接口响应
|
1570
|
+
|
1571
|
+
GET https://qrcodeapi.115.com/api/2.0/slogin.php
|
1572
|
+
|
1573
|
+
:payload:
|
1574
|
+
- key: str
|
1575
|
+
- uid: str
|
1576
|
+
- client: int = 0
|
1577
|
+
"""
|
1578
|
+
api = complete_api("/api/2.0/slogin.php", base_url=base_url)
|
1579
|
+
if isinstance(payload, str):
|
1580
|
+
payload = {"key": payload, "uid": payload, "client": 0}
|
1581
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
1482
1582
|
|
1483
1583
|
@overload
|
1484
1584
|
@staticmethod
|
@@ -1486,6 +1586,7 @@ class ClientRequestMixin:
|
|
1486
1586
|
uid: str,
|
1487
1587
|
app: str = "alipaymini",
|
1488
1588
|
request: None | Callable = None,
|
1589
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1489
1590
|
*,
|
1490
1591
|
async_: Literal[False] = False,
|
1491
1592
|
**request_kwargs,
|
@@ -1497,6 +1598,7 @@ class ClientRequestMixin:
|
|
1497
1598
|
uid: str,
|
1498
1599
|
app: str = "alipaymini",
|
1499
1600
|
request: None | Callable = None,
|
1601
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1500
1602
|
*,
|
1501
1603
|
async_: Literal[True],
|
1502
1604
|
**request_kwargs,
|
@@ -1507,13 +1609,14 @@ class ClientRequestMixin:
|
|
1507
1609
|
uid: str,
|
1508
1610
|
app: str = "alipaymini",
|
1509
1611
|
request: None | Callable = None,
|
1612
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1510
1613
|
*,
|
1511
1614
|
async_: Literal[False, True] = False,
|
1512
1615
|
**request_kwargs,
|
1513
1616
|
) -> dict | Coroutine[Any, Any, dict]:
|
1514
1617
|
"""获取扫码登录的结果,包含 cookie
|
1515
1618
|
|
1516
|
-
POST https://
|
1619
|
+
POST https://qrcodeapi.115.com/app/1.0/{app}/1.0/login/qrcode/
|
1517
1620
|
|
1518
1621
|
:param uid: 扫码的 uid
|
1519
1622
|
:param app: 绑定的 app
|
@@ -1525,7 +1628,7 @@ class ClientRequestMixin:
|
|
1525
1628
|
"""
|
1526
1629
|
if app == "desktop":
|
1527
1630
|
app = "web"
|
1528
|
-
api = f"
|
1631
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login/qrcode/", base_url=base_url)
|
1529
1632
|
payload = {"account": uid}
|
1530
1633
|
request_kwargs.setdefault("parse", default_parse)
|
1531
1634
|
if request is None:
|
@@ -1539,6 +1642,7 @@ class ClientRequestMixin:
|
|
1539
1642
|
payload: dict,
|
1540
1643
|
/,
|
1541
1644
|
request: None | Callable = None,
|
1645
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1542
1646
|
*,
|
1543
1647
|
async_: Literal[False] = False,
|
1544
1648
|
**request_kwargs,
|
@@ -1550,6 +1654,7 @@ class ClientRequestMixin:
|
|
1550
1654
|
payload: dict,
|
1551
1655
|
/,
|
1552
1656
|
request: None | Callable = None,
|
1657
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1553
1658
|
*,
|
1554
1659
|
async_: Literal[True],
|
1555
1660
|
**request_kwargs,
|
@@ -1560,6 +1665,7 @@ class ClientRequestMixin:
|
|
1560
1665
|
payload: dict,
|
1561
1666
|
/,
|
1562
1667
|
request: None | Callable = None,
|
1668
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1563
1669
|
*,
|
1564
1670
|
async_: Literal[False, True] = False,
|
1565
1671
|
**request_kwargs,
|
@@ -1577,7 +1683,7 @@ class ClientRequestMixin:
|
|
1577
1683
|
- time: int
|
1578
1684
|
- sign: str
|
1579
1685
|
"""
|
1580
|
-
api = "
|
1686
|
+
api = complete_api("/get/status/", base_url=base_url)
|
1581
1687
|
request_kwargs.setdefault("parse", default_parse)
|
1582
1688
|
if request is None:
|
1583
1689
|
return get_default_request()(url=api, params=payload, async_=async_, **request_kwargs)
|
@@ -1588,6 +1694,8 @@ class ClientRequestMixin:
|
|
1588
1694
|
@staticmethod
|
1589
1695
|
def login_qrcode_token(
|
1590
1696
|
request: None | Callable = None,
|
1697
|
+
app: str = "web",
|
1698
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1591
1699
|
*,
|
1592
1700
|
async_: Literal[False] = False,
|
1593
1701
|
**request_kwargs,
|
@@ -1597,6 +1705,8 @@ class ClientRequestMixin:
|
|
1597
1705
|
@staticmethod
|
1598
1706
|
def login_qrcode_token(
|
1599
1707
|
request: None | Callable = None,
|
1708
|
+
app: str = "web",
|
1709
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1600
1710
|
*,
|
1601
1711
|
async_: Literal[True],
|
1602
1712
|
**request_kwargs,
|
@@ -1605,6 +1715,8 @@ class ClientRequestMixin:
|
|
1605
1715
|
@staticmethod
|
1606
1716
|
def login_qrcode_token(
|
1607
1717
|
request: None | Callable = None,
|
1718
|
+
app: str = "web",
|
1719
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1608
1720
|
*,
|
1609
1721
|
async_: Literal[False, True] = False,
|
1610
1722
|
**request_kwargs,
|
@@ -1613,7 +1725,7 @@ class ClientRequestMixin:
|
|
1613
1725
|
|
1614
1726
|
GET https://qrcodeapi.115.com/api/1.0/web/1.0/token/
|
1615
1727
|
"""
|
1616
|
-
api = "
|
1728
|
+
api = complete_api(f"/api/1.0/{app}/1.0/token/", base_url=base_url)
|
1617
1729
|
request_kwargs.setdefault("parse", default_parse)
|
1618
1730
|
if request is None:
|
1619
1731
|
return get_default_request()(url=api, async_=async_, **request_kwargs)
|
@@ -1626,6 +1738,7 @@ class ClientRequestMixin:
|
|
1626
1738
|
payload: int | str | dict,
|
1627
1739
|
/,
|
1628
1740
|
request: None | Callable = None,
|
1741
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1629
1742
|
*,
|
1630
1743
|
async_: Literal[False] = False,
|
1631
1744
|
**request_kwargs,
|
@@ -1637,6 +1750,7 @@ class ClientRequestMixin:
|
|
1637
1750
|
payload: int | str | dict,
|
1638
1751
|
/,
|
1639
1752
|
request: None | Callable = None,
|
1753
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1640
1754
|
*,
|
1641
1755
|
async_: Literal[True],
|
1642
1756
|
**request_kwargs,
|
@@ -1647,6 +1761,7 @@ class ClientRequestMixin:
|
|
1647
1761
|
payload: int | str | dict,
|
1648
1762
|
/,
|
1649
1763
|
request: None | Callable = None,
|
1764
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1650
1765
|
*,
|
1651
1766
|
async_: Literal[False, True] = False,
|
1652
1767
|
**request_kwargs,
|
@@ -1678,7 +1793,7 @@ class ClientRequestMixin:
|
|
1678
1793
|
|
1679
1794
|
- code_challenge_method: str = <default> 💡 计算 `code_challenge` 的 hash 算法,支持 "md5", "sha1", "sha256"
|
1680
1795
|
"""
|
1681
|
-
api = "
|
1796
|
+
api = complete_api("/open/authDeviceCode", base_url=base_url)
|
1682
1797
|
if isinstance(payload, (int, str)):
|
1683
1798
|
payload = {
|
1684
1799
|
"client_id": payload,
|
@@ -1698,6 +1813,7 @@ class ClientRequestMixin:
|
|
1698
1813
|
/,
|
1699
1814
|
app: None | str = "",
|
1700
1815
|
console_qrcode: bool = True,
|
1816
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1701
1817
|
*,
|
1702
1818
|
async_: Literal[False] = False,
|
1703
1819
|
**request_kwargs,
|
@@ -1710,6 +1826,7 @@ class ClientRequestMixin:
|
|
1710
1826
|
/,
|
1711
1827
|
app: None | str = "",
|
1712
1828
|
console_qrcode: bool = True,
|
1829
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1713
1830
|
*,
|
1714
1831
|
async_: Literal[True],
|
1715
1832
|
**request_kwargs,
|
@@ -1721,6 +1838,7 @@ class ClientRequestMixin:
|
|
1721
1838
|
/,
|
1722
1839
|
app: None | str = "",
|
1723
1840
|
console_qrcode: bool = True,
|
1841
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1724
1842
|
*,
|
1725
1843
|
async_: Literal[False, True] = False,
|
1726
1844
|
**request_kwargs,
|
@@ -1821,6 +1939,7 @@ class ClientRequestMixin:
|
|
1821
1939
|
def gen_step():
|
1822
1940
|
resp = yield cls.login_qrcode_token(
|
1823
1941
|
async_=async_,
|
1942
|
+
base_url=base_url,
|
1824
1943
|
**request_kwargs,
|
1825
1944
|
)
|
1826
1945
|
qrcode_token = resp["data"]
|
@@ -1834,7 +1953,7 @@ class ClientRequestMixin:
|
|
1834
1953
|
qr.add_data(qrcode)
|
1835
1954
|
qr.print_ascii(tty=isatty(1))
|
1836
1955
|
else:
|
1837
|
-
url = "
|
1956
|
+
url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
|
1838
1957
|
if async_:
|
1839
1958
|
yield partial(startfile_async, url)
|
1840
1959
|
else:
|
@@ -1843,6 +1962,7 @@ class ClientRequestMixin:
|
|
1843
1962
|
try:
|
1844
1963
|
resp = yield cls.login_qrcode_scan_status(
|
1845
1964
|
qrcode_token,
|
1965
|
+
base_url=base_url,
|
1846
1966
|
async_=async_,
|
1847
1967
|
**request_kwargs,
|
1848
1968
|
)
|
@@ -1866,6 +1986,7 @@ class ClientRequestMixin:
|
|
1866
1986
|
return cls.login_qrcode_scan_result(
|
1867
1987
|
login_uid,
|
1868
1988
|
app,
|
1989
|
+
base_url=base_url,
|
1869
1990
|
async_=async_,
|
1870
1991
|
**request_kwargs,
|
1871
1992
|
)
|
@@ -1880,6 +2001,7 @@ class ClientRequestMixin:
|
|
1880
2001
|
/,
|
1881
2002
|
app_id: int | str = 100195993,
|
1882
2003
|
console_qrcode: bool = True,
|
2004
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1883
2005
|
*,
|
1884
2006
|
async_: Literal[False] = False,
|
1885
2007
|
**request_kwargs,
|
@@ -1892,6 +2014,7 @@ class ClientRequestMixin:
|
|
1892
2014
|
/,
|
1893
2015
|
app_id: int | str = 100195993,
|
1894
2016
|
console_qrcode: bool = True,
|
2017
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1895
2018
|
*,
|
1896
2019
|
async_: Literal[True],
|
1897
2020
|
**request_kwargs,
|
@@ -1903,6 +2026,7 @@ class ClientRequestMixin:
|
|
1903
2026
|
/,
|
1904
2027
|
app_id: int | str = 100195993,
|
1905
2028
|
console_qrcode: bool = True,
|
2029
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1906
2030
|
*,
|
1907
2031
|
async_: Literal[False, True] = False,
|
1908
2032
|
**request_kwargs,
|
@@ -1918,6 +2042,7 @@ class ClientRequestMixin:
|
|
1918
2042
|
def gen_step():
|
1919
2043
|
resp = yield cls.login_qrcode_token_open(
|
1920
2044
|
app_id,
|
2045
|
+
base_url=base_url,
|
1921
2046
|
async_=async_,
|
1922
2047
|
**request_kwargs,
|
1923
2048
|
)
|
@@ -1932,7 +2057,7 @@ class ClientRequestMixin:
|
|
1932
2057
|
qr.add_data(qrcode)
|
1933
2058
|
qr.print_ascii(tty=isatty(1))
|
1934
2059
|
else:
|
1935
|
-
url = "
|
2060
|
+
url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
|
1936
2061
|
if async_:
|
1937
2062
|
yield partial(startfile_async, url)
|
1938
2063
|
else:
|
@@ -1941,6 +2066,7 @@ class ClientRequestMixin:
|
|
1941
2066
|
try:
|
1942
2067
|
resp = yield cls.login_qrcode_scan_status(
|
1943
2068
|
qrcode_token,
|
2069
|
+
base_url=base_url,
|
1944
2070
|
async_=async_,
|
1945
2071
|
**request_kwargs,
|
1946
2072
|
)
|
@@ -1962,11 +2088,14 @@ class ClientRequestMixin:
|
|
1962
2088
|
raise LoginError(errno.EAUTH, f"qrcode: aborted with {resp!r}")
|
1963
2089
|
return cls.login_qrcode_access_token_open(
|
1964
2090
|
login_uid,
|
2091
|
+
base_url=base_url,
|
1965
2092
|
async_=async_,
|
1966
2093
|
**request_kwargs,
|
1967
2094
|
)
|
1968
2095
|
return run_gen_step(gen_step, async_=async_)
|
1969
2096
|
|
2097
|
+
########## Upload API ##########
|
2098
|
+
|
1970
2099
|
upload_endpoint = "http://oss-cn-shenzhen.aliyuncs.com"
|
1971
2100
|
|
1972
2101
|
def upload_endpoint_url(
|
@@ -4360,6 +4489,10 @@ class P115Client(P115OpenClient):
|
|
4360
4489
|
"""
|
4361
4490
|
self.cookies = None
|
4362
4491
|
|
4492
|
+
@locked_cacheproperty
|
4493
|
+
def request_kwargs(self, /) -> dict:
|
4494
|
+
return {}
|
4495
|
+
|
4363
4496
|
@locked_cacheproperty
|
4364
4497
|
def user_id(self, /) -> int:
|
4365
4498
|
cookie_uid = self.cookies.get("UID")
|
@@ -4658,82 +4791,6 @@ class P115Client(P115OpenClient):
|
|
4658
4791
|
return self
|
4659
4792
|
return run_gen_step(gen_step, async_=async_)
|
4660
4793
|
|
4661
|
-
@overload
|
4662
|
-
def login_qrcode_scan(
|
4663
|
-
self,
|
4664
|
-
payload: str | dict,
|
4665
|
-
/,
|
4666
|
-
async_: Literal[False] = False,
|
4667
|
-
**request_kwargs,
|
4668
|
-
) -> dict:
|
4669
|
-
...
|
4670
|
-
@overload
|
4671
|
-
def login_qrcode_scan(
|
4672
|
-
self,
|
4673
|
-
payload: str | dict,
|
4674
|
-
/,
|
4675
|
-
async_: Literal[True],
|
4676
|
-
**request_kwargs,
|
4677
|
-
) -> Coroutine[Any, Any, dict]:
|
4678
|
-
...
|
4679
|
-
def login_qrcode_scan(
|
4680
|
-
self,
|
4681
|
-
payload: str | dict,
|
4682
|
-
/,
|
4683
|
-
async_: Literal[False, True] = False,
|
4684
|
-
**request_kwargs,
|
4685
|
-
) -> dict | Coroutine[Any, Any, dict]:
|
4686
|
-
"""扫描二维码,payload 数据取自 `login_qrcode_token` 接口响应
|
4687
|
-
|
4688
|
-
GET https://qrcodeapi.115.com/api/2.0/prompt.php
|
4689
|
-
|
4690
|
-
:payload:
|
4691
|
-
- uid: str
|
4692
|
-
"""
|
4693
|
-
api = "https://qrcodeapi.115.com/api/2.0/prompt.php"
|
4694
|
-
if isinstance(payload, str):
|
4695
|
-
payload = {"uid": payload}
|
4696
|
-
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
4697
|
-
|
4698
|
-
@overload
|
4699
|
-
def login_qrcode_scan_confirm(
|
4700
|
-
self,
|
4701
|
-
payload: str | dict,
|
4702
|
-
/,
|
4703
|
-
async_: Literal[False] = False,
|
4704
|
-
**request_kwargs,
|
4705
|
-
) -> dict:
|
4706
|
-
...
|
4707
|
-
@overload
|
4708
|
-
def login_qrcode_scan_confirm(
|
4709
|
-
self,
|
4710
|
-
payload: str | dict,
|
4711
|
-
/,
|
4712
|
-
async_: Literal[True],
|
4713
|
-
**request_kwargs,
|
4714
|
-
) -> Coroutine[Any, Any, dict]:
|
4715
|
-
...
|
4716
|
-
def login_qrcode_scan_confirm(
|
4717
|
-
self,
|
4718
|
-
payload: str | dict,
|
4719
|
-
/,
|
4720
|
-
async_: Literal[False, True] = False,
|
4721
|
-
**request_kwargs,
|
4722
|
-
) -> dict | Coroutine[Any, Any, dict]:
|
4723
|
-
"""确认扫描二维码,payload 数据取自 `login_qrcode_scan` 接口响应
|
4724
|
-
|
4725
|
-
GET https://hnqrcodeapi.115.com/api/2.0/slogin.php
|
4726
|
-
|
4727
|
-
:payload:
|
4728
|
-
- key: str
|
4729
|
-
- uid: str
|
4730
|
-
- client: int = 0
|
4731
|
-
"""
|
4732
|
-
api = "https://hnqrcodeapi.115.com/api/2.0/slogin.php"
|
4733
|
-
if isinstance(payload, str):
|
4734
|
-
payload = {"key": payload, "uid": payload, "client": 0}
|
4735
|
-
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
4736
|
-
|
4737
4794
|
@overload
|
4738
4795
|
def login_with_app(
|
4739
4796
|
self,
|
@@ -5367,7 +5424,7 @@ class P115Client(P115OpenClient):
|
|
5367
5424
|
return None
|
5368
5425
|
return self.logout_by_ssoent(ssoent, async_=async_, **request_kwargs)
|
5369
5426
|
|
5370
|
-
def
|
5427
|
+
def _request(
|
5371
5428
|
self,
|
5372
5429
|
/,
|
5373
5430
|
url: str,
|
@@ -5609,6 +5666,90 @@ class P115Client(P115OpenClient):
|
|
5609
5666
|
return resp
|
5610
5667
|
return run_gen_step(gen_step, async_=async_)
|
5611
5668
|
|
5669
|
+
def request(
|
5670
|
+
self,
|
5671
|
+
/,
|
5672
|
+
url: str,
|
5673
|
+
method: str = "GET",
|
5674
|
+
params = None,
|
5675
|
+
data = None,
|
5676
|
+
*,
|
5677
|
+
async_: Literal[False, True] = False,
|
5678
|
+
**request_kwargs,
|
5679
|
+
):
|
5680
|
+
"""帮助函数:可执行同步和异步的网络请求
|
5681
|
+
|
5682
|
+
:param url: HTTP 的请求链接
|
5683
|
+
:param method: HTTP 的请求方法
|
5684
|
+
:param params: 查询参数
|
5685
|
+
:param check: 是否用 `check_response` 函数检查返回值
|
5686
|
+
:param ecdh_encrypt: 使用 ecdh 算法进行加密(返回值也要解密)
|
5687
|
+
:param fetch_cert_headers: 调用以获取认证信息头
|
5688
|
+
:param revert_cert_headers: 调用以退还认证信息头
|
5689
|
+
:param async_: 说明 `request` 是同步调用还是异步调用
|
5690
|
+
:param request: HTTP 请求调用,如果为 None,则默认用 httpx 执行请求
|
5691
|
+
如果传入调用,则必须至少能接受以下几个关键词参数:
|
5692
|
+
|
5693
|
+
- url: HTTP 的请求链接
|
5694
|
+
- method: HTTP 的请求方法
|
5695
|
+
- headers: HTTP 的请求头
|
5696
|
+
- data: HTTP 的请求体
|
5697
|
+
- parse: 解析 HTTP 响应的方法,默认会构建一个 Callable,会把响应的字节数据视为 JSON 进行反序列化解析
|
5698
|
+
|
5699
|
+
- 如果为 None,则直接把响应对象返回
|
5700
|
+
- 如果为 ...(Ellipsis),则把响应对象关闭后将其返回
|
5701
|
+
- 如果为 True,则根据响应头来确定把响应得到的字节数据解析成何种格式(反序列化),请求也会被自动关闭
|
5702
|
+
- 如果为 False,则直接返回响应得到的字节数据,请求也会被自动关闭
|
5703
|
+
- 如果为 Callable,则使用此调用来解析数据,接受 1-2 个位置参数,并把解析结果返回给 `request` 的调用者,请求也会被自动关闭
|
5704
|
+
- 如果只接受 1 个位置参数,则把响应对象传给它
|
5705
|
+
- 如果能接受 2 个位置参数,则把响应对象和响应得到的字节数据(响应体)传给它
|
5706
|
+
|
5707
|
+
:param request_kwargs: 其余的请求参数,会被传给 `request`
|
5708
|
+
|
5709
|
+
:return: 直接返回 `request` 执行请求后的返回值
|
5710
|
+
|
5711
|
+
.. note::
|
5712
|
+
`request` 可以由不同的请求库来提供,下面是封装了一些模块
|
5713
|
+
|
5714
|
+
1. `httpx_request <https://pypi.org/project/httpx_request/>`_,由 `httpx <https://pypi.org/project/httpx/>`_ 封装,支持同步和异步调用,本模块默认用的就是这个封装
|
5715
|
+
|
5716
|
+
.. code:: python
|
5717
|
+
|
5718
|
+
from httpx_request import request
|
5719
|
+
|
5720
|
+
2. `python-urlopen <https://pypi.org/project/python-urlopen/>`_,由 `urllib.request.urlopen <https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen>`_ 封装,支持同步调用,性能相对最差
|
5721
|
+
|
5722
|
+
.. code:: python
|
5723
|
+
|
5724
|
+
from urlopen import request
|
5725
|
+
|
5726
|
+
3. `urllib3_request <https://pypi.org/project/urllib3_request/>`_,由 `urllib3 <https://pypi.org/project/urllib3/>`_ 封装,支持同步调用,性能相对较好,推荐使用
|
5727
|
+
|
5728
|
+
.. code:: python
|
5729
|
+
|
5730
|
+
from urllib3_request import request
|
5731
|
+
|
5732
|
+
4. `requests_request <https://pypi.org/project/requests_request/>`_,由 `requests <https://pypi.org/project/requests/>`_ 封装,支持同步调用
|
5733
|
+
|
5734
|
+
.. code:: python
|
5735
|
+
|
5736
|
+
from requests_request import request
|
5737
|
+
|
5738
|
+
5. `aiohttp_client_request <https://pypi.org/project/aiohttp_client_request/>`_,由 `aiohttp <https://pypi.org/project/aiohttp/>`_ 封装,支持异步调用,异步并发能力最强,推荐使用
|
5739
|
+
|
5740
|
+
.. code:: python
|
5741
|
+
|
5742
|
+
from aiohttp_client_request import request
|
5743
|
+
|
5744
|
+
6. `blacksheep_client_request <https://pypi.org/project/blacksheep_client_request/>`_,由 `blacksheep <https://pypi.org/project/blacksheep/>`_ 封装,支持异步调用
|
5745
|
+
|
5746
|
+
.. code:: python
|
5747
|
+
|
5748
|
+
from blacksheep_client_request import request
|
5749
|
+
"""
|
5750
|
+
kwargs = {**self.request_kwargs, **request_kwargs}
|
5751
|
+
return self._request(url, method, params, data, async_=async_, **kwargs)
|
5752
|
+
|
5612
5753
|
########## Activity API ##########
|
5613
5754
|
|
5614
5755
|
@overload
|
@@ -14960,10 +15101,143 @@ class P115Client(P115OpenClient):
|
|
14960
15101
|
return device["icon"]
|
14961
15102
|
return run_gen_step(gen_step, async_=async_)
|
14962
15103
|
|
15104
|
+
@overload
|
15105
|
+
def login_open_auth_detail(
|
15106
|
+
self,
|
15107
|
+
payload: int | str | dict,
|
15108
|
+
/,
|
15109
|
+
app: str = "web",
|
15110
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15111
|
+
*,
|
15112
|
+
async_: Literal[False] = False,
|
15113
|
+
**request_kwargs,
|
15114
|
+
) -> dict:
|
15115
|
+
...
|
15116
|
+
@overload
|
15117
|
+
def login_open_auth_detail(
|
15118
|
+
self,
|
15119
|
+
payload: int | str | dict,
|
15120
|
+
/,
|
15121
|
+
app: str = "web",
|
15122
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15123
|
+
*,
|
15124
|
+
async_: Literal[True],
|
15125
|
+
**request_kwargs,
|
15126
|
+
) -> Coroutine[Any, Any, dict]:
|
15127
|
+
...
|
15128
|
+
def login_open_auth_detail(
|
15129
|
+
self,
|
15130
|
+
payload: int | str | dict,
|
15131
|
+
/,
|
15132
|
+
app: str = "web",
|
15133
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15134
|
+
*,
|
15135
|
+
async_: Literal[False, True] = False,
|
15136
|
+
**request_kwargs,
|
15137
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
15138
|
+
"""获取某个开放应用的授权信息
|
15139
|
+
|
15140
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/user/getAppAuthDetail
|
15141
|
+
|
15142
|
+
:payload:
|
15143
|
+
- auth_id: int | str 💡 授权 id
|
15144
|
+
"""
|
15145
|
+
api = complete_api(f"/app/1.0/{app}/1.0/user/getAppAuthDetail", base_url=base_url)
|
15146
|
+
if isinstance(payload, (int, str)):
|
15147
|
+
payload = {"auth_id": payload}
|
15148
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
15149
|
+
|
15150
|
+
@overload
|
15151
|
+
def login_open_auth_list(
|
15152
|
+
self,
|
15153
|
+
/,
|
15154
|
+
app: str = "web",
|
15155
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15156
|
+
*,
|
15157
|
+
async_: Literal[False] = False,
|
15158
|
+
**request_kwargs,
|
15159
|
+
) -> dict:
|
15160
|
+
...
|
15161
|
+
@overload
|
15162
|
+
def login_open_auth_list(
|
15163
|
+
self,
|
15164
|
+
/,
|
15165
|
+
app: str = "web",
|
15166
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15167
|
+
*,
|
15168
|
+
async_: Literal[True],
|
15169
|
+
**request_kwargs,
|
15170
|
+
) -> Coroutine[Any, Any, dict]:
|
15171
|
+
...
|
15172
|
+
def login_open_auth_list(
|
15173
|
+
self,
|
15174
|
+
/,
|
15175
|
+
app: str = "web",
|
15176
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15177
|
+
*,
|
15178
|
+
async_: Literal[False, True] = False,
|
15179
|
+
**request_kwargs,
|
15180
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
15181
|
+
"""获取所有授权的开放应用的列表
|
15182
|
+
|
15183
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/user/getAppAuthList
|
15184
|
+
"""
|
15185
|
+
api = complete_api(f"/app/1.0/{app}/1.0/user/getAppAuthList", base_url=base_url)
|
15186
|
+
return self.request(url=api, async_=async_, **request_kwargs)
|
15187
|
+
|
15188
|
+
@overload
|
15189
|
+
def login_open_deauth(
|
15190
|
+
self,
|
15191
|
+
payload: int | str | dict,
|
15192
|
+
/,
|
15193
|
+
app: str = "web",
|
15194
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15195
|
+
*,
|
15196
|
+
async_: Literal[False] = False,
|
15197
|
+
**request_kwargs,
|
15198
|
+
) -> dict:
|
15199
|
+
...
|
15200
|
+
@overload
|
15201
|
+
def login_open_deauth(
|
15202
|
+
self,
|
15203
|
+
payload: int | str | dict,
|
15204
|
+
/,
|
15205
|
+
app: str = "web",
|
15206
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15207
|
+
*,
|
15208
|
+
async_: Literal[True],
|
15209
|
+
**request_kwargs,
|
15210
|
+
) -> Coroutine[Any, Any, dict]:
|
15211
|
+
...
|
15212
|
+
def login_open_deauth(
|
15213
|
+
self,
|
15214
|
+
payload: int | str | dict,
|
15215
|
+
/,
|
15216
|
+
app: str = "web",
|
15217
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15218
|
+
*,
|
15219
|
+
async_: Literal[False, True] = False,
|
15220
|
+
**request_kwargs,
|
15221
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
15222
|
+
"""取消某个开放应用的授权
|
15223
|
+
|
15224
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/user/deauthApp
|
15225
|
+
|
15226
|
+
:payload:
|
15227
|
+
- auth_id: int | str 💡 授权 id
|
15228
|
+
"""
|
15229
|
+
api = complete_api(f"/app/1.0/{app}/1.0/user/deauthApp", base_url=base_url)
|
15230
|
+
if isinstance(payload, (int, str)):
|
15231
|
+
payload = {"auth_id": payload}
|
15232
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
15233
|
+
|
14963
15234
|
@overload
|
14964
15235
|
def login_check_sso(
|
14965
15236
|
self,
|
14966
15237
|
/,
|
15238
|
+
app: str = "web",
|
15239
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15240
|
+
*,
|
14967
15241
|
async_: Literal[False] = False,
|
14968
15242
|
**request_kwargs,
|
14969
15243
|
) -> dict:
|
@@ -14972,6 +15246,9 @@ class P115Client(P115OpenClient):
|
|
14972
15246
|
def login_check_sso(
|
14973
15247
|
self,
|
14974
15248
|
/,
|
15249
|
+
app: str = "web",
|
15250
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15251
|
+
*,
|
14975
15252
|
async_: Literal[True],
|
14976
15253
|
**request_kwargs,
|
14977
15254
|
) -> Coroutine[Any, Any, dict]:
|
@@ -14979,14 +15256,17 @@ class P115Client(P115OpenClient):
|
|
14979
15256
|
def login_check_sso(
|
14980
15257
|
self,
|
14981
15258
|
/,
|
15259
|
+
app: str = "web",
|
15260
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15261
|
+
*,
|
14982
15262
|
async_: Literal[False, True] = False,
|
14983
15263
|
**request_kwargs,
|
14984
15264
|
) -> dict | Coroutine[Any, Any, dict]:
|
14985
15265
|
"""检查当前 cookies 的登录状态信息,并且自最近一次登录的 60 秒后,使当前设备下除最近一次登录外的所有 cookies 失效
|
14986
15266
|
|
14987
|
-
GET https://
|
15267
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/check/sso
|
14988
15268
|
"""
|
14989
|
-
api = "
|
15269
|
+
api = complete_api(f"/app/1.0/{app}/1.0/check/sso", base_url=base_url)
|
14990
15270
|
return self.request(url=api, async_=async_, **request_kwargs)
|
14991
15271
|
|
14992
15272
|
@overload
|
@@ -15025,6 +15305,9 @@ class P115Client(P115OpenClient):
|
|
15025
15305
|
def login_devices(
|
15026
15306
|
self,
|
15027
15307
|
/,
|
15308
|
+
app: str = "web",
|
15309
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15310
|
+
*,
|
15028
15311
|
async_: Literal[False] = False,
|
15029
15312
|
**request_kwargs,
|
15030
15313
|
) -> dict:
|
@@ -15033,6 +15316,9 @@ class P115Client(P115OpenClient):
|
|
15033
15316
|
def login_devices(
|
15034
15317
|
self,
|
15035
15318
|
/,
|
15319
|
+
app: str = "web",
|
15320
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15321
|
+
*,
|
15036
15322
|
async_: Literal[True],
|
15037
15323
|
**request_kwargs,
|
15038
15324
|
) -> Coroutine[Any, Any, dict]:
|
@@ -15040,14 +15326,17 @@ class P115Client(P115OpenClient):
|
|
15040
15326
|
def login_devices(
|
15041
15327
|
self,
|
15042
15328
|
/,
|
15329
|
+
app: str = "web",
|
15330
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15331
|
+
*,
|
15043
15332
|
async_: Literal[False, True] = False,
|
15044
15333
|
**request_kwargs,
|
15045
15334
|
) -> dict | Coroutine[Any, Any, dict]:
|
15046
15335
|
"""获取所有的已登录设备的信息,不过当前的 cookies 必须是登录状态(未退出或未失效)
|
15047
15336
|
|
15048
|
-
GET https://
|
15337
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/login_devices
|
15049
15338
|
"""
|
15050
|
-
api = "
|
15339
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login_log/login_devices", base_url=base_url)
|
15051
15340
|
return self.request(url=api, async_=async_, **request_kwargs)
|
15052
15341
|
|
15053
15342
|
@overload
|
@@ -15093,6 +15382,8 @@ class P115Client(P115OpenClient):
|
|
15093
15382
|
self,
|
15094
15383
|
payload: dict = {},
|
15095
15384
|
/,
|
15385
|
+
app: str = "web",
|
15386
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15096
15387
|
*,
|
15097
15388
|
async_: Literal[False] = False,
|
15098
15389
|
**request_kwargs,
|
@@ -15103,6 +15394,8 @@ class P115Client(P115OpenClient):
|
|
15103
15394
|
self,
|
15104
15395
|
payload: dict = {},
|
15105
15396
|
/,
|
15397
|
+
app: str = "web",
|
15398
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15106
15399
|
*,
|
15107
15400
|
async_: Literal[True],
|
15108
15401
|
**request_kwargs,
|
@@ -15112,19 +15405,21 @@ class P115Client(P115OpenClient):
|
|
15112
15405
|
self,
|
15113
15406
|
payload: dict = {},
|
15114
15407
|
/,
|
15408
|
+
app: str = "web",
|
15409
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15115
15410
|
*,
|
15116
15411
|
async_: Literal[False, True] = False,
|
15117
15412
|
**request_kwargs,
|
15118
15413
|
) -> dict | Coroutine[Any, Any, dict]:
|
15119
15414
|
"""获取登录信息日志列表
|
15120
15415
|
|
15121
|
-
GET https://
|
15416
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/log
|
15122
15417
|
|
15123
15418
|
:payload:
|
15124
15419
|
- start: int = 0
|
15125
15420
|
- limit: int = 100
|
15126
15421
|
"""
|
15127
|
-
api = "
|
15422
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login_log/log", base_url=base_url)
|
15128
15423
|
payload = {"start": 0, "limit": 100, **payload}
|
15129
15424
|
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
15130
15425
|
|
@@ -15133,6 +15428,7 @@ class P115Client(P115OpenClient):
|
|
15133
15428
|
self,
|
15134
15429
|
/,
|
15135
15430
|
app: str = "web",
|
15431
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15136
15432
|
*,
|
15137
15433
|
async_: Literal[False] = False,
|
15138
15434
|
**request_kwargs,
|
@@ -15143,6 +15439,7 @@ class P115Client(P115OpenClient):
|
|
15143
15439
|
self,
|
15144
15440
|
/,
|
15145
15441
|
app: str = "web",
|
15442
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15146
15443
|
*,
|
15147
15444
|
async_: Literal[True],
|
15148
15445
|
**request_kwargs,
|
@@ -15152,15 +15449,16 @@ class P115Client(P115OpenClient):
|
|
15152
15449
|
self,
|
15153
15450
|
/,
|
15154
15451
|
app: str = "web",
|
15452
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15155
15453
|
*,
|
15156
15454
|
async_: Literal[False, True] = False,
|
15157
15455
|
**request_kwargs,
|
15158
15456
|
) -> dict | Coroutine[Any, Any, dict]:
|
15159
15457
|
"""当前登录的设备总数和最近登录的设备
|
15160
15458
|
|
15161
|
-
GET https://
|
15459
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/login_online
|
15162
15460
|
"""
|
15163
|
-
api = f"
|
15461
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login_log/login_online", base_url=base_url)
|
15164
15462
|
return self.request(url=api, async_=async_, **request_kwargs)
|
15165
15463
|
|
15166
15464
|
@overload
|
@@ -15222,6 +15520,7 @@ class P115Client(P115OpenClient):
|
|
15222
15520
|
/,
|
15223
15521
|
app: None | str = None,
|
15224
15522
|
request: None | Callable = None,
|
15523
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15225
15524
|
*,
|
15226
15525
|
async_: Literal[False] = False,
|
15227
15526
|
**request_kwargs,
|
@@ -15233,6 +15532,7 @@ class P115Client(P115OpenClient):
|
|
15233
15532
|
/,
|
15234
15533
|
app: None | str = None,
|
15235
15534
|
request: None | Callable = None,
|
15535
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15236
15536
|
*,
|
15237
15537
|
async_: Literal[True],
|
15238
15538
|
**request_kwargs,
|
@@ -15243,13 +15543,14 @@ class P115Client(P115OpenClient):
|
|
15243
15543
|
/,
|
15244
15544
|
app: None | str = None,
|
15245
15545
|
request: None | Callable = None,
|
15546
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15246
15547
|
*,
|
15247
15548
|
async_: Literal[False, True] = False,
|
15248
15549
|
**request_kwargs,
|
15249
15550
|
) -> None | Coroutine[Any, Any, None]:
|
15250
15551
|
"""退出登录状态(可以把某个客户端下线,所有已登录设备可从 `login_devices` 获取)
|
15251
15552
|
|
15252
|
-
GET https://
|
15553
|
+
GET https://qrcodeapi.115.com/app/1.0/{app}/1.0/logout/logout
|
15253
15554
|
|
15254
15555
|
:param app: 退出登录的 app
|
15255
15556
|
|
@@ -15315,7 +15616,7 @@ class P115Client(P115OpenClient):
|
|
15315
15616
|
app = yield self.login_app(async_=async_)
|
15316
15617
|
if app == "desktop":
|
15317
15618
|
app = "web"
|
15318
|
-
api = f"
|
15619
|
+
api = complete_api(f"/app/1.0/{app}/1.0/logout/logout", base_url=base_url)
|
15319
15620
|
request_kwargs["headers"] = {**(request_kwargs.get("headers") or {}), "Cookie": self.cookies_str}
|
15320
15621
|
request_kwargs.setdefault("parse", ...)
|
15321
15622
|
if request is None:
|
@@ -15329,6 +15630,8 @@ class P115Client(P115OpenClient):
|
|
15329
15630
|
self,
|
15330
15631
|
payload: None | str | dict = None,
|
15331
15632
|
/,
|
15633
|
+
app: str = "web",
|
15634
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15332
15635
|
*,
|
15333
15636
|
async_: Literal[False] = False,
|
15334
15637
|
**request_kwargs,
|
@@ -15339,6 +15642,8 @@ class P115Client(P115OpenClient):
|
|
15339
15642
|
self,
|
15340
15643
|
payload: None | str | dict = None,
|
15341
15644
|
/,
|
15645
|
+
app: str = "web",
|
15646
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15342
15647
|
*,
|
15343
15648
|
async_: Literal[True],
|
15344
15649
|
**request_kwargs,
|
@@ -15348,13 +15653,15 @@ class P115Client(P115OpenClient):
|
|
15348
15653
|
self,
|
15349
15654
|
payload: None | str | dict = None,
|
15350
15655
|
/,
|
15656
|
+
app: str = "web",
|
15657
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15351
15658
|
*,
|
15352
15659
|
async_: Literal[False, True] = False,
|
15353
15660
|
**request_kwargs,
|
15354
15661
|
) -> dict | Coroutine[Any, Any, dict]:
|
15355
15662
|
"""退出登录状态(可以把某个客户端下线,所有已登录设备可从 `login_devices` 获取)
|
15356
15663
|
|
15357
|
-
POST https://
|
15664
|
+
POST https://qrcodeapi.115.com/app/1.0/web/1.0/logout/mange
|
15358
15665
|
|
15359
15666
|
:payload:
|
15360
15667
|
- ssoent: str
|
@@ -15415,7 +15722,7 @@ class P115Client(P115OpenClient):
|
|
15415
15722
|
| 24 | S1 | harmony | 115(Harmony端) |
|
15416
15723
|
+-------+----------+------------+-------------------------+
|
15417
15724
|
"""
|
15418
|
-
api = "
|
15725
|
+
api = complete_api(f"/app/1.0/{app}/1.0/logout/mange", base_url=base_url)
|
15419
15726
|
if payload is None:
|
15420
15727
|
payload = {"ssoent": self.login_ssoent or ""}
|
15421
15728
|
elif isinstance(payload, str):
|
@@ -3,8 +3,9 @@
|
|
3
3
|
|
4
4
|
__all__ = [
|
5
5
|
"P115Warning", "P115OSError", "AuthenticationError", "BusyOSError", "DataError",
|
6
|
-
"LoginError", "MultipartUploadAbort", "
|
7
|
-
"
|
6
|
+
"LoginError", "MultipartUploadAbort", "OpenAppAuthLimitExceeded",
|
7
|
+
"NotSupportedError", "OperationalError", "P115FileExistsError",
|
8
|
+
"P115FileNotFoundError", "P115IsADirectoryError",
|
8
9
|
"P115NotADirectoryError", "P115PermissionError", "P115TimeoutError",
|
9
10
|
]
|
10
11
|
|
@@ -81,6 +82,11 @@ class MultipartUploadAbort(P115OSError):
|
|
81
82
|
return f"{type(self).__module__}.{type(self).__qualname__}({self.ticket})"
|
82
83
|
|
83
84
|
|
85
|
+
class OpenAppAuthLimitExceeded(AuthenticationError):
|
86
|
+
"""当授权应用数达到上限时抛出
|
87
|
+
"""
|
88
|
+
|
89
|
+
|
84
90
|
class NotSupportedError(P115OSError):
|
85
91
|
"""当调用不存在的接口或者接口不支持此操作时抛出
|
86
92
|
"""
|
@@ -276,9 +276,6 @@ def get_file_count(
|
|
276
276
|
) -> int | Coroutine[Any, Any, int]:
|
277
277
|
"""获取文件总数
|
278
278
|
|
279
|
-
.. caution::
|
280
|
-
我通过一些经验,搭配了多个接口的占比和参数分布,可能不够合理,以后会根据实际情况调整
|
281
|
-
|
282
279
|
:param client: 115 客户端或 cookies
|
283
280
|
:param cid: 目录 id
|
284
281
|
:param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
|
@@ -408,9 +405,6 @@ def get_ancestors(
|
|
408
405
|
) -> list[dict] | Coroutine[Any, Any, list[dict]]:
|
409
406
|
"""获取某个节点对应的祖先节点列表(只有 id、parent_id 和 name 的信息)
|
410
407
|
|
411
|
-
.. caution::
|
412
|
-
我通过一些经验,搭配了多个接口的占比和参数分布,可能不够合理,以后会根据实际情况调整
|
413
|
-
|
414
408
|
:param client: 115 客户端或 cookies
|
415
409
|
:param attr: 待查询节点 `id` 或信息(必须有 `id`,可选有 `parent_id`)
|
416
410
|
:param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "p115client"
|
3
|
-
version = "0.0.5.10.
|
3
|
+
version = "0.0.5.10.8"
|
4
4
|
description = "Python 115 webdisk client."
|
5
5
|
authors = ["ChenyangGao <wosiwujm@gmail.com>"]
|
6
6
|
license = "MIT"
|
@@ -31,8 +31,8 @@ python = "^3.12"
|
|
31
31
|
aiofile = "*"
|
32
32
|
ed2k = ">=0.0.2.1"
|
33
33
|
http_response = ">=0.0.2.2"
|
34
|
-
httpx = "
|
35
|
-
httpx_request = ">=0.1.
|
34
|
+
httpx = ">=0.28"
|
35
|
+
httpx_request = ">=0.1.4"
|
36
36
|
iter_collect = ">=0.0.5.1"
|
37
37
|
multidict = "*"
|
38
38
|
orjson = "*"
|
@@ -195,7 +195,7 @@ class MyCustom115Client(P115Client):
|
|
195
195
|
|
196
196
|
### 3. 检查响应
|
197
197
|
|
198
|
-
接口被调用后,如果返回的是 dict 类型的数据(说明原本是 JSON),则可以用 `p115client.check_response` 执行检查。首先会查看其中名为 "state" 的键的对应值,如果为 True、1 或不存在,则原样返回被检查的数据;否则,"state" 的对应值大概是 False 或 0,说明有问题出现,会根据实际情况抛出一个异常,但都是 `
|
198
|
+
接口被调用后,如果返回的是 dict 类型的数据(说明原本是 JSON),则可以用 `p115client.check_response` 执行检查。首先会查看其中名为 "state" 的键的对应值,如果为 True、1 或不存在,则原样返回被检查的数据;否则,"state" 的对应值大概是 False 或 0,说明有问题出现,会根据实际情况抛出一个异常,但都是 `p115client.P115OSError` 的实例。
|
199
199
|
|
200
200
|
```python
|
201
201
|
from p115client import check_response
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|