p115client 0.0.5.10.4__py3-none-any.whl → 0.0.5.11__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.
- p115client/_upload.py +6 -6
- p115client/client.py +1516 -377
- p115client/const.py +1 -1
- p115client/exception.py +8 -2
- p115client/tool/attr.py +2 -1
- p115client/tool/download.py +76 -59
- p115client/tool/edit.py +3 -3
- p115client/tool/export_dir.py +18 -19
- p115client/tool/fs_files.py +4 -7
- p115client/tool/history.py +4 -4
- p115client/tool/iterdir.py +403 -226
- p115client/tool/life.py +10 -10
- p115client/tool/pool.py +5 -5
- p115client/tool/upload.py +3 -3
- p115client/tool/xys.py +10 -7
- {p115client-0.0.5.10.4.dist-info → p115client-0.0.5.11.dist-info}/METADATA +5 -5
- p115client-0.0.5.11.dist-info/RECORD +26 -0
- p115client-0.0.5.10.4.dist-info/RECORD +0 -26
- {p115client-0.0.5.10.4.dist-info → p115client-0.0.5.11.dist-info}/LICENSE +0 -0
- {p115client-0.0.5.10.4.dist-info → p115client-0.0.5.11.dist-info}/WHEEL +0 -0
p115client/client.py
CHANGED
@@ -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
|
@@ -181,7 +181,7 @@ def complete_proapi(
|
|
181
181
|
) -> str:
|
182
182
|
if path and not path.startswith("/"):
|
183
183
|
path = "/" + path
|
184
|
-
if app
|
184
|
+
if app in ("aps", "desktop", "open", "web"):
|
185
185
|
app = "android"
|
186
186
|
if app and not app.startswith("/"):
|
187
187
|
app = "/" + app
|
@@ -266,7 +266,7 @@ def get_default_request():
|
|
266
266
|
return _httpx_request
|
267
267
|
|
268
268
|
|
269
|
-
def parse_upload_init_response(
|
269
|
+
def parse_upload_init_response(_, content: bytes, /) -> dict:
|
270
270
|
data = ecdh_aes_decode(content, decompress=True)
|
271
271
|
if not isinstance(data, (bytes, bytearray, memoryview)):
|
272
272
|
data = memoryview(data)
|
@@ -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)
|
@@ -538,6 +542,36 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
|
|
538
542
|
# {"state": 0, "errno": 40140126, "error": "access_token 校验失败(防篡改)"}
|
539
543
|
case 40140126:
|
540
544
|
raise OperationalError(errno.EINVAL, resp)
|
545
|
+
# {"state": 0, "errno": 40140127, "error": "response_type 错误"}
|
546
|
+
case 40140127:
|
547
|
+
raise OperationalError(errno.EINVAL, resp)
|
548
|
+
# {"state": 0, "errno": 40140128, "error": "redirect_uri 缺少协议"}
|
549
|
+
case 40140128:
|
550
|
+
raise OperationalError(errno.EINVAL, resp)
|
551
|
+
# {"state": 0, "errno": 40140129, "error": "redirect_uri 缺少域名"}
|
552
|
+
case 40140129:
|
553
|
+
raise OperationalError(errno.EINVAL, resp)
|
554
|
+
# {"state": 0, "errno": 40140130, "error": "没有配置重定向域名"}
|
555
|
+
case 40140130:
|
556
|
+
raise OperationalError(errno.EINVAL, resp)
|
557
|
+
# {"state": 0, "errno": 40140131, "error": "redirect_uri 非法域名"}
|
558
|
+
case 40140131:
|
559
|
+
raise OperationalError(errno.EINVAL, resp)
|
560
|
+
# {"state": 0, "errno": 40140132, "error": "grant_type 错误"}
|
561
|
+
case 40140132:
|
562
|
+
raise OperationalError(errno.EINVAL, resp)
|
563
|
+
# {"state": 0, "errno": 40140133, "error": "client_secret 验证失败"}
|
564
|
+
case 40140133:
|
565
|
+
raise OperationalError(errno.EINVAL, resp)
|
566
|
+
# {"state": 0, "errno": 40140134, "error": "授权码 code 验证失败"}
|
567
|
+
case 40140134:
|
568
|
+
raise OperationalError(errno.EINVAL, resp)
|
569
|
+
# {"state": 0, "errno": 40140135, "error": "client_id 验证失败"}
|
570
|
+
case 40140135:
|
571
|
+
raise OperationalError(errno.EINVAL, resp)
|
572
|
+
# {"state": 0, "errno": 40140136, "error": "redirect_uri 验证失败(防MITM)"}
|
573
|
+
case 40140136:
|
574
|
+
raise OperationalError(errno.EINVAL, resp)
|
541
575
|
elif "msg_code" in resp:
|
542
576
|
match resp["msg_code"]:
|
543
577
|
case 50028:
|
@@ -612,9 +646,6 @@ def normalize_attr_web(
|
|
612
646
|
if "te" in info:
|
613
647
|
attr["mtime"] = int(info["te"])
|
614
648
|
else:
|
615
|
-
attr["labels"] = info["fl"]
|
616
|
-
if "score" in info:
|
617
|
-
attr["score"] = int(info.get("score") or 0)
|
618
649
|
attr["ico"] = info.get("ico", "folder" if is_directory else "")
|
619
650
|
if "te" in info:
|
620
651
|
attr["mtime"] = attr["user_utime"] = int(info["te"])
|
@@ -647,12 +678,14 @@ def normalize_attr_web(
|
|
647
678
|
("c", "violated"),
|
648
679
|
("c", "is_collect"),
|
649
680
|
("sh", "is_share"),
|
681
|
+
("score", "score"),
|
650
682
|
#("d", "has_desc"),
|
651
683
|
#("p", "has_pass"),
|
652
684
|
):
|
653
685
|
if key in info:
|
654
686
|
attr[name] = int(info[key] or 0)
|
655
687
|
for key, name in (
|
688
|
+
("fl", "labels"),
|
656
689
|
("dp", "dir_path"),
|
657
690
|
("style", "style"),
|
658
691
|
("ns", "name_show"),
|
@@ -740,10 +773,7 @@ def normalize_attr_app(
|
|
740
773
|
if "upt" in info:
|
741
774
|
attr["mtime"] = int(info["upt"])
|
742
775
|
else:
|
743
|
-
attr["labels"] = info["fl"]
|
744
776
|
attr["ico"] = info.get("ico", "folder" if attr["is_dir"] else "")
|
745
|
-
if "ftype" in info:
|
746
|
-
attr["file_type"] = int(info["ftype"] or 0)
|
747
777
|
if "thumb" in info:
|
748
778
|
thumb = info["thumb"]
|
749
779
|
if thumb.startswith("?"):
|
@@ -759,6 +789,7 @@ def normalize_attr_app(
|
|
759
789
|
("aid", "area_id"),
|
760
790
|
("fatr", "audio_play_long"),
|
761
791
|
("fta", "status"),
|
792
|
+
("ftype", "file_type"),
|
762
793
|
("ism", "star"),
|
763
794
|
("ism", "is_mark"),
|
764
795
|
("is_top", "is_top"),
|
@@ -780,6 +811,7 @@ def normalize_attr_app(
|
|
780
811
|
("fco", "cover"),
|
781
812
|
("fco", "folder_cover"),
|
782
813
|
("fdesc", "desc"),
|
814
|
+
("fl", "labels"),
|
783
815
|
("flabel", "fflabel"),
|
784
816
|
("multitrack", "multitrack"),
|
785
817
|
("play_long", "play_long"),
|
@@ -834,18 +866,28 @@ def normalize_attr_app2(
|
|
834
866
|
else:
|
835
867
|
dict_cls = AttrDict
|
836
868
|
attr: dict[str, Any] = dict_cls()
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
869
|
+
if "file_id" in info and "parent_id" in info:
|
870
|
+
if "file_category" in info:
|
871
|
+
is_directory = not int(info["file_category"])
|
872
|
+
else:
|
873
|
+
is_directory = bool(info.get("sha1") or info.get("file_sha1"))
|
841
874
|
attr["id"] = int(info["file_id"])
|
842
|
-
attr["parent_id"] = int(info["
|
875
|
+
attr["parent_id"] = int(info["parent_id"])
|
843
876
|
attr["name"] = info["file_name"]
|
844
877
|
else:
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
878
|
+
is_directory = "file_id" not in info
|
879
|
+
if is_directory:
|
880
|
+
attr["id"] = int(info["file_id"])
|
881
|
+
attr["parent_id"] = int(info["category_id"])
|
882
|
+
attr["name"] = info["file_name"]
|
883
|
+
else:
|
884
|
+
attr["id"] = int(info["category_id"])
|
885
|
+
attr["parent_id"] = int(info["parent_id"])
|
886
|
+
attr["name"] = info["category_name"]
|
887
|
+
attr["is_dir"] = is_directory
|
888
|
+
if not simple:
|
889
|
+
attr["is_directory"] = is_directory
|
890
|
+
attr["sha1"] = info.get("sha1") or info.get("file_sha1") or ""
|
849
891
|
attr["size"] = int(info.get("file_size") or 0)
|
850
892
|
if "pick_code" in info:
|
851
893
|
attr["pickcode"] = info["pick_code"]
|
@@ -886,7 +928,8 @@ def normalize_attr_app2(
|
|
886
928
|
if "utime" in info:
|
887
929
|
attr["utime"] = int(info["utime"])
|
888
930
|
attr["ico"] = info.get("ico", "folder" if attr["is_dir"] else "")
|
889
|
-
|
931
|
+
if "fl" in info:
|
932
|
+
attr["labels"] = info["fl"]
|
890
933
|
for key, name in (
|
891
934
|
("area_id", "area_id"),
|
892
935
|
("has_desc", "has_desc"),
|
@@ -1154,13 +1197,17 @@ class ClientRequestMixin:
|
|
1154
1197
|
"user-agent": "Mozilla/5.0 AppleWebKit/600 Safari/600 Chrome/124.0.0.0",
|
1155
1198
|
})
|
1156
1199
|
|
1200
|
+
@locked_cacheproperty
|
1201
|
+
def request_kwargs(self, /) -> dict:
|
1202
|
+
return {}
|
1203
|
+
|
1157
1204
|
def close(self, /) -> None:
|
1158
1205
|
"""删除 session 和 async_session 属性,如果它们未被引用,则应该会被自动清理
|
1159
1206
|
"""
|
1160
1207
|
self.__dict__.pop("session", None)
|
1161
1208
|
self.__dict__.pop("async_session", None)
|
1162
1209
|
|
1163
|
-
def
|
1210
|
+
def _request(
|
1164
1211
|
self,
|
1165
1212
|
/,
|
1166
1213
|
url: str,
|
@@ -1278,14 +1325,203 @@ class ClientRequestMixin:
|
|
1278
1325
|
request_kwargs.setdefault("parse", default_parse)
|
1279
1326
|
return request(url=url, method=method, **request_kwargs)
|
1280
1327
|
|
1328
|
+
def request(
|
1329
|
+
self,
|
1330
|
+
/,
|
1331
|
+
url: str,
|
1332
|
+
method: str = "GET",
|
1333
|
+
params = None,
|
1334
|
+
data = None,
|
1335
|
+
*,
|
1336
|
+
async_: Literal[False, True] = False,
|
1337
|
+
**request_kwargs,
|
1338
|
+
):
|
1339
|
+
"""帮助函数:可执行同步和异步的网络请求
|
1340
|
+
|
1341
|
+
:param url: HTTP 的请求链接
|
1342
|
+
:param method: HTTP 的请求方法
|
1343
|
+
:param params: 查询参数
|
1344
|
+
:param ecdh_encrypt: 使用 ecdh 算法进行加密(返回值也要解密)
|
1345
|
+
:param async_: 说明 `request` 是同步调用还是异步调用
|
1346
|
+
:param request: HTTP 请求调用,如果为 None,则默认用 httpx 执行请求
|
1347
|
+
如果传入调用,则必须至少能接受以下几个关键词参数:
|
1348
|
+
|
1349
|
+
- url: HTTP 的请求链接
|
1350
|
+
- method: HTTP 的请求方法
|
1351
|
+
- headers: HTTP 的请求头
|
1352
|
+
- data: HTTP 的请求体
|
1353
|
+
- parse: 解析 HTTP 响应的方法,默认会构建一个 Callable,会把响应的字节数据视为 JSON 进行反序列化解析
|
1354
|
+
|
1355
|
+
- 如果为 None,则直接把响应对象返回
|
1356
|
+
- 如果为 ...(Ellipsis),则把响应对象关闭后将其返回
|
1357
|
+
- 如果为 True,则根据响应头来确定把响应得到的字节数据解析成何种格式(反序列化),请求也会被自动关闭
|
1358
|
+
- 如果为 False,则直接返回响应得到的字节数据,请求也会被自动关闭
|
1359
|
+
- 如果为 Callable,则使用此调用来解析数据,接受 1-2 个位置参数,并把解析结果返回给 `request` 的调用者,请求也会被自动关闭
|
1360
|
+
- 如果只接受 1 个位置参数,则把响应对象传给它
|
1361
|
+
- 如果能接受 2 个位置参数,则把响应对象和响应得到的字节数据(响应体)传给它
|
1362
|
+
|
1363
|
+
:param request_kwargs: 其余的请求参数,会被传给 `request`
|
1364
|
+
|
1365
|
+
:return: 直接返回 `request` 执行请求后的返回值
|
1366
|
+
|
1367
|
+
.. note::
|
1368
|
+
`request` 可以由不同的请求库来提供,下面是封装了一些模块
|
1369
|
+
|
1370
|
+
1. `httpx_request <https://pypi.org/project/httpx_request/>`_,由 `httpx <https://pypi.org/project/httpx/>`_ 封装,支持同步和异步调用,本模块默认用的就是这个封装
|
1371
|
+
|
1372
|
+
.. code:: python
|
1373
|
+
|
1374
|
+
from httpx_request import request
|
1375
|
+
|
1376
|
+
2. `python-urlopen <https://pypi.org/project/python-urlopen/>`_,由 `urllib.request.urlopen <https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen>`_ 封装,支持同步调用,性能相对最差
|
1377
|
+
|
1378
|
+
.. code:: python
|
1379
|
+
|
1380
|
+
from urlopen import request
|
1381
|
+
|
1382
|
+
3. `urllib3_request <https://pypi.org/project/urllib3_request/>`_,由 `urllib3 <https://pypi.org/project/urllib3/>`_ 封装,支持同步调用,性能相对较好,推荐使用
|
1383
|
+
|
1384
|
+
.. code:: python
|
1385
|
+
|
1386
|
+
from urllib3_request import request
|
1387
|
+
|
1388
|
+
4. `requests_request <https://pypi.org/project/requests_request/>`_,由 `requests <https://pypi.org/project/requests/>`_ 封装,支持同步调用
|
1389
|
+
|
1390
|
+
.. code:: python
|
1391
|
+
|
1392
|
+
from requests_request import request
|
1393
|
+
|
1394
|
+
5. `aiohttp_client_request <https://pypi.org/project/aiohttp_client_request/>`_,由 `aiohttp <https://pypi.org/project/aiohttp/>`_ 封装,支持异步调用,异步并发能力最强,推荐使用
|
1395
|
+
|
1396
|
+
.. code:: python
|
1397
|
+
|
1398
|
+
from aiohttp_client_request import request
|
1399
|
+
|
1400
|
+
6. `blacksheep_client_request <https://pypi.org/project/blacksheep_client_request/>`_,由 `blacksheep <https://pypi.org/project/blacksheep/>`_ 封装,支持异步调用
|
1401
|
+
|
1402
|
+
.. code:: python
|
1403
|
+
|
1404
|
+
from blacksheep_client_request import request
|
1405
|
+
"""
|
1406
|
+
kwargs = {**self.request_kwargs, **request_kwargs}
|
1407
|
+
return self._request(url, method, params, data, async_=async_, **kwargs)
|
1408
|
+
|
1281
1409
|
########## Qrcode API ##########
|
1282
1410
|
|
1411
|
+
@overload
|
1412
|
+
def login_authorize_open(
|
1413
|
+
self,
|
1414
|
+
payload: dict,
|
1415
|
+
/,
|
1416
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1417
|
+
*,
|
1418
|
+
async_: Literal[False] = False,
|
1419
|
+
**request_kwargs,
|
1420
|
+
) -> dict:
|
1421
|
+
...
|
1422
|
+
@overload
|
1423
|
+
def login_authorize_open(
|
1424
|
+
self,
|
1425
|
+
payload: dict,
|
1426
|
+
/,
|
1427
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1428
|
+
*,
|
1429
|
+
async_: Literal[True],
|
1430
|
+
**request_kwargs,
|
1431
|
+
) -> Coroutine[Any, Any, dict]:
|
1432
|
+
...
|
1433
|
+
def login_authorize_open(
|
1434
|
+
self,
|
1435
|
+
payload: dict,
|
1436
|
+
/,
|
1437
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1438
|
+
*,
|
1439
|
+
async_: Literal[False, True] = False,
|
1440
|
+
**request_kwargs,
|
1441
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
1442
|
+
"""授权码方式请求开放接口应用授权
|
1443
|
+
|
1444
|
+
GET https://qrcodeapi.115.com/open/authorize
|
1445
|
+
|
1446
|
+
.. admonition:: Reference
|
1447
|
+
|
1448
|
+
https://www.yuque.com/115yun/open/okr2cq0wywelscpe#EiOrD
|
1449
|
+
|
1450
|
+
:payload:
|
1451
|
+
- client_id: int | str 💡 AppID
|
1452
|
+
- redirect_uri: str 💡 授权成功后重定向到指定的地址并附上授权码 code,需要先到 https://open.115.com/ 应用管理应用域名设置
|
1453
|
+
- response_type: str = "code" 💡 授权模式,固定为 code,表示授权码模式
|
1454
|
+
- state: int | str = <default> 💡 随机值,会通过 redirect_uri 原样返回,可用于验证以防 MITM 和 CSRF
|
1455
|
+
"""
|
1456
|
+
api = complete_api("/open/authorize", base_url=base_url)
|
1457
|
+
payload = {"response_type": "code", **payload}
|
1458
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
1459
|
+
|
1460
|
+
@overload
|
1461
|
+
@staticmethod
|
1462
|
+
def login_authorize_access_token_open(
|
1463
|
+
payload: dict,
|
1464
|
+
/,
|
1465
|
+
request: None | Callable = None,
|
1466
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1467
|
+
*,
|
1468
|
+
async_: Literal[False] = False,
|
1469
|
+
**request_kwargs,
|
1470
|
+
) -> dict:
|
1471
|
+
...
|
1472
|
+
@overload
|
1473
|
+
@staticmethod
|
1474
|
+
def login_authorize_access_token_open(
|
1475
|
+
payload: dict,
|
1476
|
+
/,
|
1477
|
+
request: None | Callable = None,
|
1478
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1479
|
+
*,
|
1480
|
+
async_: Literal[True],
|
1481
|
+
**request_kwargs,
|
1482
|
+
) -> Coroutine[Any, Any, dict]:
|
1483
|
+
...
|
1484
|
+
@staticmethod
|
1485
|
+
def login_authorize_access_token_open(
|
1486
|
+
payload: dict,
|
1487
|
+
/,
|
1488
|
+
request: None | Callable = None,
|
1489
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1490
|
+
*,
|
1491
|
+
async_: Literal[False, True] = False,
|
1492
|
+
**request_kwargs,
|
1493
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
1494
|
+
"""用授权码获取开放接口应用的 access_token
|
1495
|
+
|
1496
|
+
POST https://qrcodeapi.115.com/open/authCodeToToken
|
1497
|
+
|
1498
|
+
.. admonition:: Reference
|
1499
|
+
|
1500
|
+
https://www.yuque.com/115yun/open/okr2cq0wywelscpe#JnDgl
|
1501
|
+
|
1502
|
+
:payload:
|
1503
|
+
- client_id: int | str 💡 AppID
|
1504
|
+
- client_secret: str 💡 AppSecret
|
1505
|
+
- code: str 💡 授权码,/open/authCodeToToken 重定向地址里面
|
1506
|
+
- redirect_uri: str 💡 与 /open/authCodeToToken 传的 redirect_uri 一致,可用于验证以防 MITM 和 CSRF
|
1507
|
+
- grant_type: str = "authorization_code" 💡 授权类型,固定为 authorization_code,表示授权码类型
|
1508
|
+
"""
|
1509
|
+
api = complete_api("/open/authCodeToToken", base_url=base_url)
|
1510
|
+
payload = {"grant_type": "authorization_code", **payload}
|
1511
|
+
request_kwargs.setdefault("parse", default_parse)
|
1512
|
+
if request is None:
|
1513
|
+
return get_default_request()(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
1514
|
+
else:
|
1515
|
+
return request(url=api, method="POST", data=payload, **request_kwargs)
|
1516
|
+
|
1283
1517
|
@overload
|
1284
1518
|
@staticmethod
|
1285
1519
|
def login_qrcode(
|
1286
1520
|
payload: str | dict,
|
1287
1521
|
/,
|
1288
1522
|
request: None | Callable = None,
|
1523
|
+
app: str = "web",
|
1524
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1289
1525
|
*,
|
1290
1526
|
async_: Literal[False] = False,
|
1291
1527
|
**request_kwargs,
|
@@ -1297,6 +1533,8 @@ class ClientRequestMixin:
|
|
1297
1533
|
payload: str | dict,
|
1298
1534
|
/,
|
1299
1535
|
request: None | Callable = None,
|
1536
|
+
app: str = "web",
|
1537
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1300
1538
|
*,
|
1301
1539
|
async_: Literal[True],
|
1302
1540
|
**request_kwargs,
|
@@ -1307,6 +1545,8 @@ class ClientRequestMixin:
|
|
1307
1545
|
payload: str | dict,
|
1308
1546
|
/,
|
1309
1547
|
request: None | Callable = None,
|
1548
|
+
app: str = "web",
|
1549
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1310
1550
|
*,
|
1311
1551
|
async_: Literal[False, True] = False,
|
1312
1552
|
**request_kwargs,
|
@@ -1319,7 +1559,7 @@ class ClientRequestMixin:
|
|
1319
1559
|
|
1320
1560
|
:return: 图片的二进制数据(PNG 图片)
|
1321
1561
|
"""
|
1322
|
-
api = "
|
1562
|
+
api = complete_api(f"/api/1.0/{app}/1.0/qrcode", base_url=base_url)
|
1323
1563
|
if isinstance(payload, str):
|
1324
1564
|
payload = {"uid": payload}
|
1325
1565
|
request_kwargs.setdefault("parse", False)
|
@@ -1334,6 +1574,7 @@ class ClientRequestMixin:
|
|
1334
1574
|
payload: str | dict,
|
1335
1575
|
/,
|
1336
1576
|
request: None | Callable = None,
|
1577
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1337
1578
|
*,
|
1338
1579
|
async_: Literal[False] = False,
|
1339
1580
|
**request_kwargs,
|
@@ -1345,6 +1586,7 @@ class ClientRequestMixin:
|
|
1345
1586
|
payload: str | dict,
|
1346
1587
|
/,
|
1347
1588
|
request: None | Callable = None,
|
1589
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1348
1590
|
*,
|
1349
1591
|
async_: Literal[True],
|
1350
1592
|
**request_kwargs,
|
@@ -1355,6 +1597,7 @@ class ClientRequestMixin:
|
|
1355
1597
|
payload: str | dict,
|
1356
1598
|
/,
|
1357
1599
|
request: None | Callable = None,
|
1600
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1358
1601
|
*,
|
1359
1602
|
async_: Literal[False, True] = False,
|
1360
1603
|
**request_kwargs,
|
@@ -1364,13 +1607,14 @@ class ClientRequestMixin:
|
|
1364
1607
|
POST https://qrcodeapi.115.com/open/deviceCodeToToken
|
1365
1608
|
|
1366
1609
|
.. admonition:: Reference
|
1610
|
+
|
1367
1611
|
https://www.yuque.com/115yun/open/shtpzfhewv5nag11#QCCVQ
|
1368
1612
|
|
1369
1613
|
:payload:
|
1370
1614
|
- uid: str
|
1371
1615
|
- code_verifier: str = <default> 💡 默认字符串是 64 个 "0"
|
1372
1616
|
"""
|
1373
|
-
api = "
|
1617
|
+
api = complete_api("/open/deviceCodeToToken", base_url=base_url)
|
1374
1618
|
if isinstance(payload, str):
|
1375
1619
|
payload = {"uid": payload, "code_verifier": _default_code_verifier}
|
1376
1620
|
request_kwargs.setdefault("parse", default_parse)
|
@@ -1380,138 +1624,175 @@ class ClientRequestMixin:
|
|
1380
1624
|
return request(url=api, method="POST", data=payload, **request_kwargs)
|
1381
1625
|
|
1382
1626
|
@overload
|
1383
|
-
|
1384
|
-
|
1627
|
+
def login_qrcode_scan(
|
1628
|
+
self,
|
1385
1629
|
payload: str | dict,
|
1386
1630
|
/,
|
1387
|
-
|
1631
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1388
1632
|
*,
|
1389
1633
|
async_: Literal[False] = False,
|
1390
1634
|
**request_kwargs,
|
1391
1635
|
) -> dict:
|
1392
1636
|
...
|
1393
1637
|
@overload
|
1394
|
-
|
1395
|
-
|
1638
|
+
def login_qrcode_scan(
|
1639
|
+
self,
|
1396
1640
|
payload: str | dict,
|
1397
1641
|
/,
|
1398
|
-
|
1642
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1399
1643
|
*,
|
1400
1644
|
async_: Literal[True],
|
1401
1645
|
**request_kwargs,
|
1402
1646
|
) -> Coroutine[Any, Any, dict]:
|
1403
1647
|
...
|
1404
|
-
|
1405
|
-
|
1648
|
+
def login_qrcode_scan(
|
1649
|
+
self,
|
1406
1650
|
payload: str | dict,
|
1407
1651
|
/,
|
1408
|
-
|
1652
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1409
1653
|
*,
|
1410
1654
|
async_: Literal[False, True] = False,
|
1411
1655
|
**request_kwargs,
|
1412
1656
|
) -> dict | Coroutine[Any, Any, dict]:
|
1413
|
-
"""
|
1414
|
-
|
1415
|
-
POST https://qrcodeapi.115.com/open/refreshToken
|
1657
|
+
"""扫描二维码,payload 数据取自 `login_qrcode_token` 接口响应
|
1416
1658
|
|
1417
|
-
|
1418
|
-
https://www.yuque.com/115yun/open/shtpzfhewv5nag11#ve54x
|
1659
|
+
GET https://qrcodeapi.115.com/api/2.0/prompt.php
|
1419
1660
|
|
1420
1661
|
:payload:
|
1421
|
-
-
|
1662
|
+
- uid: str
|
1422
1663
|
"""
|
1423
|
-
api = "
|
1664
|
+
api = complete_api("/api/2.0/prompt.php", base_url=base_url)
|
1424
1665
|
if isinstance(payload, str):
|
1425
|
-
payload = {"
|
1426
|
-
|
1427
|
-
if request is None:
|
1428
|
-
return get_default_request()(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
1429
|
-
else:
|
1430
|
-
return request(url=api, method="POST", data=payload, **request_kwargs)
|
1666
|
+
payload = {"uid": payload}
|
1667
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
1431
1668
|
|
1432
1669
|
@overload
|
1433
|
-
@staticmethod
|
1434
1670
|
def login_qrcode_scan_cancel(
|
1671
|
+
self,
|
1435
1672
|
payload: str | dict,
|
1436
1673
|
/,
|
1437
|
-
|
1674
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1438
1675
|
*,
|
1439
1676
|
async_: Literal[False] = False,
|
1440
1677
|
**request_kwargs,
|
1441
1678
|
) -> dict:
|
1442
1679
|
...
|
1443
1680
|
@overload
|
1444
|
-
@staticmethod
|
1445
1681
|
def login_qrcode_scan_cancel(
|
1682
|
+
self,
|
1446
1683
|
payload: str | dict,
|
1447
1684
|
/,
|
1448
|
-
|
1685
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1449
1686
|
*,
|
1450
1687
|
async_: Literal[True],
|
1451
1688
|
**request_kwargs,
|
1452
1689
|
) -> Coroutine[Any, Any, dict]:
|
1453
1690
|
...
|
1454
|
-
@staticmethod
|
1455
1691
|
def login_qrcode_scan_cancel(
|
1692
|
+
self,
|
1456
1693
|
payload: str | dict,
|
1457
1694
|
/,
|
1458
|
-
|
1695
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1459
1696
|
*,
|
1460
1697
|
async_: Literal[False, True] = False,
|
1461
1698
|
**request_kwargs,
|
1462
1699
|
) -> dict | Coroutine[Any, Any, dict]:
|
1463
1700
|
"""取消扫描二维码,payload 数据取自 `login_qrcode_scan` 接口响应
|
1464
1701
|
|
1465
|
-
GET https://
|
1702
|
+
GET https://qrcodeapi.115.com/api/2.0/cancel.php
|
1466
1703
|
|
1467
1704
|
:payload:
|
1468
1705
|
- key: str
|
1469
1706
|
- uid: str
|
1470
1707
|
- client: int = 0
|
1471
1708
|
"""
|
1472
|
-
api = "
|
1709
|
+
api = complete_api("/api/2.0/cancel.php", base_url=base_url)
|
1473
1710
|
if isinstance(payload, str):
|
1474
1711
|
payload = {"key": payload, "uid": payload, "client": 0}
|
1475
|
-
|
1476
|
-
if request is None:
|
1477
|
-
return get_default_request()(url=api, params=payload, async_=async_, **request_kwargs)
|
1478
|
-
else:
|
1479
|
-
return request(url=api, params=payload, **request_kwargs)
|
1712
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
1480
1713
|
|
1481
1714
|
@overload
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1715
|
+
def login_qrcode_scan_confirm(
|
1716
|
+
self,
|
1717
|
+
payload: str | dict,
|
1718
|
+
/,
|
1719
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1487
1720
|
*,
|
1488
1721
|
async_: Literal[False] = False,
|
1489
1722
|
**request_kwargs,
|
1490
1723
|
) -> dict:
|
1491
1724
|
...
|
1492
1725
|
@overload
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1726
|
+
def login_qrcode_scan_confirm(
|
1727
|
+
self,
|
1728
|
+
payload: str | dict,
|
1729
|
+
/,
|
1730
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1498
1731
|
*,
|
1499
1732
|
async_: Literal[True],
|
1500
1733
|
**request_kwargs,
|
1501
1734
|
) -> Coroutine[Any, Any, dict]:
|
1502
1735
|
...
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
*,
|
1509
|
-
async_: Literal[False, True] = False,
|
1510
|
-
**request_kwargs,
|
1736
|
+
def login_qrcode_scan_confirm(
|
1737
|
+
self,
|
1738
|
+
payload: str | dict,
|
1739
|
+
/,
|
1740
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1741
|
+
*,
|
1742
|
+
async_: Literal[False, True] = False,
|
1743
|
+
**request_kwargs,
|
1744
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
1745
|
+
"""确认扫描二维码,payload 数据取自 `login_qrcode_scan` 接口响应
|
1746
|
+
|
1747
|
+
GET https://qrcodeapi.115.com/api/2.0/slogin.php
|
1748
|
+
|
1749
|
+
:payload:
|
1750
|
+
- key: str
|
1751
|
+
- uid: str
|
1752
|
+
- client: int = 0
|
1753
|
+
"""
|
1754
|
+
api = complete_api("/api/2.0/slogin.php", base_url=base_url)
|
1755
|
+
if isinstance(payload, str):
|
1756
|
+
payload = {"key": payload, "uid": payload, "client": 0}
|
1757
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
1758
|
+
|
1759
|
+
@overload
|
1760
|
+
@staticmethod
|
1761
|
+
def login_qrcode_scan_result(
|
1762
|
+
uid: str,
|
1763
|
+
app: str = "alipaymini",
|
1764
|
+
request: None | Callable = None,
|
1765
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1766
|
+
*,
|
1767
|
+
async_: Literal[False] = False,
|
1768
|
+
**request_kwargs,
|
1769
|
+
) -> dict:
|
1770
|
+
...
|
1771
|
+
@overload
|
1772
|
+
@staticmethod
|
1773
|
+
def login_qrcode_scan_result(
|
1774
|
+
uid: str,
|
1775
|
+
app: str = "alipaymini",
|
1776
|
+
request: None | Callable = None,
|
1777
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1778
|
+
*,
|
1779
|
+
async_: Literal[True],
|
1780
|
+
**request_kwargs,
|
1781
|
+
) -> Coroutine[Any, Any, dict]:
|
1782
|
+
...
|
1783
|
+
@staticmethod
|
1784
|
+
def login_qrcode_scan_result(
|
1785
|
+
uid: str,
|
1786
|
+
app: str = "alipaymini",
|
1787
|
+
request: None | Callable = None,
|
1788
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1789
|
+
*,
|
1790
|
+
async_: Literal[False, True] = False,
|
1791
|
+
**request_kwargs,
|
1511
1792
|
) -> dict | Coroutine[Any, Any, dict]:
|
1512
1793
|
"""获取扫码登录的结果,包含 cookie
|
1513
1794
|
|
1514
|
-
POST https://
|
1795
|
+
POST https://qrcodeapi.115.com/app/1.0/{app}/1.0/login/qrcode/
|
1515
1796
|
|
1516
1797
|
:param uid: 扫码的 uid
|
1517
1798
|
:param app: 绑定的 app
|
@@ -1523,7 +1804,7 @@ class ClientRequestMixin:
|
|
1523
1804
|
"""
|
1524
1805
|
if app == "desktop":
|
1525
1806
|
app = "web"
|
1526
|
-
api = f"
|
1807
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login/qrcode/", base_url=base_url)
|
1527
1808
|
payload = {"account": uid}
|
1528
1809
|
request_kwargs.setdefault("parse", default_parse)
|
1529
1810
|
if request is None:
|
@@ -1537,6 +1818,7 @@ class ClientRequestMixin:
|
|
1537
1818
|
payload: dict,
|
1538
1819
|
/,
|
1539
1820
|
request: None | Callable = None,
|
1821
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1540
1822
|
*,
|
1541
1823
|
async_: Literal[False] = False,
|
1542
1824
|
**request_kwargs,
|
@@ -1548,6 +1830,7 @@ class ClientRequestMixin:
|
|
1548
1830
|
payload: dict,
|
1549
1831
|
/,
|
1550
1832
|
request: None | Callable = None,
|
1833
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1551
1834
|
*,
|
1552
1835
|
async_: Literal[True],
|
1553
1836
|
**request_kwargs,
|
@@ -1558,6 +1841,7 @@ class ClientRequestMixin:
|
|
1558
1841
|
payload: dict,
|
1559
1842
|
/,
|
1560
1843
|
request: None | Callable = None,
|
1844
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1561
1845
|
*,
|
1562
1846
|
async_: Literal[False, True] = False,
|
1563
1847
|
**request_kwargs,
|
@@ -1567,6 +1851,7 @@ class ClientRequestMixin:
|
|
1567
1851
|
GET https://qrcodeapi.115.com/get/status/
|
1568
1852
|
|
1569
1853
|
.. admonition:: Reference
|
1854
|
+
|
1570
1855
|
https://www.yuque.com/115yun/open/shtpzfhewv5nag11#lAsp2
|
1571
1856
|
|
1572
1857
|
:payload:
|
@@ -1574,7 +1859,7 @@ class ClientRequestMixin:
|
|
1574
1859
|
- time: int
|
1575
1860
|
- sign: str
|
1576
1861
|
"""
|
1577
|
-
api = "
|
1862
|
+
api = complete_api("/get/status/", base_url=base_url)
|
1578
1863
|
request_kwargs.setdefault("parse", default_parse)
|
1579
1864
|
if request is None:
|
1580
1865
|
return get_default_request()(url=api, params=payload, async_=async_, **request_kwargs)
|
@@ -1585,6 +1870,8 @@ class ClientRequestMixin:
|
|
1585
1870
|
@staticmethod
|
1586
1871
|
def login_qrcode_token(
|
1587
1872
|
request: None | Callable = None,
|
1873
|
+
app: str = "web",
|
1874
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1588
1875
|
*,
|
1589
1876
|
async_: Literal[False] = False,
|
1590
1877
|
**request_kwargs,
|
@@ -1594,6 +1881,8 @@ class ClientRequestMixin:
|
|
1594
1881
|
@staticmethod
|
1595
1882
|
def login_qrcode_token(
|
1596
1883
|
request: None | Callable = None,
|
1884
|
+
app: str = "web",
|
1885
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1597
1886
|
*,
|
1598
1887
|
async_: Literal[True],
|
1599
1888
|
**request_kwargs,
|
@@ -1602,6 +1891,8 @@ class ClientRequestMixin:
|
|
1602
1891
|
@staticmethod
|
1603
1892
|
def login_qrcode_token(
|
1604
1893
|
request: None | Callable = None,
|
1894
|
+
app: str = "web",
|
1895
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1605
1896
|
*,
|
1606
1897
|
async_: Literal[False, True] = False,
|
1607
1898
|
**request_kwargs,
|
@@ -1610,7 +1901,7 @@ class ClientRequestMixin:
|
|
1610
1901
|
|
1611
1902
|
GET https://qrcodeapi.115.com/api/1.0/web/1.0/token/
|
1612
1903
|
"""
|
1613
|
-
api = "
|
1904
|
+
api = complete_api(f"/api/1.0/{app}/1.0/token/", base_url=base_url)
|
1614
1905
|
request_kwargs.setdefault("parse", default_parse)
|
1615
1906
|
if request is None:
|
1616
1907
|
return get_default_request()(url=api, async_=async_, **request_kwargs)
|
@@ -1623,6 +1914,7 @@ class ClientRequestMixin:
|
|
1623
1914
|
payload: int | str | dict,
|
1624
1915
|
/,
|
1625
1916
|
request: None | Callable = None,
|
1917
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1626
1918
|
*,
|
1627
1919
|
async_: Literal[False] = False,
|
1628
1920
|
**request_kwargs,
|
@@ -1634,6 +1926,7 @@ class ClientRequestMixin:
|
|
1634
1926
|
payload: int | str | dict,
|
1635
1927
|
/,
|
1636
1928
|
request: None | Callable = None,
|
1929
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1637
1930
|
*,
|
1638
1931
|
async_: Literal[True],
|
1639
1932
|
**request_kwargs,
|
@@ -1644,15 +1937,17 @@ class ClientRequestMixin:
|
|
1644
1937
|
payload: int | str | dict,
|
1645
1938
|
/,
|
1646
1939
|
request: None | Callable = None,
|
1940
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1647
1941
|
*,
|
1648
1942
|
async_: Literal[False, True] = False,
|
1649
1943
|
**request_kwargs,
|
1650
1944
|
) -> dict | Coroutine[Any, Any, dict]:
|
1651
|
-
"""
|
1945
|
+
"""获取开放平台的登录二维码,扫码可用,采用 PKCE (Proof Key for Code Exchange)
|
1652
1946
|
|
1653
1947
|
POST https://qrcodeapi.115.com/open/authDeviceCode
|
1654
1948
|
|
1655
1949
|
.. admonition:: Reference
|
1950
|
+
|
1656
1951
|
https://www.yuque.com/115yun/open/shtpzfhewv5nag11#WzRhM
|
1657
1952
|
|
1658
1953
|
.. note::
|
@@ -1674,7 +1969,7 @@ class ClientRequestMixin:
|
|
1674
1969
|
|
1675
1970
|
- code_challenge_method: str = <default> 💡 计算 `code_challenge` 的 hash 算法,支持 "md5", "sha1", "sha256"
|
1676
1971
|
"""
|
1677
|
-
api = "
|
1972
|
+
api = complete_api("/open/authDeviceCode", base_url=base_url)
|
1678
1973
|
if isinstance(payload, (int, str)):
|
1679
1974
|
payload = {
|
1680
1975
|
"client_id": payload,
|
@@ -1687,6 +1982,62 @@ class ClientRequestMixin:
|
|
1687
1982
|
else:
|
1688
1983
|
return request(url=api, method="POST", data=payload, **request_kwargs)
|
1689
1984
|
|
1985
|
+
@overload
|
1986
|
+
@staticmethod
|
1987
|
+
def login_refresh_token_open(
|
1988
|
+
payload: str | dict,
|
1989
|
+
/,
|
1990
|
+
request: None | Callable = None,
|
1991
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1992
|
+
*,
|
1993
|
+
async_: Literal[False] = False,
|
1994
|
+
**request_kwargs,
|
1995
|
+
) -> dict:
|
1996
|
+
...
|
1997
|
+
@overload
|
1998
|
+
@staticmethod
|
1999
|
+
def login_refresh_token_open(
|
2000
|
+
payload: str | dict,
|
2001
|
+
/,
|
2002
|
+
request: None | Callable = None,
|
2003
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
2004
|
+
*,
|
2005
|
+
async_: Literal[True],
|
2006
|
+
**request_kwargs,
|
2007
|
+
) -> Coroutine[Any, Any, dict]:
|
2008
|
+
...
|
2009
|
+
@staticmethod
|
2010
|
+
def login_refresh_token_open(
|
2011
|
+
payload: str | dict,
|
2012
|
+
/,
|
2013
|
+
request: None | Callable = None,
|
2014
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
2015
|
+
*,
|
2016
|
+
async_: Literal[False, True] = False,
|
2017
|
+
**request_kwargs,
|
2018
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
2019
|
+
"""用一个 refresh_token 去获取新的 access_token 和 refresh_token,然后原来的 refresh_token 作废
|
2020
|
+
|
2021
|
+
POST https://qrcodeapi.115.com/open/refreshToken
|
2022
|
+
|
2023
|
+
.. admonition:: Reference
|
2024
|
+
|
2025
|
+
https://www.yuque.com/115yun/open/shtpzfhewv5nag11#ve54x
|
2026
|
+
|
2027
|
+
https://www.yuque.com/115yun/open/opnx8yezo4at2be6
|
2028
|
+
|
2029
|
+
:payload:
|
2030
|
+
- refresh_token: str
|
2031
|
+
"""
|
2032
|
+
api = complete_api("/open/refreshToken", base_url=base_url)
|
2033
|
+
if isinstance(payload, str):
|
2034
|
+
payload = {"refresh_token": payload}
|
2035
|
+
request_kwargs.setdefault("parse", default_parse)
|
2036
|
+
if request is None:
|
2037
|
+
return get_default_request()(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
2038
|
+
else:
|
2039
|
+
return request(url=api, method="POST", data=payload, **request_kwargs)
|
2040
|
+
|
1690
2041
|
@overload
|
1691
2042
|
@classmethod
|
1692
2043
|
def login_with_qrcode(
|
@@ -1694,6 +2045,7 @@ class ClientRequestMixin:
|
|
1694
2045
|
/,
|
1695
2046
|
app: None | str = "",
|
1696
2047
|
console_qrcode: bool = True,
|
2048
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1697
2049
|
*,
|
1698
2050
|
async_: Literal[False] = False,
|
1699
2051
|
**request_kwargs,
|
@@ -1706,6 +2058,7 @@ class ClientRequestMixin:
|
|
1706
2058
|
/,
|
1707
2059
|
app: None | str = "",
|
1708
2060
|
console_qrcode: bool = True,
|
2061
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1709
2062
|
*,
|
1710
2063
|
async_: Literal[True],
|
1711
2064
|
**request_kwargs,
|
@@ -1717,6 +2070,7 @@ class ClientRequestMixin:
|
|
1717
2070
|
/,
|
1718
2071
|
app: None | str = "",
|
1719
2072
|
console_qrcode: bool = True,
|
2073
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1720
2074
|
*,
|
1721
2075
|
async_: Literal[False, True] = False,
|
1722
2076
|
**request_kwargs,
|
@@ -1817,6 +2171,7 @@ class ClientRequestMixin:
|
|
1817
2171
|
def gen_step():
|
1818
2172
|
resp = yield cls.login_qrcode_token(
|
1819
2173
|
async_=async_,
|
2174
|
+
base_url=base_url,
|
1820
2175
|
**request_kwargs,
|
1821
2176
|
)
|
1822
2177
|
qrcode_token = resp["data"]
|
@@ -1830,15 +2185,16 @@ class ClientRequestMixin:
|
|
1830
2185
|
qr.add_data(qrcode)
|
1831
2186
|
qr.print_ascii(tty=isatty(1))
|
1832
2187
|
else:
|
1833
|
-
url = "
|
2188
|
+
url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
|
1834
2189
|
if async_:
|
1835
|
-
yield
|
2190
|
+
yield startfile_async(url)
|
1836
2191
|
else:
|
1837
2192
|
startfile(url)
|
1838
2193
|
while True:
|
1839
2194
|
try:
|
1840
2195
|
resp = yield cls.login_qrcode_scan_status(
|
1841
2196
|
qrcode_token,
|
2197
|
+
base_url=base_url,
|
1842
2198
|
async_=async_,
|
1843
2199
|
**request_kwargs,
|
1844
2200
|
)
|
@@ -1862,12 +2218,13 @@ class ClientRequestMixin:
|
|
1862
2218
|
return cls.login_qrcode_scan_result(
|
1863
2219
|
login_uid,
|
1864
2220
|
app,
|
2221
|
+
base_url=base_url,
|
1865
2222
|
async_=async_,
|
1866
2223
|
**request_kwargs,
|
1867
2224
|
)
|
1868
2225
|
else:
|
1869
2226
|
return qrcode_token
|
1870
|
-
return run_gen_step(gen_step, async_=async_)
|
2227
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
1871
2228
|
|
1872
2229
|
@overload
|
1873
2230
|
@classmethod
|
@@ -1876,6 +2233,7 @@ class ClientRequestMixin:
|
|
1876
2233
|
/,
|
1877
2234
|
app_id: int | str = 100195993,
|
1878
2235
|
console_qrcode: bool = True,
|
2236
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1879
2237
|
*,
|
1880
2238
|
async_: Literal[False] = False,
|
1881
2239
|
**request_kwargs,
|
@@ -1888,6 +2246,7 @@ class ClientRequestMixin:
|
|
1888
2246
|
/,
|
1889
2247
|
app_id: int | str = 100195993,
|
1890
2248
|
console_qrcode: bool = True,
|
2249
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1891
2250
|
*,
|
1892
2251
|
async_: Literal[True],
|
1893
2252
|
**request_kwargs,
|
@@ -1899,6 +2258,7 @@ class ClientRequestMixin:
|
|
1899
2258
|
/,
|
1900
2259
|
app_id: int | str = 100195993,
|
1901
2260
|
console_qrcode: bool = True,
|
2261
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1902
2262
|
*,
|
1903
2263
|
async_: Literal[False, True] = False,
|
1904
2264
|
**request_kwargs,
|
@@ -1914,6 +2274,7 @@ class ClientRequestMixin:
|
|
1914
2274
|
def gen_step():
|
1915
2275
|
resp = yield cls.login_qrcode_token_open(
|
1916
2276
|
app_id,
|
2277
|
+
base_url=base_url,
|
1917
2278
|
async_=async_,
|
1918
2279
|
**request_kwargs,
|
1919
2280
|
)
|
@@ -1928,15 +2289,16 @@ class ClientRequestMixin:
|
|
1928
2289
|
qr.add_data(qrcode)
|
1929
2290
|
qr.print_ascii(tty=isatty(1))
|
1930
2291
|
else:
|
1931
|
-
url = "
|
2292
|
+
url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
|
1932
2293
|
if async_:
|
1933
|
-
yield
|
2294
|
+
yield startfile_async(url)
|
1934
2295
|
else:
|
1935
2296
|
startfile(url)
|
1936
2297
|
while True:
|
1937
2298
|
try:
|
1938
2299
|
resp = yield cls.login_qrcode_scan_status(
|
1939
2300
|
qrcode_token,
|
2301
|
+
base_url=base_url,
|
1940
2302
|
async_=async_,
|
1941
2303
|
**request_kwargs,
|
1942
2304
|
)
|
@@ -1958,10 +2320,13 @@ class ClientRequestMixin:
|
|
1958
2320
|
raise LoginError(errno.EAUTH, f"qrcode: aborted with {resp!r}")
|
1959
2321
|
return cls.login_qrcode_access_token_open(
|
1960
2322
|
login_uid,
|
2323
|
+
base_url=base_url,
|
1961
2324
|
async_=async_,
|
1962
2325
|
**request_kwargs,
|
1963
2326
|
)
|
1964
|
-
return run_gen_step(gen_step, async_=async_)
|
2327
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2328
|
+
|
2329
|
+
########## Upload API ##########
|
1965
2330
|
|
1966
2331
|
upload_endpoint = "http://oss-cn-shenzhen.aliyuncs.com"
|
1967
2332
|
|
@@ -2342,7 +2707,7 @@ class ClientRequestMixin:
|
|
2342
2707
|
async_=async_,
|
2343
2708
|
**request_kwargs,
|
2344
2709
|
)
|
2345
|
-
return run_gen_step(gen_step, async_=async_)
|
2710
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2346
2711
|
|
2347
2712
|
@overload
|
2348
2713
|
def read_bytes_range(
|
@@ -2457,13 +2822,14 @@ class ClientRequestMixin:
|
|
2457
2822
|
async_=async_,
|
2458
2823
|
**request_kwargs,
|
2459
2824
|
)
|
2460
|
-
return run_gen_step(gen_step, async_=async_)
|
2825
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2461
2826
|
|
2462
2827
|
|
2463
2828
|
class P115OpenClient(ClientRequestMixin):
|
2464
2829
|
"""115 的客户端对象
|
2465
2830
|
|
2466
2831
|
.. admonition:: Reference
|
2832
|
+
|
2467
2833
|
https://www.yuque.com/115yun/open
|
2468
2834
|
|
2469
2835
|
:param app_id_or_refresh_token: 申请到的 AppID 或 refresh_token
|
@@ -2534,7 +2900,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2534
2900
|
app_id_or_refresh_token.startswith("0") or
|
2535
2901
|
app_id_or_refresh_token.strip(digits)
|
2536
2902
|
):
|
2537
|
-
resp = yield self.
|
2903
|
+
resp = yield self.login_refresh_token_open(
|
2538
2904
|
app_id_or_refresh_token,
|
2539
2905
|
async_=async_,
|
2540
2906
|
**request_kwargs,
|
@@ -2552,7 +2918,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2552
2918
|
self.refresh_token = data["refresh_token"]
|
2553
2919
|
self.access_token = data["access_token"]
|
2554
2920
|
return self
|
2555
|
-
return run_gen_step(gen_step, async_=async_)
|
2921
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2556
2922
|
|
2557
2923
|
@classmethod
|
2558
2924
|
def from_token(cls, /, access_token: str, refresh_token: str) -> P115OpenClient:
|
@@ -2609,7 +2975,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2609
2975
|
"""更新 access_token 和 refresh_token (⚠️ 目前是 7200 秒内就要求刷新一次)
|
2610
2976
|
"""
|
2611
2977
|
def gen_step():
|
2612
|
-
resp = yield self.
|
2978
|
+
resp = yield self.login_refresh_token_open(
|
2613
2979
|
self.refresh_token,
|
2614
2980
|
async_=async_,
|
2615
2981
|
**request_kwargs,
|
@@ -2619,7 +2985,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2619
2985
|
self.refresh_token = data["refresh_token"]
|
2620
2986
|
access_token = self.access_token = data["access_token"]
|
2621
2987
|
return access_token
|
2622
|
-
return run_gen_step(gen_step, async_=async_)
|
2988
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2623
2989
|
|
2624
2990
|
@overload
|
2625
2991
|
def download_url(
|
@@ -2747,6 +3113,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2747
3113
|
相当于 `P115Client.download_url_app(app="chrome")`
|
2748
3114
|
|
2749
3115
|
.. admonition:: Reference
|
3116
|
+
|
2750
3117
|
https://www.yuque.com/115yun/open/um8whr91bxb5997o
|
2751
3118
|
|
2752
3119
|
:payload:
|
@@ -2810,6 +3177,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2810
3177
|
POST https://proapi.115.com/open/ufile/copy
|
2811
3178
|
|
2812
3179
|
.. admonition:: Reference
|
3180
|
+
|
2813
3181
|
https://www.yuque.com/115yun/open/lvas49ar94n47bbk
|
2814
3182
|
|
2815
3183
|
:payload:
|
@@ -2866,6 +3234,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2866
3234
|
POST https://proapi.115.com/open/ufile/delete
|
2867
3235
|
|
2868
3236
|
.. admonition:: Reference
|
3237
|
+
|
2869
3238
|
https://www.yuque.com/115yun/open/kt04fu8vcchd2fnb
|
2870
3239
|
|
2871
3240
|
:payload:
|
@@ -2909,7 +3278,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2909
3278
|
async_: Literal[False, True] = False,
|
2910
3279
|
**request_kwargs,
|
2911
3280
|
) -> dict | Coroutine[Any, Any, dict]:
|
2912
|
-
"""
|
3281
|
+
"""获取目录中的文件列表和基本信息
|
2913
3282
|
|
2914
3283
|
GET https://proapi.115.com/open/ufile/files
|
2915
3284
|
|
@@ -2917,6 +3286,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2917
3286
|
相当于 `P115Client.fs_files_app`
|
2918
3287
|
|
2919
3288
|
.. admonition:: Reference
|
3289
|
+
|
2920
3290
|
https://www.yuque.com/115yun/open/kz9ft9a7s57ep868
|
2921
3291
|
|
2922
3292
|
:payload:
|
@@ -3036,6 +3406,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3036
3406
|
相当于 `P115Client.fs_category_get_app`
|
3037
3407
|
|
3038
3408
|
.. admonition:: Reference
|
3409
|
+
|
3039
3410
|
https://www.yuque.com/115yun/open/rl8zrhe2nag21dfw
|
3040
3411
|
|
3041
3412
|
:payload:
|
@@ -3085,6 +3456,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3085
3456
|
POST https://proapi.115.com/open/folder/add
|
3086
3457
|
|
3087
3458
|
.. admonition:: Reference
|
3459
|
+
|
3088
3460
|
https://www.yuque.com/115yun/open/qur839kyx9cgxpxi
|
3089
3461
|
|
3090
3462
|
:payload:
|
@@ -3137,6 +3509,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3137
3509
|
POST https://proapi.115.com/open/ufile/move
|
3138
3510
|
|
3139
3511
|
.. admonition:: Reference
|
3512
|
+
|
3140
3513
|
https://www.yuque.com/115yun/open/vc6fhi2mrkenmav2
|
3141
3514
|
|
3142
3515
|
:payload:
|
@@ -3157,9 +3530,663 @@ class P115OpenClient(ClientRequestMixin):
|
|
3157
3530
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3158
3531
|
|
3159
3532
|
@overload
|
3160
|
-
def fs_search(
|
3533
|
+
def fs_search(
|
3534
|
+
self,
|
3535
|
+
payload: str | dict = ".",
|
3536
|
+
/,
|
3537
|
+
base_url: bool | str | Callable[[], str] = False,
|
3538
|
+
*,
|
3539
|
+
async_: Literal[False] = False,
|
3540
|
+
**request_kwargs,
|
3541
|
+
) -> dict:
|
3542
|
+
...
|
3543
|
+
@overload
|
3544
|
+
def fs_search(
|
3545
|
+
self,
|
3546
|
+
payload: str | dict = ".",
|
3547
|
+
/,
|
3548
|
+
base_url: bool | str | Callable[[], str] = False,
|
3549
|
+
*,
|
3550
|
+
async_: Literal[True],
|
3551
|
+
**request_kwargs,
|
3552
|
+
) -> Coroutine[Any, Any, dict]:
|
3553
|
+
...
|
3554
|
+
def fs_search(
|
3555
|
+
self,
|
3556
|
+
payload: str | dict = ".",
|
3557
|
+
/,
|
3558
|
+
base_url: bool | str | Callable[[], str] = False,
|
3559
|
+
*,
|
3560
|
+
async_: Literal[False, True] = False,
|
3561
|
+
**request_kwargs,
|
3562
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3563
|
+
"""搜索文件或目录
|
3564
|
+
|
3565
|
+
GET https://proapi.115.com/open/ufile/search
|
3566
|
+
|
3567
|
+
.. hint::
|
3568
|
+
相当于 `P115Client.fs_search_app2`
|
3569
|
+
|
3570
|
+
.. admonition:: Reference
|
3571
|
+
|
3572
|
+
https://www.yuque.com/115yun/open/ft2yelxzopusus38
|
3573
|
+
|
3574
|
+
:payload:
|
3575
|
+
- aid: int | str = 1 💡 area_id。1:正常文件 7:回收站文件 12:瞬间文件 120:彻底删除文件、简历附件
|
3576
|
+
- asc: 0 | 1 = <default> 💡 是否升序排列
|
3577
|
+
- cid: int | str = 0 💡 目录 id。cid=-1 时,表示不返回列表任何内容
|
3578
|
+
- count_folders: 0 | 1 = <default>
|
3579
|
+
- date: str = <default> 💡 筛选日期
|
3580
|
+
- fc: 0 | 1 = <default> 💡 只显示文件或目录。1:只显示目录 2:只显示文件
|
3581
|
+
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
3582
|
+
- file_label: int | str = <default> 💡 标签 id
|
3583
|
+
- format: str = "json" 💡 输出格式(不用管)
|
3584
|
+
- gte_day: str 💡 搜索结果匹配的开始时间;格式:YYYY-MM-DD
|
3585
|
+
- limit: int = 32 💡 一页大小,意思就是 page_size
|
3586
|
+
- lte_day: str 💡 搜索结果匹配的结束时间;格式:YYYY-MM-DD
|
3587
|
+
- o: str = <default> 💡 用某字段排序
|
3588
|
+
|
3589
|
+
- "file_name": 文件名
|
3590
|
+
- "file_size": 文件大小
|
3591
|
+
- "file_type": 文件种类
|
3592
|
+
- "user_utime": 修改时间
|
3593
|
+
- "user_ptime": 创建时间
|
3594
|
+
- "user_otime": 上一次打开时间
|
3595
|
+
|
3596
|
+
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
3597
|
+
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
3598
|
+
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
3599
|
+
- show_dir: 0 | 1 = 1
|
3600
|
+
- source: str = <default>
|
3601
|
+
- star: 0 | 1 = <default>
|
3602
|
+
- suffix: str = <default>
|
3603
|
+
- type: int = <default> 💡 文件类型
|
3604
|
+
|
3605
|
+
- 0: 全部(仅当前目录)
|
3606
|
+
- 1: 文档
|
3607
|
+
- 2: 图片
|
3608
|
+
- 3: 音频
|
3609
|
+
- 4: 视频
|
3610
|
+
- 5: 压缩包
|
3611
|
+
- 6: 软件/应用
|
3612
|
+
- 7: 书籍
|
3613
|
+
- 99: 仅文件
|
3614
|
+
|
3615
|
+
- version: str = <default> 💡 版本号,比如 3.1
|
3616
|
+
"""
|
3617
|
+
api = complete_proapi("/open/ufile/search", base_url)
|
3618
|
+
if isinstance(payload, str):
|
3619
|
+
payload = {
|
3620
|
+
"aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
|
3621
|
+
"show_dir": 1, "search_value": payload,
|
3622
|
+
}
|
3623
|
+
else:
|
3624
|
+
payload = {
|
3625
|
+
"aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
|
3626
|
+
"show_dir": 1, "search_value": ".", **payload,
|
3627
|
+
}
|
3628
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
3629
|
+
|
3630
|
+
@overload
|
3631
|
+
def fs_star_set(
|
3632
|
+
self,
|
3633
|
+
payload: int | str | Iterable[int | str] | dict,
|
3634
|
+
/,
|
3635
|
+
star: bool = True,
|
3636
|
+
base_url: bool | str | Callable[[], str] = False,
|
3637
|
+
*,
|
3638
|
+
async_: Literal[False] = False,
|
3639
|
+
**request_kwargs,
|
3640
|
+
) -> dict:
|
3641
|
+
...
|
3642
|
+
@overload
|
3643
|
+
def fs_star_set(
|
3644
|
+
self,
|
3645
|
+
payload: int | str | Iterable[int | str] | dict,
|
3646
|
+
/,
|
3647
|
+
star: bool = True,
|
3648
|
+
base_url: bool | str | Callable[[], str] = False,
|
3649
|
+
*,
|
3650
|
+
async_: Literal[True],
|
3651
|
+
**request_kwargs,
|
3652
|
+
) -> Coroutine[Any, Any, dict]:
|
3653
|
+
...
|
3654
|
+
def fs_star_set(
|
3655
|
+
self,
|
3656
|
+
payload: int | str | Iterable[int | str] | dict,
|
3657
|
+
/,
|
3658
|
+
star: bool = True,
|
3659
|
+
base_url: bool | str | Callable[[], str] = False,
|
3660
|
+
*,
|
3661
|
+
async_: Literal[False, True] = False,
|
3662
|
+
**request_kwargs,
|
3663
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3664
|
+
"""为文件或目录设置或取消星标,此接口是对 `fs_update_open` 的封装
|
3665
|
+
|
3666
|
+
.. note::
|
3667
|
+
即使其中任何一个 id 目前已经被删除,也可以操作成功
|
3668
|
+
|
3669
|
+
:payload:
|
3670
|
+
- file_id: int | str 💡 只能传入 1 个
|
3671
|
+
- file_id[0]: int | str 💡 如果有多个,则按顺序给出
|
3672
|
+
- file_id[1]: int | str
|
3673
|
+
- ...
|
3674
|
+
- star: 0 | 1 = 1
|
3675
|
+
"""
|
3676
|
+
api = complete_webapi("/files/star", base_url=base_url)
|
3677
|
+
if isinstance(payload, (int, str)):
|
3678
|
+
payload = {"file_id": payload, "star": int(star)}
|
3679
|
+
elif not isinstance(payload, dict):
|
3680
|
+
payload = {f"file_id[{i}]": id for i, id in enumerate(payload)}
|
3681
|
+
if not payload:
|
3682
|
+
return {"state": False, "message": "no op"}
|
3683
|
+
payload["star"] = int(star)
|
3684
|
+
else:
|
3685
|
+
payload = {"star": int(star), **payload}
|
3686
|
+
return self.fs_update(payload, async_=async_, **request_kwargs)
|
3687
|
+
|
3688
|
+
@overload
|
3689
|
+
def fs_video_history(
|
3690
|
+
self,
|
3691
|
+
payload: str | dict,
|
3692
|
+
/,
|
3693
|
+
base_url: bool | str | Callable[[], str] = False,
|
3694
|
+
*,
|
3695
|
+
async_: Literal[False] = False,
|
3696
|
+
**request_kwargs,
|
3697
|
+
) -> dict:
|
3698
|
+
...
|
3699
|
+
@overload
|
3700
|
+
def fs_video_history(
|
3701
|
+
self,
|
3702
|
+
payload: str | dict,
|
3703
|
+
/,
|
3704
|
+
base_url: bool | str | Callable[[], str] = False,
|
3705
|
+
*,
|
3706
|
+
async_: Literal[True],
|
3707
|
+
**request_kwargs,
|
3708
|
+
) -> Coroutine[Any, Any, dict]:
|
3709
|
+
...
|
3710
|
+
def fs_video_history(
|
3711
|
+
self,
|
3712
|
+
payload: str | dict,
|
3713
|
+
/,
|
3714
|
+
base_url: bool | str | Callable[[], str] = False,
|
3715
|
+
*,
|
3716
|
+
async_: Literal[False, True] = False,
|
3717
|
+
**request_kwargs,
|
3718
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3719
|
+
"""获取视频播放进度
|
3720
|
+
|
3721
|
+
GET https://proapi.115.com/open/video/history
|
3722
|
+
|
3723
|
+
.. admonition:: Reference
|
3724
|
+
|
3725
|
+
https://www.yuque.com/115yun/open/gssqdrsq6vfqigag
|
3726
|
+
|
3727
|
+
:payload:
|
3728
|
+
- pick_code: str 💡 文件提取码
|
3729
|
+
"""
|
3730
|
+
api = complete_proapi("/open/video/history", base_url)
|
3731
|
+
if isinstance(payload, str):
|
3732
|
+
payload = {"pick_code": payload}
|
3733
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
3734
|
+
|
3735
|
+
@overload
|
3736
|
+
def fs_video_history_set(
|
3737
|
+
self,
|
3738
|
+
payload: str | dict,
|
3739
|
+
/,
|
3740
|
+
base_url: bool | str | Callable[[], str] = False,
|
3741
|
+
*,
|
3742
|
+
async_: Literal[False] = False,
|
3743
|
+
**request_kwargs,
|
3744
|
+
) -> dict:
|
3745
|
+
...
|
3746
|
+
@overload
|
3747
|
+
def fs_video_history_set(
|
3748
|
+
self,
|
3749
|
+
payload: str | dict,
|
3750
|
+
/,
|
3751
|
+
base_url: bool | str | Callable[[], str] = False,
|
3752
|
+
*,
|
3753
|
+
async_: Literal[True],
|
3754
|
+
**request_kwargs,
|
3755
|
+
) -> Coroutine[Any, Any, dict]:
|
3756
|
+
...
|
3757
|
+
def fs_video_history_set(
|
3758
|
+
self,
|
3759
|
+
payload: str | dict,
|
3760
|
+
/,
|
3761
|
+
base_url: bool | str | Callable[[], str] = False,
|
3762
|
+
*,
|
3763
|
+
async_: Literal[False, True] = False,
|
3764
|
+
**request_kwargs,
|
3765
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3766
|
+
"""记忆视频播放进度
|
3767
|
+
|
3768
|
+
POST https://proapi.115.com/open/video/history
|
3769
|
+
|
3770
|
+
.. admonition:: Reference
|
3771
|
+
|
3772
|
+
https://www.yuque.com/115yun/open/bshagbxv1gzqglg4
|
3773
|
+
|
3774
|
+
:payload:
|
3775
|
+
- pick_code: str 💡 文件提取码
|
3776
|
+
- time: int = <default> 💡 视频播放进度时长 (单位秒)
|
3777
|
+
- watch_end: int = <default> 💡 视频是否播放播放完毕 0:未完毕 1:完毕
|
3778
|
+
"""
|
3779
|
+
api = complete_proapi("/open/video/history", base_url)
|
3780
|
+
if isinstance(payload, str):
|
3781
|
+
payload = {"pick_code": payload}
|
3782
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3783
|
+
|
3784
|
+
@overload
|
3785
|
+
def fs_video_play(
|
3786
|
+
self,
|
3787
|
+
payload: str | dict,
|
3788
|
+
/,
|
3789
|
+
base_url: bool | str | Callable[[], str] = False,
|
3790
|
+
*,
|
3791
|
+
async_: Literal[False] = False,
|
3792
|
+
**request_kwargs,
|
3793
|
+
) -> dict:
|
3794
|
+
...
|
3795
|
+
@overload
|
3796
|
+
def fs_video_play(
|
3797
|
+
self,
|
3798
|
+
payload: str | dict,
|
3799
|
+
/,
|
3800
|
+
base_url: bool | str | Callable[[], str] = False,
|
3801
|
+
*,
|
3802
|
+
async_: Literal[True],
|
3803
|
+
**request_kwargs,
|
3804
|
+
) -> Coroutine[Any, Any, dict]:
|
3805
|
+
...
|
3806
|
+
def fs_video_play(
|
3807
|
+
self,
|
3808
|
+
payload: str | dict,
|
3809
|
+
/,
|
3810
|
+
base_url: bool | str | Callable[[], str] = False,
|
3811
|
+
*,
|
3812
|
+
async_: Literal[False, True] = False,
|
3813
|
+
**request_kwargs,
|
3814
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3815
|
+
"""获取视频在线播放地址(和视频文件相关数据)
|
3816
|
+
|
3817
|
+
GET https://proapi.115.com/open/video/play
|
3818
|
+
|
3819
|
+
.. admonition:: Reference
|
3820
|
+
|
3821
|
+
https://www.yuque.com/115yun/open/hqglxv3cedi3p9dz
|
3822
|
+
|
3823
|
+
.. hint::
|
3824
|
+
需切换音轨时,在请求返回的播放地址中增加请求参数 `&audio_track=${index}`,值就是接口响应中 `multitrack_list` 中某个成员的索引,从 0 开始计数
|
3825
|
+
|
3826
|
+
:payload:
|
3827
|
+
- pick_code: str 💡 文件提取码
|
3828
|
+
- share_id: int | str = <default> 💡 共享 id,获取共享文件播放地址所需
|
3829
|
+
"""
|
3830
|
+
api = complete_proapi("/open/video/play", base_url)
|
3831
|
+
if isinstance(payload, str):
|
3832
|
+
payload = {"pick_code": payload}
|
3833
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
3834
|
+
|
3835
|
+
@overload
|
3836
|
+
def fs_video_push(
|
3837
|
+
self,
|
3838
|
+
payload: str | dict,
|
3839
|
+
/,
|
3840
|
+
base_url: bool | str | Callable[[], str] = False,
|
3841
|
+
*,
|
3842
|
+
async_: Literal[False] = False,
|
3843
|
+
**request_kwargs,
|
3844
|
+
) -> dict:
|
3845
|
+
...
|
3846
|
+
@overload
|
3847
|
+
def fs_video_push(
|
3848
|
+
self,
|
3849
|
+
payload: str | dict,
|
3850
|
+
/,
|
3851
|
+
base_url: bool | str | Callable[[], str] = False,
|
3852
|
+
*,
|
3853
|
+
async_: Literal[True],
|
3854
|
+
**request_kwargs,
|
3855
|
+
) -> Coroutine[Any, Any, dict]:
|
3856
|
+
...
|
3857
|
+
def fs_video_push(
|
3858
|
+
self,
|
3859
|
+
payload: str | dict,
|
3860
|
+
/,
|
3861
|
+
base_url: bool | str | Callable[[], str] = False,
|
3862
|
+
*,
|
3863
|
+
async_: Literal[False, True] = False,
|
3864
|
+
**request_kwargs,
|
3865
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3866
|
+
"""提交视频转码
|
3867
|
+
|
3868
|
+
POST https://proapi.115.com/open/video/video_push
|
3869
|
+
|
3870
|
+
.. admonition:: Reference
|
3871
|
+
|
3872
|
+
https://www.yuque.com/115yun/open/nxt8r1qcktmg3oan
|
3873
|
+
|
3874
|
+
:payload:
|
3875
|
+
- pick_code: str 💡 文件提取码
|
3876
|
+
- op: str = "vip_push" 💡 提交视频加速转码方式:vip_push:根据;vip 等级加速 pay_push:枫叶加速
|
3877
|
+
"""
|
3878
|
+
api = complete_proapi("/open/video/video_push", base_url)
|
3879
|
+
if isinstance(payload, str):
|
3880
|
+
payload = {"pick_code": payload, "op": "vip_push"}
|
3881
|
+
else:
|
3882
|
+
payload.setdefault("op", "vip_push")
|
3883
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3884
|
+
|
3885
|
+
@overload
|
3886
|
+
def fs_video_subtitle(
|
3887
|
+
self,
|
3888
|
+
payload: str | dict,
|
3889
|
+
/,
|
3890
|
+
base_url: bool | str | Callable[[], str] = False,
|
3891
|
+
*,
|
3892
|
+
async_: Literal[False] = False,
|
3893
|
+
**request_kwargs,
|
3894
|
+
) -> dict:
|
3895
|
+
...
|
3896
|
+
@overload
|
3897
|
+
def fs_video_subtitle(
|
3898
|
+
self,
|
3899
|
+
payload: str | dict,
|
3900
|
+
/,
|
3901
|
+
base_url: bool | str | Callable[[], str] = False,
|
3902
|
+
*,
|
3903
|
+
async_: Literal[True],
|
3904
|
+
**request_kwargs,
|
3905
|
+
) -> Coroutine[Any, Any, dict]:
|
3906
|
+
...
|
3907
|
+
def fs_video_subtitle(
|
3908
|
+
self,
|
3909
|
+
payload: str | dict,
|
3910
|
+
/,
|
3911
|
+
base_url: bool | str | Callable[[], str] = False,
|
3912
|
+
*,
|
3913
|
+
async_: Literal[False, True] = False,
|
3914
|
+
**request_kwargs,
|
3915
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3916
|
+
"""视频字幕列表
|
3917
|
+
|
3918
|
+
GET https://proapi.115.com/open/video/subtitle
|
3919
|
+
|
3920
|
+
.. admonition:: Reference
|
3921
|
+
|
3922
|
+
https://www.yuque.com/115yun/open/nx076h3glapoyh7u
|
3923
|
+
|
3924
|
+
:payload:
|
3925
|
+
- pick_code: str 💡 文件提取码
|
3926
|
+
"""
|
3927
|
+
api = complete_proapi("/open/video/subtitle", base_url)
|
3928
|
+
if isinstance(payload, str):
|
3929
|
+
payload = {"pick_code": payload}
|
3930
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
3931
|
+
|
3932
|
+
@overload
|
3933
|
+
def fs_update(
|
3934
|
+
self,
|
3935
|
+
payload: dict,
|
3936
|
+
/,
|
3937
|
+
base_url: bool | str | Callable[[], str] = False,
|
3938
|
+
*,
|
3939
|
+
async_: Literal[False] = False,
|
3940
|
+
**request_kwargs,
|
3941
|
+
) -> dict:
|
3942
|
+
...
|
3943
|
+
@overload
|
3944
|
+
def fs_update(
|
3945
|
+
self,
|
3946
|
+
payload: dict,
|
3947
|
+
/,
|
3948
|
+
base_url: bool | str | Callable[[], str] = False,
|
3949
|
+
*,
|
3950
|
+
async_: Literal[True],
|
3951
|
+
**request_kwargs,
|
3952
|
+
) -> Coroutine[Any, Any, dict]:
|
3953
|
+
...
|
3954
|
+
def fs_update(
|
3955
|
+
self,
|
3956
|
+
payload: dict,
|
3957
|
+
/,
|
3958
|
+
base_url: bool | str | Callable[[], str] = False,
|
3959
|
+
*,
|
3960
|
+
async_: Literal[False, True] = False,
|
3961
|
+
**request_kwargs,
|
3962
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3963
|
+
"""设置文件或目录(备注、标签等)
|
3964
|
+
|
3965
|
+
POST https://proapi.115.com/open/ufile/update
|
3966
|
+
|
3967
|
+
.. hint::
|
3968
|
+
即使文件已经被删除,也可以操作成功
|
3969
|
+
|
3970
|
+
.. admonition:: Reference
|
3971
|
+
|
3972
|
+
https://www.yuque.com/115yun/open/gyrpw5a0zc4sengm
|
3973
|
+
|
3974
|
+
:payload:
|
3975
|
+
- file_id: int | str 💡 只能传入 1 个
|
3976
|
+
- file_id[0]: int | str 💡 如果有多个,则按顺序给出
|
3977
|
+
- file_id[1]: int | str
|
3978
|
+
- ...
|
3979
|
+
- file_name: str = <default> 💡 文件名
|
3980
|
+
- star: 0 | 1 = <default> 💡 是否星标:0:取消星标 1:设置星标
|
3981
|
+
- ...
|
3982
|
+
"""
|
3983
|
+
api = complete_proapi("/open/ufile/update", base_url)
|
3984
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3985
|
+
|
3986
|
+
@overload
|
3987
|
+
def offline_add_torrent(
|
3988
|
+
self,
|
3989
|
+
payload: dict,
|
3990
|
+
/,
|
3991
|
+
base_url: bool | str | Callable[[], str] = False,
|
3992
|
+
*,
|
3993
|
+
async_: Literal[False] = False,
|
3994
|
+
**request_kwargs,
|
3995
|
+
) -> dict:
|
3996
|
+
...
|
3997
|
+
@overload
|
3998
|
+
def offline_add_torrent(
|
3999
|
+
self,
|
4000
|
+
payload: dict,
|
4001
|
+
/,
|
4002
|
+
base_url: bool | str | Callable[[], str] = False,
|
4003
|
+
*,
|
4004
|
+
async_: Literal[True],
|
4005
|
+
**request_kwargs,
|
4006
|
+
) -> Coroutine[Any, Any, dict]:
|
4007
|
+
...
|
4008
|
+
def offline_add_torrent(
|
4009
|
+
self,
|
4010
|
+
payload: dict,
|
4011
|
+
/,
|
4012
|
+
base_url: bool | str | Callable[[], str] = False,
|
4013
|
+
*,
|
4014
|
+
async_: Literal[False, True] = False,
|
4015
|
+
**request_kwargs,
|
4016
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
4017
|
+
"""添加云下载 BT 任务
|
4018
|
+
|
4019
|
+
POST https://proapi.115.com/open/offline/add_task_bt
|
4020
|
+
|
4021
|
+
.. admonition:: Reference
|
4022
|
+
|
4023
|
+
https://www.yuque.com/115yun/open/svfe4unlhayvluly
|
4024
|
+
|
4025
|
+
:payload:
|
4026
|
+
- info_hash: str 💡 种子文件的 info_hash
|
4027
|
+
- pick_code: str 💡 种子文件的提取码
|
4028
|
+
- save_path: str 💡 保存到 `wp_path_id` 对应目录下的相对路径
|
4029
|
+
- torrent_sha1: str 💡 种子文件的 sha1
|
4030
|
+
- wanted: str 💡 选择文件进行下载(是数字索引,从 0 开始计数,用 "," 分隔)
|
4031
|
+
- wp_path_id: int | str = <default> 💡 保存目标文件夹 id
|
4032
|
+
"""
|
4033
|
+
api = complete_proapi("/open/offline/add_task_bt ", base_url)
|
4034
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
4035
|
+
|
4036
|
+
@overload
|
4037
|
+
def offline_add_urls(
|
4038
|
+
self,
|
4039
|
+
payload: str | Iterable[str] | dict,
|
4040
|
+
/,
|
4041
|
+
base_url: bool | str | Callable[[], str] = False,
|
4042
|
+
*,
|
4043
|
+
async_: Literal[False] = False,
|
4044
|
+
**request_kwargs,
|
4045
|
+
) -> dict:
|
4046
|
+
...
|
4047
|
+
@overload
|
4048
|
+
def offline_add_urls(
|
4049
|
+
self,
|
4050
|
+
payload: str | Iterable[str] | dict,
|
4051
|
+
/,
|
4052
|
+
base_url: bool | str | Callable[[], str] = False,
|
4053
|
+
*,
|
4054
|
+
async_: Literal[True],
|
4055
|
+
**request_kwargs,
|
4056
|
+
) -> Coroutine[Any, Any, dict]:
|
4057
|
+
...
|
4058
|
+
def offline_add_urls(
|
4059
|
+
self,
|
4060
|
+
payload: str | Iterable[str] | dict,
|
4061
|
+
/,
|
4062
|
+
base_url: bool | str | Callable[[], str] = False,
|
4063
|
+
*,
|
4064
|
+
async_: Literal[False, True] = False,
|
4065
|
+
**request_kwargs,
|
4066
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
4067
|
+
"""添加云下载链接任务
|
4068
|
+
|
4069
|
+
POST https://proapi.115.com/open/offline/add_task_urls
|
4070
|
+
|
4071
|
+
.. admonition:: Reference
|
4072
|
+
|
4073
|
+
https://www.yuque.com/115yun/open/zkyfq2499gdn3mty
|
4074
|
+
|
4075
|
+
:payload:
|
4076
|
+
- urls: str 💡 链接,用 "\\n" 分隔,支持HTTP、HTTPS、FTP、磁力链和电驴链接
|
4077
|
+
- wp_path_id: int | str = <default> 💡 保存到目录的 id
|
4078
|
+
"""
|
4079
|
+
api = complete_proapi("/open/offline/add_task_urls", base_url)
|
4080
|
+
if isinstance(payload, str):
|
4081
|
+
payload = {"urls": payload.strip("\n")}
|
4082
|
+
elif not isinstance(payload, dict):
|
4083
|
+
payload = {"urls": ",".join(payload)}
|
4084
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
4085
|
+
|
4086
|
+
@overload
|
4087
|
+
def offline_clear(
|
4088
|
+
self,
|
4089
|
+
payload: int | dict = 0,
|
4090
|
+
/,
|
4091
|
+
base_url: bool | str | Callable[[], str] = False,
|
4092
|
+
*,
|
4093
|
+
async_: Literal[False] = False,
|
4094
|
+
**request_kwargs,
|
4095
|
+
) -> dict:
|
4096
|
+
...
|
4097
|
+
@overload
|
4098
|
+
def offline_clear(
|
4099
|
+
self,
|
4100
|
+
payload: int | dict = 0,
|
4101
|
+
/,
|
4102
|
+
base_url: bool | str | Callable[[], str] = False,
|
4103
|
+
*,
|
4104
|
+
async_: Literal[True],
|
4105
|
+
**request_kwargs,
|
4106
|
+
) -> Coroutine[Any, Any, dict]:
|
4107
|
+
...
|
4108
|
+
def offline_clear(
|
4109
|
+
self,
|
4110
|
+
payload: int | dict = 0,
|
4111
|
+
/,
|
4112
|
+
base_url: bool | str | Callable[[], str] = False,
|
4113
|
+
*,
|
4114
|
+
async_: Literal[False, True] = False,
|
4115
|
+
**request_kwargs,
|
4116
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
4117
|
+
"""清空云下载任务
|
4118
|
+
|
4119
|
+
POST https://proapi.115.com/open/offline/clear_task
|
4120
|
+
|
4121
|
+
.. admonition:: Reference
|
4122
|
+
|
4123
|
+
https://www.yuque.com/115yun/open/uu5i4urb5ylqwfy4
|
4124
|
+
|
4125
|
+
:payload:
|
4126
|
+
- flag: int = 0 💡 标识,用于对应某种情况
|
4127
|
+
|
4128
|
+
- 0: 已完成
|
4129
|
+
- 1: 全部
|
4130
|
+
- 2: 已失败
|
4131
|
+
- 3: 进行中
|
4132
|
+
- 4: 已完成+删除源文件
|
4133
|
+
- 5: 全部+删除源文件
|
4134
|
+
"""
|
4135
|
+
api = complete_proapi("/open/offline/clear_task", base_url)
|
4136
|
+
if isinstance(payload, int):
|
4137
|
+
payload = {"flag": payload}
|
4138
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
4139
|
+
|
4140
|
+
@overload
|
4141
|
+
def offline_list(
|
4142
|
+
self,
|
4143
|
+
payload: int | dict = 1,
|
4144
|
+
/,
|
4145
|
+
base_url: bool | str | Callable[[], str] = False,
|
4146
|
+
*,
|
4147
|
+
async_: Literal[False] = False,
|
4148
|
+
**request_kwargs,
|
4149
|
+
) -> dict:
|
4150
|
+
...
|
4151
|
+
@overload
|
4152
|
+
def offline_list(
|
4153
|
+
self,
|
4154
|
+
payload: int | dict = 1,
|
4155
|
+
/,
|
4156
|
+
base_url: bool | str | Callable[[], str] = False,
|
4157
|
+
*,
|
4158
|
+
async_: Literal[True],
|
4159
|
+
**request_kwargs,
|
4160
|
+
) -> Coroutine[Any, Any, dict]:
|
4161
|
+
...
|
4162
|
+
def offline_list(
|
4163
|
+
self,
|
4164
|
+
payload: int | dict = 1,
|
4165
|
+
/,
|
4166
|
+
base_url: bool | str | Callable[[], str] = False,
|
4167
|
+
*,
|
4168
|
+
async_: Literal[False, True] = False,
|
4169
|
+
**request_kwargs,
|
4170
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
4171
|
+
"""获取用户云下载任务列表
|
4172
|
+
|
4173
|
+
GET https://proapi.115.com/open/offline/get_task_list
|
4174
|
+
|
4175
|
+
.. admonition:: Reference
|
4176
|
+
|
4177
|
+
https://www.yuque.com/115yun/open/av2mluz7uwigz74k
|
4178
|
+
|
4179
|
+
:payload:
|
4180
|
+
- page: int | str = 1
|
4181
|
+
"""
|
4182
|
+
api = complete_proapi("/open/offline/get_task_list", base_url)
|
4183
|
+
if isinstance(payload, int):
|
4184
|
+
payload = {"page": payload}
|
4185
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
4186
|
+
|
4187
|
+
@overload
|
4188
|
+
def offline_quota_info(
|
3161
4189
|
self,
|
3162
|
-
payload: str | dict = ".",
|
3163
4190
|
/,
|
3164
4191
|
base_url: bool | str | Callable[[], str] = False,
|
3165
4192
|
*,
|
@@ -3168,9 +4195,8 @@ class P115OpenClient(ClientRequestMixin):
|
|
3168
4195
|
) -> dict:
|
3169
4196
|
...
|
3170
4197
|
@overload
|
3171
|
-
def
|
4198
|
+
def offline_quota_info(
|
3172
4199
|
self,
|
3173
|
-
payload: str | dict = ".",
|
3174
4200
|
/,
|
3175
4201
|
base_url: bool | str | Callable[[], str] = False,
|
3176
4202
|
*,
|
@@ -3178,87 +4204,30 @@ class P115OpenClient(ClientRequestMixin):
|
|
3178
4204
|
**request_kwargs,
|
3179
4205
|
) -> Coroutine[Any, Any, dict]:
|
3180
4206
|
...
|
3181
|
-
def
|
4207
|
+
def offline_quota_info(
|
3182
4208
|
self,
|
3183
|
-
payload: str | dict = ".",
|
3184
4209
|
/,
|
3185
4210
|
base_url: bool | str | Callable[[], str] = False,
|
3186
4211
|
*,
|
3187
4212
|
async_: Literal[False, True] = False,
|
3188
4213
|
**request_kwargs,
|
3189
4214
|
) -> dict | Coroutine[Any, Any, dict]:
|
3190
|
-
"""
|
3191
|
-
|
3192
|
-
GET https://proapi.115.com/open/ufile/search
|
4215
|
+
"""获取云下载配额信息
|
3193
4216
|
|
3194
|
-
|
3195
|
-
相当于 `P115Client.fs_search_app2`
|
4217
|
+
GET https://proapi.115.com/open/offline/get_quota_info
|
3196
4218
|
|
3197
4219
|
.. admonition:: Reference
|
3198
|
-
https://www.yuque.com/115yun/open/ft2yelxzopusus38
|
3199
|
-
|
3200
|
-
:payload:
|
3201
|
-
- aid: int | str = 1 💡 area_id。1:正常文件 7:回收站文件 12:瞬间文件 120:彻底删除文件、简历附件
|
3202
|
-
- asc: 0 | 1 = <default> 💡 是否升序排列
|
3203
|
-
- cid: int | str = 0 💡 目录 id。cid=-1 时,表示不返回列表任何内容
|
3204
|
-
- count_folders: 0 | 1 = <default>
|
3205
|
-
- date: str = <default> 💡 筛选日期
|
3206
|
-
- fc: 0 | 1 = <default> 💡 只显示文件或目录。1:只显示目录 2:只显示文件
|
3207
|
-
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
3208
|
-
- file_label: int | str = <default> 💡 标签 id
|
3209
|
-
- format: str = "json" 💡 输出格式(不用管)
|
3210
|
-
- gte_day: str 💡 搜索结果匹配的开始时间;格式:YYYY-MM-DD
|
3211
|
-
- limit: int = 32 💡 一页大小,意思就是 page_size
|
3212
|
-
- lte_day: str 💡 搜索结果匹配的结束时间;格式:YYYY-MM-DD
|
3213
|
-
- o: str = <default> 💡 用某字段排序
|
3214
|
-
|
3215
|
-
- "file_name": 文件名
|
3216
|
-
- "file_size": 文件大小
|
3217
|
-
- "file_type": 文件种类
|
3218
|
-
- "user_utime": 修改时间
|
3219
|
-
- "user_ptime": 创建时间
|
3220
|
-
- "user_otime": 上一次打开时间
|
3221
|
-
|
3222
|
-
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
3223
|
-
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
3224
|
-
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
3225
|
-
- show_dir: 0 | 1 = 1
|
3226
|
-
- source: str = <default>
|
3227
|
-
- star: 0 | 1 = <default>
|
3228
|
-
- suffix: str = <default>
|
3229
|
-
- type: int = <default> 💡 文件类型
|
3230
|
-
|
3231
|
-
- 0: 全部(仅当前目录)
|
3232
|
-
- 1: 文档
|
3233
|
-
- 2: 图片
|
3234
|
-
- 3: 音频
|
3235
|
-
- 4: 视频
|
3236
|
-
- 5: 压缩包
|
3237
|
-
- 6: 软件/应用
|
3238
|
-
- 7: 书籍
|
3239
|
-
- 99: 仅文件
|
3240
4220
|
|
3241
|
-
|
4221
|
+
https://www.yuque.com/115yun/open/gif2n3smh54kyg0p
|
3242
4222
|
"""
|
3243
|
-
api = complete_proapi("/open/
|
3244
|
-
|
3245
|
-
payload = {
|
3246
|
-
"aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
|
3247
|
-
"show_dir": 1, "search_value": payload,
|
3248
|
-
}
|
3249
|
-
else:
|
3250
|
-
payload = {
|
3251
|
-
"aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
|
3252
|
-
"show_dir": 1, "search_value": ".", **payload,
|
3253
|
-
}
|
3254
|
-
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
4223
|
+
api = complete_proapi("/open/offline/get_quota_info", base_url)
|
4224
|
+
return self.request(url=api, async_=async_, **request_kwargs)
|
3255
4225
|
|
3256
4226
|
@overload
|
3257
|
-
def
|
4227
|
+
def offline_remove(
|
3258
4228
|
self,
|
3259
|
-
payload:
|
4229
|
+
payload: str | dict,
|
3260
4230
|
/,
|
3261
|
-
star: bool = True,
|
3262
4231
|
base_url: bool | str | Callable[[], str] = False,
|
3263
4232
|
*,
|
3264
4233
|
async_: Literal[False] = False,
|
@@ -3266,53 +4235,44 @@ class P115OpenClient(ClientRequestMixin):
|
|
3266
4235
|
) -> dict:
|
3267
4236
|
...
|
3268
4237
|
@overload
|
3269
|
-
def
|
4238
|
+
def offline_remove(
|
3270
4239
|
self,
|
3271
|
-
payload:
|
4240
|
+
payload: str | dict,
|
3272
4241
|
/,
|
3273
|
-
star: bool = True,
|
3274
4242
|
base_url: bool | str | Callable[[], str] = False,
|
3275
4243
|
*,
|
3276
4244
|
async_: Literal[True],
|
3277
4245
|
**request_kwargs,
|
3278
4246
|
) -> Coroutine[Any, Any, dict]:
|
3279
4247
|
...
|
3280
|
-
def
|
4248
|
+
def offline_remove(
|
3281
4249
|
self,
|
3282
|
-
payload:
|
4250
|
+
payload: str | dict,
|
3283
4251
|
/,
|
3284
|
-
star: bool = True,
|
3285
4252
|
base_url: bool | str | Callable[[], str] = False,
|
3286
4253
|
*,
|
3287
4254
|
async_: Literal[False, True] = False,
|
3288
4255
|
**request_kwargs,
|
3289
4256
|
) -> dict | Coroutine[Any, Any, dict]:
|
3290
|
-
"""
|
4257
|
+
"""删除用户云下载任务
|
3291
4258
|
|
3292
|
-
|
3293
|
-
|
4259
|
+
POST https://proapi.115.com/open/offline/del_task
|
4260
|
+
|
4261
|
+
.. admonition:: Reference
|
4262
|
+
|
4263
|
+
https://www.yuque.com/115yun/open/pmgwc86lpcy238nw
|
3294
4264
|
|
3295
4265
|
:payload:
|
3296
|
-
-
|
3297
|
-
-
|
3298
|
-
- file_id[1]: int | str
|
3299
|
-
- ...
|
3300
|
-
- star: 0 | 1 = 1
|
4266
|
+
- info_hash: str 💡 待删除任务的 info_hash
|
4267
|
+
- del_source_file: 0 | 1 = <default> 💡 是否删除源文件 1:删除 0:不删除
|
3301
4268
|
"""
|
3302
|
-
api =
|
3303
|
-
if isinstance(payload,
|
3304
|
-
payload = {"
|
3305
|
-
|
3306
|
-
payload = {f"file_id[{i}]": id for i, id in enumerate(payload)}
|
3307
|
-
if not payload:
|
3308
|
-
return {"state": False, "message": "no op"}
|
3309
|
-
payload["star"] = int(star)
|
3310
|
-
else:
|
3311
|
-
payload = {"star": int(star), **payload}
|
3312
|
-
return self.fs_update(payload, async_=async_, **request_kwargs)
|
4269
|
+
api = complete_proapi("/open/offline/del_task", base_url)
|
4270
|
+
if isinstance(payload, str):
|
4271
|
+
payload = {"info_hash": payload}
|
4272
|
+
return self.request(api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3313
4273
|
|
3314
4274
|
@overload
|
3315
|
-
def
|
4275
|
+
def offline_torrent_info(
|
3316
4276
|
self,
|
3317
4277
|
payload: dict,
|
3318
4278
|
/,
|
@@ -3323,7 +4283,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3323
4283
|
) -> dict:
|
3324
4284
|
...
|
3325
4285
|
@overload
|
3326
|
-
def
|
4286
|
+
def offline_torrent_info(
|
3327
4287
|
self,
|
3328
4288
|
payload: dict,
|
3329
4289
|
/,
|
@@ -3333,7 +4293,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3333
4293
|
**request_kwargs,
|
3334
4294
|
) -> Coroutine[Any, Any, dict]:
|
3335
4295
|
...
|
3336
|
-
def
|
4296
|
+
def offline_torrent_info(
|
3337
4297
|
self,
|
3338
4298
|
payload: dict,
|
3339
4299
|
/,
|
@@ -3342,26 +4302,19 @@ class P115OpenClient(ClientRequestMixin):
|
|
3342
4302
|
async_: Literal[False, True] = False,
|
3343
4303
|
**request_kwargs,
|
3344
4304
|
) -> dict | Coroutine[Any, Any, dict]:
|
3345
|
-
"""
|
3346
|
-
|
3347
|
-
POST https://proapi.115.com/open/ufile/update
|
4305
|
+
"""解析 BT 种子
|
3348
4306
|
|
3349
|
-
|
3350
|
-
即使文件已经被删除,也可以操作成功
|
4307
|
+
POST https://proapi.115.com/open/offline/torrent
|
3351
4308
|
|
3352
4309
|
.. admonition:: Reference
|
3353
|
-
|
4310
|
+
|
4311
|
+
https://www.yuque.com/115yun/open/evez3u50cemoict1
|
3354
4312
|
|
3355
4313
|
:payload:
|
3356
|
-
-
|
3357
|
-
-
|
3358
|
-
- file_id[1]: int | str
|
3359
|
-
- ...
|
3360
|
-
- file_name: str = <default> 💡 文件名
|
3361
|
-
- star: 0 | 1 = <default> 💡 是否星标:0:取消星标 1:设置星标
|
3362
|
-
- ...
|
4314
|
+
- torrent_sha1: str 💡 种子文件的 sha1
|
4315
|
+
- pick_code: str 💡 种子文件的提取码
|
3363
4316
|
"""
|
3364
|
-
api = complete_proapi("/open/
|
4317
|
+
api = complete_proapi("/open/offline/torrent", base_url)
|
3365
4318
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3366
4319
|
|
3367
4320
|
@overload
|
@@ -3399,7 +4352,8 @@ class P115OpenClient(ClientRequestMixin):
|
|
3399
4352
|
|
3400
4353
|
POST https://proapi.115.com/open/rb/del
|
3401
4354
|
|
3402
|
-
..
|
4355
|
+
.. admonition:: Reference
|
4356
|
+
|
3403
4357
|
https://www.yuque.com/115yun/open/gwtof85nmboulrce
|
3404
4358
|
|
3405
4359
|
:payload:
|
@@ -3448,6 +4402,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3448
4402
|
GET https://proapi.115.com/open/rb/list
|
3449
4403
|
|
3450
4404
|
.. admonition:: Reference
|
4405
|
+
|
3451
4406
|
https://www.yuque.com/115yun/open/bg7l4328t98fwgex
|
3452
4407
|
|
3453
4408
|
:payload:
|
@@ -3497,6 +4452,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3497
4452
|
POST https://proapi.115.com/open/rb/revert
|
3498
4453
|
|
3499
4454
|
.. admonition:: Reference
|
4455
|
+
|
3500
4456
|
https://www.yuque.com/115yun/open/gq293z80a3kmxbaq
|
3501
4457
|
|
3502
4458
|
:payload:
|
@@ -3542,6 +4498,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3542
4498
|
GET https://proapi.115.com/open/upload/get_token
|
3543
4499
|
|
3544
4500
|
.. admonition:: Reference
|
4501
|
+
|
3545
4502
|
https://www.yuque.com/115yun/open/kzacvzl0g7aiyyn4
|
3546
4503
|
"""
|
3547
4504
|
api = complete_proapi("/open/upload/get_token", base_url)
|
@@ -3583,6 +4540,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3583
4540
|
POST https://proapi.115.com/open/upload/init
|
3584
4541
|
|
3585
4542
|
.. admonition:: Reference
|
4543
|
+
|
3586
4544
|
https://www.yuque.com/115yun/open/ul4mrauo5i2uza0q
|
3587
4545
|
|
3588
4546
|
:payload:
|
@@ -3641,6 +4599,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3641
4599
|
POST https://proapi.115.com/open/upload/resume
|
3642
4600
|
|
3643
4601
|
.. admonition:: Reference
|
4602
|
+
|
3644
4603
|
https://www.yuque.com/115yun/open/tzvi9sbcg59msddz
|
3645
4604
|
|
3646
4605
|
:payload:
|
@@ -3752,7 +4711,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3752
4711
|
check_response(resp)
|
3753
4712
|
resp["data"] = {**payload, **resp["data"], "sha1": filesha1, "cid": pid}
|
3754
4713
|
return resp
|
3755
|
-
return run_gen_step(gen_step, async_=async_)
|
4714
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
3756
4715
|
|
3757
4716
|
@overload
|
3758
4717
|
def upload_file(
|
@@ -4096,7 +5055,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
4096
5055
|
async_=async_, # type: ignore
|
4097
5056
|
**request_kwargs,
|
4098
5057
|
)
|
4099
|
-
return run_gen_step(gen_step, async_=async_)
|
5058
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4100
5059
|
|
4101
5060
|
@overload
|
4102
5061
|
def user_info(
|
@@ -4131,6 +5090,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
4131
5090
|
GET https://proapi.115.com/open/user/info
|
4132
5091
|
|
4133
5092
|
.. admonition:: Reference
|
5093
|
+
|
4134
5094
|
https://www.yuque.com/115yun/open/ot1litggzxa1czww
|
4135
5095
|
"""
|
4136
5096
|
api = complete_proapi("/open/user/info", base_url)
|
@@ -4146,7 +5106,19 @@ class P115OpenClient(ClientRequestMixin):
|
|
4146
5106
|
fs_move_open = fs_move
|
4147
5107
|
fs_search_open = fs_search
|
4148
5108
|
fs_star_set_open = fs_star_set
|
5109
|
+
fs_video_history_open = fs_video_history
|
5110
|
+
fs_video_history_set_open = fs_video_history_set
|
5111
|
+
fs_video_play_open = fs_video_play
|
5112
|
+
fs_video_push_open = fs_video_push
|
5113
|
+
fs_video_subtitle_open = fs_video_subtitle
|
4149
5114
|
fs_update_open = fs_update
|
5115
|
+
offline_add_torrent_open = offline_add_torrent
|
5116
|
+
offline_add_urls_open = offline_add_urls
|
5117
|
+
offline_clear_open = offline_clear
|
5118
|
+
offline_list_open = offline_list
|
5119
|
+
offline_quota_info_open = offline_quota_info
|
5120
|
+
offline_remove_open = offline_remove
|
5121
|
+
offline_torrent_info_open = offline_torrent_info
|
4150
5122
|
recyclebin_clean_open = recyclebin_clean
|
4151
5123
|
recyclebin_list_open = recyclebin_list
|
4152
5124
|
recyclebin_revert_open = recyclebin_revert
|
@@ -4464,7 +5436,7 @@ class P115Client(P115OpenClient):
|
|
4464
5436
|
)
|
4465
5437
|
setattr(self, "check_for_relogin", check_for_relogin)
|
4466
5438
|
return self
|
4467
|
-
return run_gen_step(gen_step, async_=async_)
|
5439
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4468
5440
|
|
4469
5441
|
@locked_cacheproperty
|
4470
5442
|
def request_lock(self, /) -> Lock:
|
@@ -4601,118 +5573,42 @@ class P115Client(P115OpenClient):
|
|
4601
5573
|
| 20 | P2 | mac | 115生活(macOS端) |
|
4602
5574
|
+-------+----------+------------+-------------------------+
|
4603
5575
|
| 21 | P3 | linux | 115生活(Linux端) |
|
4604
|
-
+-------+----------+------------+-------------------------+
|
4605
|
-
| 22 | R1 | wechatmini | 115生活(微信小程序) |
|
4606
|
-
+-------+----------+------------+-------------------------+
|
4607
|
-
| 23 | R2 | alipaymini | 115生活(支付宝小程序) |
|
4608
|
-
+-------+----------+------------+-------------------------+
|
4609
|
-
| 24 | S1 | harmony | 115(Harmony端) |
|
4610
|
-
+-------+----------+------------+-------------------------+
|
4611
|
-
"""
|
4612
|
-
def gen_step():
|
4613
|
-
nonlocal app
|
4614
|
-
status = yield self.login_status(async_=async_, **request_kwargs)
|
4615
|
-
if status:
|
4616
|
-
return self
|
4617
|
-
if not app:
|
4618
|
-
app = yield self.login_app(async_=async_, **request_kwargs)
|
4619
|
-
if not app:
|
4620
|
-
app = "alipaymini"
|
4621
|
-
resp = yield self.login_with_qrcode(
|
4622
|
-
app,
|
4623
|
-
console_qrcode=console_qrcode,
|
4624
|
-
async_=async_,
|
4625
|
-
**request_kwargs,
|
4626
|
-
)
|
4627
|
-
try:
|
4628
|
-
check_response(resp)
|
4629
|
-
except AuthenticationError:
|
4630
|
-
resp = yield self.login_with_qrcode(
|
4631
|
-
app,
|
4632
|
-
console_qrcode=console_qrcode,
|
4633
|
-
async_=async_,
|
4634
|
-
**request_kwargs,
|
4635
|
-
)
|
4636
|
-
check_response(resp)
|
4637
|
-
setattr(self, "cookies", resp["data"]["cookie"])
|
4638
|
-
return self
|
4639
|
-
return run_gen_step(gen_step, async_=async_)
|
4640
|
-
|
4641
|
-
@overload
|
4642
|
-
def login_qrcode_scan(
|
4643
|
-
self,
|
4644
|
-
payload: str | dict,
|
4645
|
-
/,
|
4646
|
-
async_: Literal[False] = False,
|
4647
|
-
**request_kwargs,
|
4648
|
-
) -> dict:
|
4649
|
-
...
|
4650
|
-
@overload
|
4651
|
-
def login_qrcode_scan(
|
4652
|
-
self,
|
4653
|
-
payload: str | dict,
|
4654
|
-
/,
|
4655
|
-
async_: Literal[True],
|
4656
|
-
**request_kwargs,
|
4657
|
-
) -> Coroutine[Any, Any, dict]:
|
4658
|
-
...
|
4659
|
-
def login_qrcode_scan(
|
4660
|
-
self,
|
4661
|
-
payload: str | dict,
|
4662
|
-
/,
|
4663
|
-
async_: Literal[False, True] = False,
|
4664
|
-
**request_kwargs,
|
4665
|
-
) -> dict | Coroutine[Any, Any, dict]:
|
4666
|
-
"""扫描二维码,payload 数据取自 `login_qrcode_token` 接口响应
|
4667
|
-
|
4668
|
-
GET https://qrcodeapi.115.com/api/2.0/prompt.php
|
4669
|
-
|
4670
|
-
:payload:
|
4671
|
-
- uid: str
|
4672
|
-
"""
|
4673
|
-
api = "https://qrcodeapi.115.com/api/2.0/prompt.php"
|
4674
|
-
if isinstance(payload, str):
|
4675
|
-
payload = {"uid": payload}
|
4676
|
-
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
4677
|
-
|
4678
|
-
@overload
|
4679
|
-
def login_qrcode_scan_confirm(
|
4680
|
-
self,
|
4681
|
-
payload: str | dict,
|
4682
|
-
/,
|
4683
|
-
async_: Literal[False] = False,
|
4684
|
-
**request_kwargs,
|
4685
|
-
) -> dict:
|
4686
|
-
...
|
4687
|
-
@overload
|
4688
|
-
def login_qrcode_scan_confirm(
|
4689
|
-
self,
|
4690
|
-
payload: str | dict,
|
4691
|
-
/,
|
4692
|
-
async_: Literal[True],
|
4693
|
-
**request_kwargs,
|
4694
|
-
) -> Coroutine[Any, Any, dict]:
|
4695
|
-
...
|
4696
|
-
def login_qrcode_scan_confirm(
|
4697
|
-
self,
|
4698
|
-
payload: str | dict,
|
4699
|
-
/,
|
4700
|
-
async_: Literal[False, True] = False,
|
4701
|
-
**request_kwargs,
|
4702
|
-
) -> dict | Coroutine[Any, Any, dict]:
|
4703
|
-
"""确认扫描二维码,payload 数据取自 `login_qrcode_scan` 接口响应
|
4704
|
-
|
4705
|
-
GET https://hnqrcodeapi.115.com/api/2.0/slogin.php
|
4706
|
-
|
4707
|
-
:payload:
|
4708
|
-
- key: str
|
4709
|
-
- uid: str
|
4710
|
-
- client: int = 0
|
5576
|
+
+-------+----------+------------+-------------------------+
|
5577
|
+
| 22 | R1 | wechatmini | 115生活(微信小程序) |
|
5578
|
+
+-------+----------+------------+-------------------------+
|
5579
|
+
| 23 | R2 | alipaymini | 115生活(支付宝小程序) |
|
5580
|
+
+-------+----------+------------+-------------------------+
|
5581
|
+
| 24 | S1 | harmony | 115(Harmony端) |
|
5582
|
+
+-------+----------+------------+-------------------------+
|
4711
5583
|
"""
|
4712
|
-
|
4713
|
-
|
4714
|
-
|
4715
|
-
|
5584
|
+
def gen_step():
|
5585
|
+
nonlocal app
|
5586
|
+
status = yield self.login_status(async_=async_, **request_kwargs)
|
5587
|
+
if status:
|
5588
|
+
return self
|
5589
|
+
if not app:
|
5590
|
+
app = yield self.login_app(async_=async_, **request_kwargs)
|
5591
|
+
if not app:
|
5592
|
+
app = "alipaymini"
|
5593
|
+
resp = yield self.login_with_qrcode(
|
5594
|
+
app,
|
5595
|
+
console_qrcode=console_qrcode,
|
5596
|
+
async_=async_,
|
5597
|
+
**request_kwargs,
|
5598
|
+
)
|
5599
|
+
try:
|
5600
|
+
check_response(resp)
|
5601
|
+
except AuthenticationError:
|
5602
|
+
resp = yield self.login_with_qrcode(
|
5603
|
+
app,
|
5604
|
+
console_qrcode=console_qrcode,
|
5605
|
+
async_=async_,
|
5606
|
+
**request_kwargs,
|
5607
|
+
)
|
5608
|
+
check_response(resp)
|
5609
|
+
setattr(self, "cookies", resp["data"]["cookie"])
|
5610
|
+
return self
|
5611
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4716
5612
|
|
4717
5613
|
@overload
|
4718
5614
|
def login_with_app(
|
@@ -4844,7 +5740,7 @@ class P115Client(P115OpenClient):
|
|
4844
5740
|
async_=async_,
|
4845
5741
|
**request_kwargs,
|
4846
5742
|
)
|
4847
|
-
return run_gen_step(gen_step, async_=async_)
|
5743
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4848
5744
|
|
4849
5745
|
@overload
|
4850
5746
|
def login_without_app(
|
@@ -4902,7 +5798,7 @@ class P115Client(P115OpenClient):
|
|
4902
5798
|
)
|
4903
5799
|
check_response(resp)
|
4904
5800
|
return uid
|
4905
|
-
return run_gen_step(gen_step, async_=async_)
|
5801
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4906
5802
|
|
4907
5803
|
@overload
|
4908
5804
|
def login_with_open(
|
@@ -4954,7 +5850,7 @@ class P115Client(P115OpenClient):
|
|
4954
5850
|
resp = yield self.login_qrcode_scan_confirm(login_uid, async_=async_, **request_kwargs)
|
4955
5851
|
check_response(resp)
|
4956
5852
|
return self.login_qrcode_access_token_open(login_uid, async_=async_, **request_kwargs)
|
4957
|
-
return run_gen_step(gen_step, async_=async_)
|
5853
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4958
5854
|
|
4959
5855
|
@overload
|
4960
5856
|
def login_another_app(
|
@@ -5098,7 +5994,7 @@ class P115Client(P115OpenClient):
|
|
5098
5994
|
if self is not inst and ssoent == inst.login_ssoent:
|
5099
5995
|
warn(f"login with the same ssoent {ssoent!r}, {self!r} will expire within 60 seconds", category=P115Warning)
|
5100
5996
|
return inst
|
5101
|
-
return run_gen_step(gen_step, async_=async_)
|
5997
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5102
5998
|
|
5103
5999
|
@overload
|
5104
6000
|
def login_another_open(
|
@@ -5192,7 +6088,7 @@ class P115Client(P115OpenClient):
|
|
5192
6088
|
inst.access_token = data["access_token"]
|
5193
6089
|
inst.app_id = app_id
|
5194
6090
|
return inst
|
5195
|
-
return run_gen_step(gen_step, async_=async_)
|
6091
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5196
6092
|
|
5197
6093
|
@overload
|
5198
6094
|
@classmethod
|
@@ -5311,7 +6207,7 @@ class P115Client(P115OpenClient):
|
|
5311
6207
|
resp = yield cls.login_qrcode_scan_result(uid, app, async_=async_, **request_kwargs)
|
5312
6208
|
cookies = check_response(resp)["data"]["cookie"]
|
5313
6209
|
return cls(cookies, check_for_relogin=check_for_relogin)
|
5314
|
-
return run_gen_step(gen_step, async_=async_)
|
6210
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5315
6211
|
|
5316
6212
|
@overload
|
5317
6213
|
def logout(
|
@@ -5347,7 +6243,7 @@ class P115Client(P115OpenClient):
|
|
5347
6243
|
return None
|
5348
6244
|
return self.logout_by_ssoent(ssoent, async_=async_, **request_kwargs)
|
5349
6245
|
|
5350
|
-
def
|
6246
|
+
def _request(
|
5351
6247
|
self,
|
5352
6248
|
/,
|
5353
6249
|
url: str,
|
@@ -5463,7 +6359,7 @@ class P115Client(P115OpenClient):
|
|
5463
6359
|
if async_:
|
5464
6360
|
fetch_cert_headers = ensure_async(fetch_cert_headers)
|
5465
6361
|
if fetch_cert_headers_argcount:
|
5466
|
-
fetch_cert_headers =
|
6362
|
+
fetch_cert_headers = cast(Callable, fetch_cert_headers)(async_)
|
5467
6363
|
if revert_cert_headers is not None and async_:
|
5468
6364
|
revert_cert_headers = ensure_async(revert_cert_headers)
|
5469
6365
|
if is_open_api:
|
@@ -5517,8 +6413,7 @@ class P115Client(P115OpenClient):
|
|
5517
6413
|
cert: str = headers["authorization"]
|
5518
6414
|
else:
|
5519
6415
|
cert = headers["cookie"]
|
5520
|
-
resp = yield
|
5521
|
-
cast(Callable, request),
|
6416
|
+
resp = yield cast(Callable, request)(
|
5522
6417
|
url=url,
|
5523
6418
|
method=method,
|
5524
6419
|
**request_kwargs,
|
@@ -5531,10 +6426,10 @@ class P115Client(P115OpenClient):
|
|
5531
6426
|
not is_auth_error and
|
5532
6427
|
get_status_code(e) != 405
|
5533
6428
|
):
|
5534
|
-
yield
|
6429
|
+
yield revert_cert_headers(cert_headers)
|
5535
6430
|
if not need_to_check:
|
5536
6431
|
raise
|
5537
|
-
res = yield
|
6432
|
+
res = yield cast(Callable, check_for_relogin)(e)
|
5538
6433
|
if not res if isinstance(res, bool) else res != 405:
|
5539
6434
|
raise
|
5540
6435
|
if fetch_cert_headers is not None:
|
@@ -5583,11 +6478,95 @@ class P115Client(P115OpenClient):
|
|
5583
6478
|
lock.release()
|
5584
6479
|
else:
|
5585
6480
|
if cert_headers is not None and revert_cert_headers is not None:
|
5586
|
-
yield
|
6481
|
+
yield revert_cert_headers(cert_headers)
|
5587
6482
|
if check and isinstance(resp, dict):
|
5588
6483
|
check_response(resp)
|
5589
6484
|
return resp
|
5590
|
-
return run_gen_step(gen_step, async_=async_)
|
6485
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
6486
|
+
|
6487
|
+
def request(
|
6488
|
+
self,
|
6489
|
+
/,
|
6490
|
+
url: str,
|
6491
|
+
method: str = "GET",
|
6492
|
+
params = None,
|
6493
|
+
data = None,
|
6494
|
+
*,
|
6495
|
+
async_: Literal[False, True] = False,
|
6496
|
+
**request_kwargs,
|
6497
|
+
):
|
6498
|
+
"""帮助函数:可执行同步和异步的网络请求
|
6499
|
+
|
6500
|
+
:param url: HTTP 的请求链接
|
6501
|
+
:param method: HTTP 的请求方法
|
6502
|
+
:param params: 查询参数
|
6503
|
+
:param check: 是否用 `check_response` 函数检查返回值
|
6504
|
+
:param ecdh_encrypt: 使用 ecdh 算法进行加密(返回值也要解密)
|
6505
|
+
:param fetch_cert_headers: 调用以获取认证信息头
|
6506
|
+
:param revert_cert_headers: 调用以退还认证信息头
|
6507
|
+
:param async_: 说明 `request` 是同步调用还是异步调用
|
6508
|
+
:param request: HTTP 请求调用,如果为 None,则默认用 httpx 执行请求
|
6509
|
+
如果传入调用,则必须至少能接受以下几个关键词参数:
|
6510
|
+
|
6511
|
+
- url: HTTP 的请求链接
|
6512
|
+
- method: HTTP 的请求方法
|
6513
|
+
- headers: HTTP 的请求头
|
6514
|
+
- data: HTTP 的请求体
|
6515
|
+
- parse: 解析 HTTP 响应的方法,默认会构建一个 Callable,会把响应的字节数据视为 JSON 进行反序列化解析
|
6516
|
+
|
6517
|
+
- 如果为 None,则直接把响应对象返回
|
6518
|
+
- 如果为 ...(Ellipsis),则把响应对象关闭后将其返回
|
6519
|
+
- 如果为 True,则根据响应头来确定把响应得到的字节数据解析成何种格式(反序列化),请求也会被自动关闭
|
6520
|
+
- 如果为 False,则直接返回响应得到的字节数据,请求也会被自动关闭
|
6521
|
+
- 如果为 Callable,则使用此调用来解析数据,接受 1-2 个位置参数,并把解析结果返回给 `request` 的调用者,请求也会被自动关闭
|
6522
|
+
- 如果只接受 1 个位置参数,则把响应对象传给它
|
6523
|
+
- 如果能接受 2 个位置参数,则把响应对象和响应得到的字节数据(响应体)传给它
|
6524
|
+
|
6525
|
+
:param request_kwargs: 其余的请求参数,会被传给 `request`
|
6526
|
+
|
6527
|
+
:return: 直接返回 `request` 执行请求后的返回值
|
6528
|
+
|
6529
|
+
.. note::
|
6530
|
+
`request` 可以由不同的请求库来提供,下面是封装了一些模块
|
6531
|
+
|
6532
|
+
1. `httpx_request <https://pypi.org/project/httpx_request/>`_,由 `httpx <https://pypi.org/project/httpx/>`_ 封装,支持同步和异步调用,本模块默认用的就是这个封装
|
6533
|
+
|
6534
|
+
.. code:: python
|
6535
|
+
|
6536
|
+
from httpx_request import request
|
6537
|
+
|
6538
|
+
2. `python-urlopen <https://pypi.org/project/python-urlopen/>`_,由 `urllib.request.urlopen <https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen>`_ 封装,支持同步调用,性能相对最差
|
6539
|
+
|
6540
|
+
.. code:: python
|
6541
|
+
|
6542
|
+
from urlopen import request
|
6543
|
+
|
6544
|
+
3. `urllib3_request <https://pypi.org/project/urllib3_request/>`_,由 `urllib3 <https://pypi.org/project/urllib3/>`_ 封装,支持同步调用,性能相对较好,推荐使用
|
6545
|
+
|
6546
|
+
.. code:: python
|
6547
|
+
|
6548
|
+
from urllib3_request import request
|
6549
|
+
|
6550
|
+
4. `requests_request <https://pypi.org/project/requests_request/>`_,由 `requests <https://pypi.org/project/requests/>`_ 封装,支持同步调用
|
6551
|
+
|
6552
|
+
.. code:: python
|
6553
|
+
|
6554
|
+
from requests_request import request
|
6555
|
+
|
6556
|
+
5. `aiohttp_client_request <https://pypi.org/project/aiohttp_client_request/>`_,由 `aiohttp <https://pypi.org/project/aiohttp/>`_ 封装,支持异步调用,异步并发能力最强,推荐使用
|
6557
|
+
|
6558
|
+
.. code:: python
|
6559
|
+
|
6560
|
+
from aiohttp_client_request import request
|
6561
|
+
|
6562
|
+
6. `blacksheep_client_request <https://pypi.org/project/blacksheep_client_request/>`_,由 `blacksheep <https://pypi.org/project/blacksheep/>`_ 封装,支持异步调用
|
6563
|
+
|
6564
|
+
.. code:: python
|
6565
|
+
|
6566
|
+
from blacksheep_client_request import request
|
6567
|
+
"""
|
6568
|
+
kwargs = {**self.request_kwargs, **request_kwargs}
|
6569
|
+
return self._request(url, method, params, data, async_=async_, **kwargs)
|
5591
6570
|
|
5592
6571
|
########## Activity API ##########
|
5593
6572
|
|
@@ -6355,15 +7334,14 @@ class P115Client(P115OpenClient):
|
|
6355
7334
|
if "sign" not in payload:
|
6356
7335
|
resp = yield self.captcha_sign(async_=async_)
|
6357
7336
|
payload["sign"] = resp["sign"]
|
6358
|
-
return
|
6359
|
-
self.request,
|
7337
|
+
return self.request(
|
6360
7338
|
url=api,
|
6361
7339
|
method="POST",
|
6362
7340
|
data=payload,
|
6363
7341
|
async_=async_,
|
6364
7342
|
**request_kwargs,
|
6365
7343
|
)
|
6366
|
-
return run_gen_step(gen_step, async_=async_)
|
7344
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
6367
7345
|
|
6368
7346
|
########## Download API ##########
|
6369
7347
|
|
@@ -9057,9 +10035,9 @@ class P115Client(P115OpenClient):
|
|
9057
10035
|
4. show_dir=0 且 cur=0(或不指定 cur)
|
9058
10036
|
|
9059
10037
|
.. hint::
|
9060
|
-
|
10038
|
+
如果不指定或者指定的 cid 不存在,则会视为 cid=0 进行处理
|
9061
10039
|
|
9062
|
-
|
10040
|
+
当指定 natsort=1 时,如果里面的数量较少时,可仅统计某个目录内的文件或目录总数,而不返回具体的文件信息
|
9063
10041
|
|
9064
10042
|
.. hint::
|
9065
10043
|
当一个 cookies 被另一个更新的登录所失效,并不意味着这个 cookies 就直接不可用了。
|
@@ -14938,12 +15916,145 @@ class P115Client(P115OpenClient):
|
|
14938
15916
|
if device is None:
|
14939
15917
|
return None
|
14940
15918
|
return device["icon"]
|
14941
|
-
return run_gen_step(gen_step, async_=async_)
|
15919
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
15920
|
+
|
15921
|
+
@overload
|
15922
|
+
def login_open_auth_detail(
|
15923
|
+
self,
|
15924
|
+
payload: int | str | dict,
|
15925
|
+
/,
|
15926
|
+
app: str = "web",
|
15927
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15928
|
+
*,
|
15929
|
+
async_: Literal[False] = False,
|
15930
|
+
**request_kwargs,
|
15931
|
+
) -> dict:
|
15932
|
+
...
|
15933
|
+
@overload
|
15934
|
+
def login_open_auth_detail(
|
15935
|
+
self,
|
15936
|
+
payload: int | str | dict,
|
15937
|
+
/,
|
15938
|
+
app: str = "web",
|
15939
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15940
|
+
*,
|
15941
|
+
async_: Literal[True],
|
15942
|
+
**request_kwargs,
|
15943
|
+
) -> Coroutine[Any, Any, dict]:
|
15944
|
+
...
|
15945
|
+
def login_open_auth_detail(
|
15946
|
+
self,
|
15947
|
+
payload: int | str | dict,
|
15948
|
+
/,
|
15949
|
+
app: str = "web",
|
15950
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15951
|
+
*,
|
15952
|
+
async_: Literal[False, True] = False,
|
15953
|
+
**request_kwargs,
|
15954
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
15955
|
+
"""获取某个开放应用的授权信息
|
15956
|
+
|
15957
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/user/getAppAuthDetail
|
15958
|
+
|
15959
|
+
:payload:
|
15960
|
+
- auth_id: int | str 💡 授权 id
|
15961
|
+
"""
|
15962
|
+
api = complete_api(f"/app/1.0/{app}/1.0/user/getAppAuthDetail", base_url=base_url)
|
15963
|
+
if isinstance(payload, (int, str)):
|
15964
|
+
payload = {"auth_id": payload}
|
15965
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
15966
|
+
|
15967
|
+
@overload
|
15968
|
+
def login_open_auth_list(
|
15969
|
+
self,
|
15970
|
+
/,
|
15971
|
+
app: str = "web",
|
15972
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15973
|
+
*,
|
15974
|
+
async_: Literal[False] = False,
|
15975
|
+
**request_kwargs,
|
15976
|
+
) -> dict:
|
15977
|
+
...
|
15978
|
+
@overload
|
15979
|
+
def login_open_auth_list(
|
15980
|
+
self,
|
15981
|
+
/,
|
15982
|
+
app: str = "web",
|
15983
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15984
|
+
*,
|
15985
|
+
async_: Literal[True],
|
15986
|
+
**request_kwargs,
|
15987
|
+
) -> Coroutine[Any, Any, dict]:
|
15988
|
+
...
|
15989
|
+
def login_open_auth_list(
|
15990
|
+
self,
|
15991
|
+
/,
|
15992
|
+
app: str = "web",
|
15993
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15994
|
+
*,
|
15995
|
+
async_: Literal[False, True] = False,
|
15996
|
+
**request_kwargs,
|
15997
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
15998
|
+
"""获取所有授权的开放应用的列表
|
15999
|
+
|
16000
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/user/getAppAuthList
|
16001
|
+
"""
|
16002
|
+
api = complete_api(f"/app/1.0/{app}/1.0/user/getAppAuthList", base_url=base_url)
|
16003
|
+
return self.request(url=api, async_=async_, **request_kwargs)
|
16004
|
+
|
16005
|
+
@overload
|
16006
|
+
def login_open_deauth(
|
16007
|
+
self,
|
16008
|
+
payload: int | str | dict,
|
16009
|
+
/,
|
16010
|
+
app: str = "web",
|
16011
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16012
|
+
*,
|
16013
|
+
async_: Literal[False] = False,
|
16014
|
+
**request_kwargs,
|
16015
|
+
) -> dict:
|
16016
|
+
...
|
16017
|
+
@overload
|
16018
|
+
def login_open_deauth(
|
16019
|
+
self,
|
16020
|
+
payload: int | str | dict,
|
16021
|
+
/,
|
16022
|
+
app: str = "web",
|
16023
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16024
|
+
*,
|
16025
|
+
async_: Literal[True],
|
16026
|
+
**request_kwargs,
|
16027
|
+
) -> Coroutine[Any, Any, dict]:
|
16028
|
+
...
|
16029
|
+
def login_open_deauth(
|
16030
|
+
self,
|
16031
|
+
payload: int | str | dict,
|
16032
|
+
/,
|
16033
|
+
app: str = "web",
|
16034
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16035
|
+
*,
|
16036
|
+
async_: Literal[False, True] = False,
|
16037
|
+
**request_kwargs,
|
16038
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
16039
|
+
"""取消某个开放应用的授权
|
16040
|
+
|
16041
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/user/deauthApp
|
16042
|
+
|
16043
|
+
:payload:
|
16044
|
+
- auth_id: int | str 💡 授权 id
|
16045
|
+
"""
|
16046
|
+
api = complete_api(f"/app/1.0/{app}/1.0/user/deauthApp", base_url=base_url)
|
16047
|
+
if isinstance(payload, (int, str)):
|
16048
|
+
payload = {"auth_id": payload}
|
16049
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
14942
16050
|
|
14943
16051
|
@overload
|
14944
16052
|
def login_check_sso(
|
14945
16053
|
self,
|
14946
16054
|
/,
|
16055
|
+
app: str = "web",
|
16056
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16057
|
+
*,
|
14947
16058
|
async_: Literal[False] = False,
|
14948
16059
|
**request_kwargs,
|
14949
16060
|
) -> dict:
|
@@ -14952,6 +16063,9 @@ class P115Client(P115OpenClient):
|
|
14952
16063
|
def login_check_sso(
|
14953
16064
|
self,
|
14954
16065
|
/,
|
16066
|
+
app: str = "web",
|
16067
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16068
|
+
*,
|
14955
16069
|
async_: Literal[True],
|
14956
16070
|
**request_kwargs,
|
14957
16071
|
) -> Coroutine[Any, Any, dict]:
|
@@ -14959,14 +16073,17 @@ class P115Client(P115OpenClient):
|
|
14959
16073
|
def login_check_sso(
|
14960
16074
|
self,
|
14961
16075
|
/,
|
16076
|
+
app: str = "web",
|
16077
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16078
|
+
*,
|
14962
16079
|
async_: Literal[False, True] = False,
|
14963
16080
|
**request_kwargs,
|
14964
16081
|
) -> dict | Coroutine[Any, Any, dict]:
|
14965
16082
|
"""检查当前 cookies 的登录状态信息,并且自最近一次登录的 60 秒后,使当前设备下除最近一次登录外的所有 cookies 失效
|
14966
16083
|
|
14967
|
-
GET https://
|
16084
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/check/sso
|
14968
16085
|
"""
|
14969
|
-
api = "
|
16086
|
+
api = complete_api(f"/app/1.0/{app}/1.0/check/sso", base_url=base_url)
|
14970
16087
|
return self.request(url=api, async_=async_, **request_kwargs)
|
14971
16088
|
|
14972
16089
|
@overload
|
@@ -15005,6 +16122,9 @@ class P115Client(P115OpenClient):
|
|
15005
16122
|
def login_devices(
|
15006
16123
|
self,
|
15007
16124
|
/,
|
16125
|
+
app: str = "web",
|
16126
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16127
|
+
*,
|
15008
16128
|
async_: Literal[False] = False,
|
15009
16129
|
**request_kwargs,
|
15010
16130
|
) -> dict:
|
@@ -15013,6 +16133,9 @@ class P115Client(P115OpenClient):
|
|
15013
16133
|
def login_devices(
|
15014
16134
|
self,
|
15015
16135
|
/,
|
16136
|
+
app: str = "web",
|
16137
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16138
|
+
*,
|
15016
16139
|
async_: Literal[True],
|
15017
16140
|
**request_kwargs,
|
15018
16141
|
) -> Coroutine[Any, Any, dict]:
|
@@ -15020,14 +16143,17 @@ class P115Client(P115OpenClient):
|
|
15020
16143
|
def login_devices(
|
15021
16144
|
self,
|
15022
16145
|
/,
|
16146
|
+
app: str = "web",
|
16147
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
16148
|
+
*,
|
15023
16149
|
async_: Literal[False, True] = False,
|
15024
16150
|
**request_kwargs,
|
15025
16151
|
) -> dict | Coroutine[Any, Any, dict]:
|
15026
16152
|
"""获取所有的已登录设备的信息,不过当前的 cookies 必须是登录状态(未退出或未失效)
|
15027
16153
|
|
15028
|
-
GET https://
|
16154
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/login_devices
|
15029
16155
|
"""
|
15030
|
-
api = "
|
16156
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login_log/login_devices", base_url=base_url)
|
15031
16157
|
return self.request(url=api, async_=async_, **request_kwargs)
|
15032
16158
|
|
15033
16159
|
@overload
|
@@ -15073,6 +16199,8 @@ class P115Client(P115OpenClient):
|
|
15073
16199
|
self,
|
15074
16200
|
payload: dict = {},
|
15075
16201
|
/,
|
16202
|
+
app: str = "web",
|
16203
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15076
16204
|
*,
|
15077
16205
|
async_: Literal[False] = False,
|
15078
16206
|
**request_kwargs,
|
@@ -15083,6 +16211,8 @@ class P115Client(P115OpenClient):
|
|
15083
16211
|
self,
|
15084
16212
|
payload: dict = {},
|
15085
16213
|
/,
|
16214
|
+
app: str = "web",
|
16215
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15086
16216
|
*,
|
15087
16217
|
async_: Literal[True],
|
15088
16218
|
**request_kwargs,
|
@@ -15092,19 +16222,21 @@ class P115Client(P115OpenClient):
|
|
15092
16222
|
self,
|
15093
16223
|
payload: dict = {},
|
15094
16224
|
/,
|
16225
|
+
app: str = "web",
|
16226
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15095
16227
|
*,
|
15096
16228
|
async_: Literal[False, True] = False,
|
15097
16229
|
**request_kwargs,
|
15098
16230
|
) -> dict | Coroutine[Any, Any, dict]:
|
15099
16231
|
"""获取登录信息日志列表
|
15100
16232
|
|
15101
|
-
GET https://
|
16233
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/log
|
15102
16234
|
|
15103
16235
|
:payload:
|
15104
16236
|
- start: int = 0
|
15105
16237
|
- limit: int = 100
|
15106
16238
|
"""
|
15107
|
-
api = "
|
16239
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login_log/log", base_url=base_url)
|
15108
16240
|
payload = {"start": 0, "limit": 100, **payload}
|
15109
16241
|
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
15110
16242
|
|
@@ -15113,6 +16245,7 @@ class P115Client(P115OpenClient):
|
|
15113
16245
|
self,
|
15114
16246
|
/,
|
15115
16247
|
app: str = "web",
|
16248
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15116
16249
|
*,
|
15117
16250
|
async_: Literal[False] = False,
|
15118
16251
|
**request_kwargs,
|
@@ -15123,6 +16256,7 @@ class P115Client(P115OpenClient):
|
|
15123
16256
|
self,
|
15124
16257
|
/,
|
15125
16258
|
app: str = "web",
|
16259
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15126
16260
|
*,
|
15127
16261
|
async_: Literal[True],
|
15128
16262
|
**request_kwargs,
|
@@ -15132,15 +16266,16 @@ class P115Client(P115OpenClient):
|
|
15132
16266
|
self,
|
15133
16267
|
/,
|
15134
16268
|
app: str = "web",
|
16269
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15135
16270
|
*,
|
15136
16271
|
async_: Literal[False, True] = False,
|
15137
16272
|
**request_kwargs,
|
15138
16273
|
) -> dict | Coroutine[Any, Any, dict]:
|
15139
16274
|
"""当前登录的设备总数和最近登录的设备
|
15140
16275
|
|
15141
|
-
GET https://
|
16276
|
+
GET https://qrcodeapi.115.com/app/1.0/web/1.0/login_log/login_online
|
15142
16277
|
"""
|
15143
|
-
api = f"
|
16278
|
+
api = complete_api(f"/app/1.0/{app}/1.0/login_log/login_online", base_url=base_url)
|
15144
16279
|
return self.request(url=api, async_=async_, **request_kwargs)
|
15145
16280
|
|
15146
16281
|
@overload
|
@@ -15202,6 +16337,7 @@ class P115Client(P115OpenClient):
|
|
15202
16337
|
/,
|
15203
16338
|
app: None | str = None,
|
15204
16339
|
request: None | Callable = None,
|
16340
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15205
16341
|
*,
|
15206
16342
|
async_: Literal[False] = False,
|
15207
16343
|
**request_kwargs,
|
@@ -15213,6 +16349,7 @@ class P115Client(P115OpenClient):
|
|
15213
16349
|
/,
|
15214
16350
|
app: None | str = None,
|
15215
16351
|
request: None | Callable = None,
|
16352
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15216
16353
|
*,
|
15217
16354
|
async_: Literal[True],
|
15218
16355
|
**request_kwargs,
|
@@ -15223,13 +16360,14 @@ class P115Client(P115OpenClient):
|
|
15223
16360
|
/,
|
15224
16361
|
app: None | str = None,
|
15225
16362
|
request: None | Callable = None,
|
16363
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15226
16364
|
*,
|
15227
16365
|
async_: Literal[False, True] = False,
|
15228
16366
|
**request_kwargs,
|
15229
16367
|
) -> None | Coroutine[Any, Any, None]:
|
15230
16368
|
"""退出登录状态(可以把某个客户端下线,所有已登录设备可从 `login_devices` 获取)
|
15231
16369
|
|
15232
|
-
GET https://
|
16370
|
+
GET https://qrcodeapi.115.com/app/1.0/{app}/1.0/logout/logout
|
15233
16371
|
|
15234
16372
|
:param app: 退出登录的 app
|
15235
16373
|
|
@@ -15295,20 +16433,22 @@ class P115Client(P115OpenClient):
|
|
15295
16433
|
app = yield self.login_app(async_=async_)
|
15296
16434
|
if app == "desktop":
|
15297
16435
|
app = "web"
|
15298
|
-
api = f"
|
16436
|
+
api = complete_api(f"/app/1.0/{app}/1.0/logout/logout", base_url=base_url)
|
15299
16437
|
request_kwargs["headers"] = {**(request_kwargs.get("headers") or {}), "Cookie": self.cookies_str}
|
15300
16438
|
request_kwargs.setdefault("parse", ...)
|
15301
16439
|
if request is None:
|
15302
16440
|
return get_default_request()(url=api, async_=async_, **request_kwargs)
|
15303
16441
|
else:
|
15304
16442
|
return request(url=api, **request_kwargs)
|
15305
|
-
return run_gen_step(gen_step, async_=async_)
|
16443
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
15306
16444
|
|
15307
16445
|
@overload
|
15308
16446
|
def logout_by_ssoent(
|
15309
16447
|
self,
|
15310
16448
|
payload: None | str | dict = None,
|
15311
16449
|
/,
|
16450
|
+
app: str = "web",
|
16451
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15312
16452
|
*,
|
15313
16453
|
async_: Literal[False] = False,
|
15314
16454
|
**request_kwargs,
|
@@ -15319,6 +16459,8 @@ class P115Client(P115OpenClient):
|
|
15319
16459
|
self,
|
15320
16460
|
payload: None | str | dict = None,
|
15321
16461
|
/,
|
16462
|
+
app: str = "web",
|
16463
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15322
16464
|
*,
|
15323
16465
|
async_: Literal[True],
|
15324
16466
|
**request_kwargs,
|
@@ -15328,13 +16470,15 @@ class P115Client(P115OpenClient):
|
|
15328
16470
|
self,
|
15329
16471
|
payload: None | str | dict = None,
|
15330
16472
|
/,
|
16473
|
+
app: str = "web",
|
16474
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
15331
16475
|
*,
|
15332
16476
|
async_: Literal[False, True] = False,
|
15333
16477
|
**request_kwargs,
|
15334
16478
|
) -> dict | Coroutine[Any, Any, dict]:
|
15335
16479
|
"""退出登录状态(可以把某个客户端下线,所有已登录设备可从 `login_devices` 获取)
|
15336
16480
|
|
15337
|
-
POST https://
|
16481
|
+
POST https://qrcodeapi.115.com/app/1.0/web/1.0/logout/mange
|
15338
16482
|
|
15339
16483
|
:payload:
|
15340
16484
|
- ssoent: str
|
@@ -15395,7 +16539,7 @@ class P115Client(P115OpenClient):
|
|
15395
16539
|
| 24 | S1 | harmony | 115(Harmony端) |
|
15396
16540
|
+-------+----------+------------+-------------------------+
|
15397
16541
|
"""
|
15398
|
-
api = "
|
16542
|
+
api = complete_api(f"/app/1.0/{app}/1.0/logout/mange", base_url=base_url)
|
15399
16543
|
if payload is None:
|
15400
16544
|
payload = {"ssoent": self.login_ssoent or ""}
|
15401
16545
|
elif isinstance(payload, str):
|
@@ -16389,7 +17533,7 @@ class P115Client(P115OpenClient):
|
|
16389
17533
|
method = self._offline_lixianssp_post
|
16390
17534
|
return method(payload, ac, async_=async_, ecdh_encrypt=ecdh_encrypt, **request_kwargs)
|
16391
17535
|
|
16392
|
-
@overload
|
17536
|
+
@overload # type: ignore
|
16393
17537
|
def offline_add_torrent(
|
16394
17538
|
self,
|
16395
17539
|
payload: str | dict,
|
@@ -16431,8 +17575,8 @@ class P115Client(P115OpenClient):
|
|
16431
17575
|
|
16432
17576
|
:payload:
|
16433
17577
|
- info_hash: str 💡 种子文件的 info_hash
|
16434
|
-
- wanted: str = <default> 💡
|
16435
|
-
- savepath: str = <default> 💡
|
17578
|
+
- wanted: str = <default> 💡 选择文件进行下载(是数字索引,从 0 开始计数,用 "," 分隔)
|
17579
|
+
- savepath: str = <default> 💡 保存到 `wp_path_id` 对应目录下的相对路径
|
16436
17580
|
- wp_path_id: int | str = <default> 💡 保存到目录的 id
|
16437
17581
|
"""
|
16438
17582
|
if isinstance(payload, str):
|
@@ -16483,7 +17627,7 @@ class P115Client(P115OpenClient):
|
|
16483
17627
|
payload = {"url": payload}
|
16484
17628
|
return self._offline_post(payload, "add_task_url", use_web_api=use_web_api, async_=async_, **request_kwargs)
|
16485
17629
|
|
16486
|
-
@overload
|
17630
|
+
@overload # type: ignore
|
16487
17631
|
def offline_add_urls(
|
16488
17632
|
self,
|
16489
17633
|
payload: str | Iterable[str] | dict,
|
@@ -16526,7 +17670,7 @@ class P115Client(P115OpenClient):
|
|
16526
17670
|
- wp_path_id: int | str = <default> 💡 保存到目录的 id
|
16527
17671
|
"""
|
16528
17672
|
if isinstance(payload, str):
|
16529
|
-
payload = payload.strip().split("\n")
|
17673
|
+
payload = payload.strip("\n").split("\n")
|
16530
17674
|
if not isinstance(payload, dict):
|
16531
17675
|
payload = {f"url[{i}]": url for i, url in enumerate(payload)}
|
16532
17676
|
if not payload:
|
@@ -16536,7 +17680,7 @@ class P115Client(P115OpenClient):
|
|
16536
17680
|
@overload
|
16537
17681
|
def offline_clear(
|
16538
17682
|
self,
|
16539
|
-
payload: int | dict,
|
17683
|
+
payload: int | dict = 0,
|
16540
17684
|
/,
|
16541
17685
|
base_url: None | bool | str | Callable[[], str] = None,
|
16542
17686
|
*,
|
@@ -16547,7 +17691,7 @@ class P115Client(P115OpenClient):
|
|
16547
17691
|
@overload
|
16548
17692
|
def offline_clear(
|
16549
17693
|
self,
|
16550
|
-
payload: int | dict,
|
17694
|
+
payload: int | dict = 0,
|
16551
17695
|
/,
|
16552
17696
|
base_url: None | bool | str | Callable[[], str] = None,
|
16553
17697
|
*,
|
@@ -16557,7 +17701,7 @@ class P115Client(P115OpenClient):
|
|
16557
17701
|
...
|
16558
17702
|
def offline_clear(
|
16559
17703
|
self,
|
16560
|
-
payload: int | dict =
|
17704
|
+
payload: int | dict = 0,
|
16561
17705
|
/,
|
16562
17706
|
base_url: None | bool | str | Callable[[], str] = None,
|
16563
17707
|
*,
|
@@ -16580,11 +17724,6 @@ class P115Client(P115OpenClient):
|
|
16580
17724
|
"""
|
16581
17725
|
api = complete_lixian_api("?ct=lixian&ac=task_clear", base_url=base_url)
|
16582
17726
|
if isinstance(payload, int):
|
16583
|
-
flag = payload
|
16584
|
-
if flag < 0:
|
16585
|
-
flag = 0
|
16586
|
-
elif flag > 5:
|
16587
|
-
flag = 5
|
16588
17727
|
payload = {"flag": payload}
|
16589
17728
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
16590
17729
|
|
@@ -16658,7 +17797,7 @@ class P115Client(P115OpenClient):
|
|
16658
17797
|
api = complete_api("/?ct=offline&ac=space", base_url=base_url)
|
16659
17798
|
return self.request(url=api, async_=async_, **request_kwargs)
|
16660
17799
|
|
16661
|
-
@overload
|
17800
|
+
@overload # type: ignore
|
16662
17801
|
def offline_list(
|
16663
17802
|
self,
|
16664
17803
|
payload: int | dict = 1,
|
@@ -16694,7 +17833,7 @@ class P115Client(P115OpenClient):
|
|
16694
17833
|
POST https://lixian.115.com/lixian/?ct=lixian&ac=task_lists
|
16695
17834
|
|
16696
17835
|
:payload:
|
16697
|
-
- page: int | str
|
17836
|
+
- page: int | str = 1
|
16698
17837
|
"""
|
16699
17838
|
api = complete_lixian_api("?ct=lixian&ac=task_lists", base_url=base_url)
|
16700
17839
|
if isinstance(payload, int):
|
@@ -16809,7 +17948,7 @@ class P115Client(P115OpenClient):
|
|
16809
17948
|
@overload
|
16810
17949
|
def offline_remove(
|
16811
17950
|
self,
|
16812
|
-
payload: str | dict,
|
17951
|
+
payload: str | Iterable[str] | dict,
|
16813
17952
|
/,
|
16814
17953
|
base_url: None | bool | str | Callable[[], str] = None,
|
16815
17954
|
*,
|
@@ -16820,7 +17959,7 @@ class P115Client(P115OpenClient):
|
|
16820
17959
|
@overload
|
16821
17960
|
def offline_remove(
|
16822
17961
|
self,
|
16823
|
-
payload: str | dict,
|
17962
|
+
payload: str | Iterable[str] | dict,
|
16824
17963
|
/,
|
16825
17964
|
base_url: None | bool | str | Callable[[], str] = None,
|
16826
17965
|
*,
|
@@ -16830,7 +17969,7 @@ class P115Client(P115OpenClient):
|
|
16830
17969
|
...
|
16831
17970
|
def offline_remove(
|
16832
17971
|
self,
|
16833
|
-
payload: str | dict,
|
17972
|
+
payload: str | Iterable[str] | dict,
|
16834
17973
|
/,
|
16835
17974
|
base_url: None | bool | str | Callable[[], str] = None,
|
16836
17975
|
*,
|
@@ -19195,7 +20334,7 @@ class P115Client(P115OpenClient):
|
|
19195
20334
|
if resp["state"]:
|
19196
20335
|
self.user_key = resp["data"]["userkey"]
|
19197
20336
|
return resp
|
19198
|
-
return run_gen_step(gen_step, async_=async_)
|
20337
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
19199
20338
|
|
19200
20339
|
@overload
|
19201
20340
|
def upload_resume(
|
@@ -19562,7 +20701,7 @@ class P115Client(P115OpenClient):
|
|
19562
20701
|
"pickcode": resp["pickcode"],
|
19563
20702
|
}
|
19564
20703
|
return resp
|
19565
|
-
return run_gen_step(gen_step, async_=async_)
|
20704
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
19566
20705
|
|
19567
20706
|
@overload
|
19568
20707
|
def upload_file_sample(
|
@@ -19698,7 +20837,7 @@ class P115Client(P115OpenClient):
|
|
19698
20837
|
async_=async_,
|
19699
20838
|
**request_kwargs,
|
19700
20839
|
)
|
19701
|
-
return run_gen_step(gen_step, async_=async_)
|
20840
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
19702
20841
|
|
19703
20842
|
@overload # type: ignore
|
19704
20843
|
def upload_file(
|
@@ -20057,7 +21196,7 @@ class P115Client(P115OpenClient):
|
|
20057
21196
|
async_=async_, # type: ignore
|
20058
21197
|
**request_kwargs,
|
20059
21198
|
)
|
20060
|
-
return run_gen_step(gen_step, async_=async_)
|
21199
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
20061
21200
|
|
20062
21201
|
########## User API ##########
|
20063
21202
|
|