p115client 0.0.5.10.6__tar.gz → 0.0.5.10.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.
Files changed (25) hide show
  1. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/PKG-INFO +2 -2
  2. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/client.py +315 -114
  3. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/const.py +1 -1
  4. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/exception.py +8 -2
  5. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/iterdir.py +0 -6
  6. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/pyproject.toml +1 -1
  7. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/readme.md +1 -1
  8. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/LICENSE +0 -0
  9. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/__init__.py +0 -0
  10. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/_upload.py +0 -0
  11. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/py.typed +0 -0
  12. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/__init__.py +0 -0
  13. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/attr.py +0 -0
  14. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/download.py +0 -0
  15. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/edit.py +0 -0
  16. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/export_dir.py +0 -0
  17. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/fs_files.py +0 -0
  18. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/history.py +0 -0
  19. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/life.py +0 -0
  20. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/pool.py +0 -0
  21. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/request.py +0 -0
  22. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/upload.py +0 -0
  23. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/util.py +0 -0
  24. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/p115client/tool/xys.py +0 -0
  25. {p115client-0.0.5.10.6 → p115client-0.0.5.10.7}/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.6
3
+ Version: 0.0.5.10.7
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -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,说明有问题出现,会根据实际情况抛出一个异常,但都是 `OSError` 的实例,其中大部分还是 `p115client.P115OSError` 的实例。
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, NotSupportedError,
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 OperationalError(errno.EINVAL, resp)
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 = "https://qrcodeapi.115.com/api/1.0/web/1.0/qrcode"
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 = "https://qrcodeapi.115.com/open/deviceCodeToToken"
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 = "https://qrcodeapi.115.com/open/refreshToken"
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
- @staticmethod
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
- request: None | Callable = None,
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
- request: None | Callable = None,
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
- request: None | Callable = None,
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://hnqrcodeapi.115.com/api/2.0/cancel.php
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 = "https://hnqrcodeapi.115.com/api/2.0/cancel.php"
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
- request_kwargs.setdefault("parse", default_parse)
1478
- if request is None:
1479
- return get_default_request()(url=api, params=payload, async_=async_, **request_kwargs)
1480
- else:
1481
- return request(url=api, params=payload, **request_kwargs)
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://passportapi.115.com/app/1.0/{app}/1.0/login/qrcode/
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"http://passportapi.115.com/app/1.0/{app}/1.0/login/qrcode/"
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 = "https://qrcodeapi.115.com/get/status/"
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 = "https://qrcodeapi.115.com/api/1.0/web/1.0/token/"
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 = "https://qrcodeapi.115.com/open/authDeviceCode"
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 = "https://qrcodeapi.115.com/api/1.0/web/1.0/qrcode?uid=" + login_uid
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 = "https://qrcodeapi.115.com/api/1.0/web/1.0/qrcode?uid=" + login_uid
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(
@@ -4658,82 +4787,6 @@ class P115Client(P115OpenClient):
4658
4787
  return self
4659
4788
  return run_gen_step(gen_step, async_=async_)
4660
4789
 
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
4790
  @overload
4738
4791
  def login_with_app(
4739
4792
  self,
@@ -14960,10 +15013,125 @@ class P115Client(P115OpenClient):
14960
15013
  return device["icon"]
14961
15014
  return run_gen_step(gen_step, async_=async_)
14962
15015
 
15016
+ @overload
15017
+ def login_open_auth_detail(
15018
+ self,
15019
+ payload: int | str | dict,
15020
+ /,
15021
+ app: str = "web",
15022
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15023
+ *,
15024
+ async_: Literal[False] = False,
15025
+ **request_kwargs,
15026
+ ) -> dict:
15027
+ ...
15028
+ @overload
15029
+ def login_open_auth_detail(
15030
+ self,
15031
+ payload: int | str | dict,
15032
+ /,
15033
+ app: str = "web",
15034
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15035
+ *,
15036
+ async_: Literal[True],
15037
+ **request_kwargs,
15038
+ ) -> Coroutine[Any, Any, dict]:
15039
+ ...
15040
+ def login_open_auth_detail(
15041
+ self,
15042
+ payload: int | str | dict,
15043
+ /,
15044
+ app: str = "web",
15045
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15046
+ *,
15047
+ async_: Literal[False, True] = False,
15048
+ **request_kwargs,
15049
+ ) -> dict | Coroutine[Any, Any, dict]:
15050
+ api = complete_api(f"/app/1.0/{app}/1.0/user/getAppAuthDetail", base_url=base_url)
15051
+ if isinstance(payload, (int, str)):
15052
+ payload = {"auth_id": payload}
15053
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
15054
+
15055
+ @overload
15056
+ def login_open_auth_list(
15057
+ self,
15058
+ /,
15059
+ app: str = "web",
15060
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15061
+ *,
15062
+ async_: Literal[False] = False,
15063
+ **request_kwargs,
15064
+ ) -> dict:
15065
+ ...
15066
+ @overload
15067
+ def login_open_auth_list(
15068
+ self,
15069
+ /,
15070
+ app: str = "web",
15071
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15072
+ *,
15073
+ async_: Literal[True],
15074
+ **request_kwargs,
15075
+ ) -> Coroutine[Any, Any, dict]:
15076
+ ...
15077
+ def login_open_auth_list(
15078
+ self,
15079
+ /,
15080
+ app: str = "web",
15081
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15082
+ *,
15083
+ async_: Literal[False, True] = False,
15084
+ **request_kwargs,
15085
+ ) -> dict | Coroutine[Any, Any, dict]:
15086
+ api = complete_api(f"/app/1.0/{app}/1.0/user/getAppAuthList", base_url=base_url)
15087
+ return self.request(url=api, async_=async_, **request_kwargs)
15088
+
15089
+ @overload
15090
+ def login_open_deauth(
15091
+ self,
15092
+ payload: int | str | dict,
15093
+ /,
15094
+ app: str = "web",
15095
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15096
+ *,
15097
+ async_: Literal[False] = False,
15098
+ **request_kwargs,
15099
+ ) -> dict:
15100
+ ...
15101
+ @overload
15102
+ def login_open_deauth(
15103
+ self,
15104
+ payload: int | str | dict,
15105
+ /,
15106
+ app: str = "web",
15107
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15108
+ *,
15109
+ async_: Literal[True],
15110
+ **request_kwargs,
15111
+ ) -> Coroutine[Any, Any, dict]:
15112
+ ...
15113
+ def login_open_deauth(
15114
+ self,
15115
+ payload: int | str | dict,
15116
+ /,
15117
+ app: str = "web",
15118
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15119
+ *,
15120
+ async_: Literal[False, True] = False,
15121
+ **request_kwargs,
15122
+ ) -> dict | Coroutine[Any, Any, dict]:
15123
+ api = complete_api(f"/app/1.0/{app}/1.0/user/deauthApp", base_url=base_url)
15124
+ if isinstance(payload, (int, str)):
15125
+ payload = {"auth_id": payload}
15126
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
15127
+
14963
15128
  @overload
14964
15129
  def login_check_sso(
14965
15130
  self,
14966
15131
  /,
15132
+ app: str = "web",
15133
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15134
+ *,
14967
15135
  async_: Literal[False] = False,
14968
15136
  **request_kwargs,
14969
15137
  ) -> dict:
@@ -14972,6 +15140,9 @@ class P115Client(P115OpenClient):
14972
15140
  def login_check_sso(
14973
15141
  self,
14974
15142
  /,
15143
+ app: str = "web",
15144
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15145
+ *,
14975
15146
  async_: Literal[True],
14976
15147
  **request_kwargs,
14977
15148
  ) -> Coroutine[Any, Any, dict]:
@@ -14979,14 +15150,17 @@ class P115Client(P115OpenClient):
14979
15150
  def login_check_sso(
14980
15151
  self,
14981
15152
  /,
15153
+ app: str = "web",
15154
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15155
+ *,
14982
15156
  async_: Literal[False, True] = False,
14983
15157
  **request_kwargs,
14984
15158
  ) -> dict | Coroutine[Any, Any, dict]:
14985
15159
  """检查当前 cookies 的登录状态信息,并且自最近一次登录的 60 秒后,使当前设备下除最近一次登录外的所有 cookies 失效
14986
15160
 
14987
- GET https://passportapi.115.com/app/1.0/web/1.0/check/sso
15161
+ GET https://qrcodeapi.115.com/app/1.0/web/1.0/check/sso
14988
15162
  """
14989
- api = "https://passportapi.115.com/app/1.0/web/1.0/check/sso"
15163
+ api = complete_api(f"/app/1.0/{app}/1.0/check/sso", base_url=base_url)
14990
15164
  return self.request(url=api, async_=async_, **request_kwargs)
14991
15165
 
14992
15166
  @overload
@@ -15025,6 +15199,9 @@ class P115Client(P115OpenClient):
15025
15199
  def login_devices(
15026
15200
  self,
15027
15201
  /,
15202
+ app: str = "web",
15203
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15204
+ *,
15028
15205
  async_: Literal[False] = False,
15029
15206
  **request_kwargs,
15030
15207
  ) -> dict:
@@ -15033,6 +15210,9 @@ class P115Client(P115OpenClient):
15033
15210
  def login_devices(
15034
15211
  self,
15035
15212
  /,
15213
+ app: str = "web",
15214
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15215
+ *,
15036
15216
  async_: Literal[True],
15037
15217
  **request_kwargs,
15038
15218
  ) -> Coroutine[Any, Any, dict]:
@@ -15040,14 +15220,17 @@ class P115Client(P115OpenClient):
15040
15220
  def login_devices(
15041
15221
  self,
15042
15222
  /,
15223
+ app: str = "web",
15224
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15225
+ *,
15043
15226
  async_: Literal[False, True] = False,
15044
15227
  **request_kwargs,
15045
15228
  ) -> dict | Coroutine[Any, Any, dict]:
15046
15229
  """获取所有的已登录设备的信息,不过当前的 cookies 必须是登录状态(未退出或未失效)
15047
15230
 
15048
- GET https://passportapi.115.com/app/1.0/web/1.0/login_log/login_devices
15231
+ GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/login_devices
15049
15232
  """
15050
- api = "https://passportapi.115.com/app/1.0/web/1.0/login_log/login_devices"
15233
+ api = complete_api(f"/app/1.0/{app}/1.0/login_log/login_devices", base_url=base_url)
15051
15234
  return self.request(url=api, async_=async_, **request_kwargs)
15052
15235
 
15053
15236
  @overload
@@ -15093,6 +15276,8 @@ class P115Client(P115OpenClient):
15093
15276
  self,
15094
15277
  payload: dict = {},
15095
15278
  /,
15279
+ app: str = "web",
15280
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15096
15281
  *,
15097
15282
  async_: Literal[False] = False,
15098
15283
  **request_kwargs,
@@ -15103,6 +15288,8 @@ class P115Client(P115OpenClient):
15103
15288
  self,
15104
15289
  payload: dict = {},
15105
15290
  /,
15291
+ app: str = "web",
15292
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15106
15293
  *,
15107
15294
  async_: Literal[True],
15108
15295
  **request_kwargs,
@@ -15112,19 +15299,21 @@ class P115Client(P115OpenClient):
15112
15299
  self,
15113
15300
  payload: dict = {},
15114
15301
  /,
15302
+ app: str = "web",
15303
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15115
15304
  *,
15116
15305
  async_: Literal[False, True] = False,
15117
15306
  **request_kwargs,
15118
15307
  ) -> dict | Coroutine[Any, Any, dict]:
15119
15308
  """获取登录信息日志列表
15120
15309
 
15121
- GET https://passportapi.115.com/app/1.0/web/1.0/login_log/log
15310
+ GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/log
15122
15311
 
15123
15312
  :payload:
15124
15313
  - start: int = 0
15125
15314
  - limit: int = 100
15126
15315
  """
15127
- api = "https://passportapi.115.com/app/1.0/web/1.0/login_log/log"
15316
+ api = complete_api(f"/app/1.0/{app}/1.0/login_log/log", base_url=base_url)
15128
15317
  payload = {"start": 0, "limit": 100, **payload}
15129
15318
  return self.request(url=api, params=payload, async_=async_, **request_kwargs)
15130
15319
 
@@ -15133,6 +15322,7 @@ class P115Client(P115OpenClient):
15133
15322
  self,
15134
15323
  /,
15135
15324
  app: str = "web",
15325
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15136
15326
  *,
15137
15327
  async_: Literal[False] = False,
15138
15328
  **request_kwargs,
@@ -15143,6 +15333,7 @@ class P115Client(P115OpenClient):
15143
15333
  self,
15144
15334
  /,
15145
15335
  app: str = "web",
15336
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15146
15337
  *,
15147
15338
  async_: Literal[True],
15148
15339
  **request_kwargs,
@@ -15152,15 +15343,16 @@ class P115Client(P115OpenClient):
15152
15343
  self,
15153
15344
  /,
15154
15345
  app: str = "web",
15346
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15155
15347
  *,
15156
15348
  async_: Literal[False, True] = False,
15157
15349
  **request_kwargs,
15158
15350
  ) -> dict | Coroutine[Any, Any, dict]:
15159
15351
  """当前登录的设备总数和最近登录的设备
15160
15352
 
15161
- GET https://passportapi.115.com/app/1.0/web/1.0/login_log/login_online
15353
+ GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/login_online
15162
15354
  """
15163
- api = f"http://passportapi.115.com/app/1.0/{app}/1.0/login_log/login_online"
15355
+ api = complete_api(f"/app/1.0/{app}/1.0/login_log/login_online", base_url=base_url)
15164
15356
  return self.request(url=api, async_=async_, **request_kwargs)
15165
15357
 
15166
15358
  @overload
@@ -15222,6 +15414,7 @@ class P115Client(P115OpenClient):
15222
15414
  /,
15223
15415
  app: None | str = None,
15224
15416
  request: None | Callable = None,
15417
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15225
15418
  *,
15226
15419
  async_: Literal[False] = False,
15227
15420
  **request_kwargs,
@@ -15233,6 +15426,7 @@ class P115Client(P115OpenClient):
15233
15426
  /,
15234
15427
  app: None | str = None,
15235
15428
  request: None | Callable = None,
15429
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15236
15430
  *,
15237
15431
  async_: Literal[True],
15238
15432
  **request_kwargs,
@@ -15243,13 +15437,14 @@ class P115Client(P115OpenClient):
15243
15437
  /,
15244
15438
  app: None | str = None,
15245
15439
  request: None | Callable = None,
15440
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15246
15441
  *,
15247
15442
  async_: Literal[False, True] = False,
15248
15443
  **request_kwargs,
15249
15444
  ) -> None | Coroutine[Any, Any, None]:
15250
15445
  """退出登录状态(可以把某个客户端下线,所有已登录设备可从 `login_devices` 获取)
15251
15446
 
15252
- GET https://passportapi.115.com/app/1.0/{app}/1.0/logout/logout
15447
+ GET https://qrcodeapi.115.com/app/1.0/{app}/1.0/logout/logout
15253
15448
 
15254
15449
  :param app: 退出登录的 app
15255
15450
 
@@ -15315,7 +15510,7 @@ class P115Client(P115OpenClient):
15315
15510
  app = yield self.login_app(async_=async_)
15316
15511
  if app == "desktop":
15317
15512
  app = "web"
15318
- api = f"http://passportapi.115.com/app/1.0/{app}/1.0/logout/logout"
15513
+ api = complete_api(f"/app/1.0/{app}/1.0/logout/logout", base_url=base_url)
15319
15514
  request_kwargs["headers"] = {**(request_kwargs.get("headers") or {}), "Cookie": self.cookies_str}
15320
15515
  request_kwargs.setdefault("parse", ...)
15321
15516
  if request is None:
@@ -15329,6 +15524,8 @@ class P115Client(P115OpenClient):
15329
15524
  self,
15330
15525
  payload: None | str | dict = None,
15331
15526
  /,
15527
+ app: str = "web",
15528
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15332
15529
  *,
15333
15530
  async_: Literal[False] = False,
15334
15531
  **request_kwargs,
@@ -15339,6 +15536,8 @@ class P115Client(P115OpenClient):
15339
15536
  self,
15340
15537
  payload: None | str | dict = None,
15341
15538
  /,
15539
+ app: str = "web",
15540
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15342
15541
  *,
15343
15542
  async_: Literal[True],
15344
15543
  **request_kwargs,
@@ -15348,13 +15547,15 @@ class P115Client(P115OpenClient):
15348
15547
  self,
15349
15548
  payload: None | str | dict = None,
15350
15549
  /,
15550
+ app: str = "web",
15551
+ base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
15351
15552
  *,
15352
15553
  async_: Literal[False, True] = False,
15353
15554
  **request_kwargs,
15354
15555
  ) -> dict | Coroutine[Any, Any, dict]:
15355
15556
  """退出登录状态(可以把某个客户端下线,所有已登录设备可从 `login_devices` 获取)
15356
15557
 
15357
- POST https://passportapi.115.com/app/1.0/web/1.0/logout/mange
15558
+ POST https://qrcodeapi.115.com/app/1.0/web/1.0/logout/mange
15358
15559
 
15359
15560
  :payload:
15360
15561
  - ssoent: str
@@ -15415,7 +15616,7 @@ class P115Client(P115OpenClient):
15415
15616
  | 24 | S1 | harmony | 115(Harmony端) |
15416
15617
  +-------+----------+------------+-------------------------+
15417
15618
  """
15418
- api = "https://passportapi.115.com/app/1.0/web/1.0/logout/mange"
15619
+ api = complete_api(f"/app/1.0/{app}/1.0/logout/mange", base_url=base_url)
15419
15620
  if payload is None:
15420
15621
  payload = {"ssoent": self.login_ssoent or ""}
15421
15622
  elif isinstance(payload, str):
@@ -14,7 +14,7 @@ from typing import Final
14
14
 
15
15
 
16
16
  #: 可用的 AppID 列表
17
- AVAILABLE_APP_IDS = range(100195123, 100196837, 2)
17
+ AVAILABLE_APP_IDS = range(100195123, 100196845, 2)
18
18
 
19
19
 
20
20
  #: 目前可用的登录设备
@@ -3,8 +3,9 @@
3
3
 
4
4
  __all__ = [
5
5
  "P115Warning", "P115OSError", "AuthenticationError", "BusyOSError", "DataError",
6
- "LoginError", "MultipartUploadAbort", "NotSupportedError", "OperationalError",
7
- "P115FileExistsError", "P115FileNotFoundError", "P115IsADirectoryError",
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.6"
3
+ version = "0.0.5.10.7"
4
4
  description = "Python 115 webdisk client."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"
@@ -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,说明有问题出现,会根据实际情况抛出一个异常,但都是 `OSError` 的实例,其中大部分还是 `p115client.P115OSError` 的实例。
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