p115client 0.0.5.10.8__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 +1130 -318
- p115client/tool/attr.py +1 -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 +151 -72
- 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.8.dist-info → p115client-0.0.5.11.dist-info}/METADATA +2 -2
- p115client-0.0.5.11.dist-info/RECORD +26 -0
- p115client-0.0.5.10.8.dist-info/RECORD +0 -26
- {p115client-0.0.5.10.8.dist-info → p115client-0.0.5.11.dist-info}/LICENSE +0 -0
- {p115client-0.0.5.10.8.dist-info → p115client-0.0.5.11.dist-info}/WHEEL +0 -0
p115client/client.py
CHANGED
@@ -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)
|
@@ -542,6 +542,36 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
|
|
542
542
|
# {"state": 0, "errno": 40140126, "error": "access_token 校验失败(防篡改)"}
|
543
543
|
case 40140126:
|
544
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)
|
545
575
|
elif "msg_code" in resp:
|
546
576
|
match resp["msg_code"]:
|
547
577
|
case 50028:
|
@@ -616,9 +646,6 @@ def normalize_attr_web(
|
|
616
646
|
if "te" in info:
|
617
647
|
attr["mtime"] = int(info["te"])
|
618
648
|
else:
|
619
|
-
attr["labels"] = info["fl"]
|
620
|
-
if "score" in info:
|
621
|
-
attr["score"] = int(info.get("score") or 0)
|
622
649
|
attr["ico"] = info.get("ico", "folder" if is_directory else "")
|
623
650
|
if "te" in info:
|
624
651
|
attr["mtime"] = attr["user_utime"] = int(info["te"])
|
@@ -651,12 +678,14 @@ def normalize_attr_web(
|
|
651
678
|
("c", "violated"),
|
652
679
|
("c", "is_collect"),
|
653
680
|
("sh", "is_share"),
|
681
|
+
("score", "score"),
|
654
682
|
#("d", "has_desc"),
|
655
683
|
#("p", "has_pass"),
|
656
684
|
):
|
657
685
|
if key in info:
|
658
686
|
attr[name] = int(info[key] or 0)
|
659
687
|
for key, name in (
|
688
|
+
("fl", "labels"),
|
660
689
|
("dp", "dir_path"),
|
661
690
|
("style", "style"),
|
662
691
|
("ns", "name_show"),
|
@@ -744,10 +773,7 @@ def normalize_attr_app(
|
|
744
773
|
if "upt" in info:
|
745
774
|
attr["mtime"] = int(info["upt"])
|
746
775
|
else:
|
747
|
-
attr["labels"] = info["fl"]
|
748
776
|
attr["ico"] = info.get("ico", "folder" if attr["is_dir"] else "")
|
749
|
-
if "ftype" in info:
|
750
|
-
attr["file_type"] = int(info["ftype"] or 0)
|
751
777
|
if "thumb" in info:
|
752
778
|
thumb = info["thumb"]
|
753
779
|
if thumb.startswith("?"):
|
@@ -763,6 +789,7 @@ def normalize_attr_app(
|
|
763
789
|
("aid", "area_id"),
|
764
790
|
("fatr", "audio_play_long"),
|
765
791
|
("fta", "status"),
|
792
|
+
("ftype", "file_type"),
|
766
793
|
("ism", "star"),
|
767
794
|
("ism", "is_mark"),
|
768
795
|
("is_top", "is_top"),
|
@@ -784,6 +811,7 @@ def normalize_attr_app(
|
|
784
811
|
("fco", "cover"),
|
785
812
|
("fco", "folder_cover"),
|
786
813
|
("fdesc", "desc"),
|
814
|
+
("fl", "labels"),
|
787
815
|
("flabel", "fflabel"),
|
788
816
|
("multitrack", "multitrack"),
|
789
817
|
("play_long", "play_long"),
|
@@ -838,18 +866,28 @@ def normalize_attr_app2(
|
|
838
866
|
else:
|
839
867
|
dict_cls = AttrDict
|
840
868
|
attr: dict[str, Any] = dict_cls()
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
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"))
|
845
874
|
attr["id"] = int(info["file_id"])
|
846
|
-
attr["parent_id"] = int(info["
|
875
|
+
attr["parent_id"] = int(info["parent_id"])
|
847
876
|
attr["name"] = info["file_name"]
|
848
877
|
else:
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
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 ""
|
853
891
|
attr["size"] = int(info.get("file_size") or 0)
|
854
892
|
if "pick_code" in info:
|
855
893
|
attr["pickcode"] = info["pick_code"]
|
@@ -890,7 +928,8 @@ def normalize_attr_app2(
|
|
890
928
|
if "utime" in info:
|
891
929
|
attr["utime"] = int(info["utime"])
|
892
930
|
attr["ico"] = info.get("ico", "folder" if attr["is_dir"] else "")
|
893
|
-
|
931
|
+
if "fl" in info:
|
932
|
+
attr["labels"] = info["fl"]
|
894
933
|
for key, name in (
|
895
934
|
("area_id", "area_id"),
|
896
935
|
("has_desc", "has_desc"),
|
@@ -1158,13 +1197,17 @@ class ClientRequestMixin:
|
|
1158
1197
|
"user-agent": "Mozilla/5.0 AppleWebKit/600 Safari/600 Chrome/124.0.0.0",
|
1159
1198
|
})
|
1160
1199
|
|
1200
|
+
@locked_cacheproperty
|
1201
|
+
def request_kwargs(self, /) -> dict:
|
1202
|
+
return {}
|
1203
|
+
|
1161
1204
|
def close(self, /) -> None:
|
1162
1205
|
"""删除 session 和 async_session 属性,如果它们未被引用,则应该会被自动清理
|
1163
1206
|
"""
|
1164
1207
|
self.__dict__.pop("session", None)
|
1165
1208
|
self.__dict__.pop("async_session", None)
|
1166
1209
|
|
1167
|
-
def
|
1210
|
+
def _request(
|
1168
1211
|
self,
|
1169
1212
|
/,
|
1170
1213
|
url: str,
|
@@ -1282,120 +1325,252 @@ class ClientRequestMixin:
|
|
1282
1325
|
request_kwargs.setdefault("parse", default_parse)
|
1283
1326
|
return request(url=url, method=method, **request_kwargs)
|
1284
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
|
+
|
1285
1409
|
########## Qrcode API ##########
|
1286
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
|
+
|
1287
1460
|
@overload
|
1288
1461
|
@staticmethod
|
1289
|
-
def
|
1290
|
-
payload:
|
1462
|
+
def login_authorize_access_token_open(
|
1463
|
+
payload: dict,
|
1291
1464
|
/,
|
1292
1465
|
request: None | Callable = None,
|
1293
|
-
app: str = "web",
|
1294
1466
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1295
1467
|
*,
|
1296
1468
|
async_: Literal[False] = False,
|
1297
1469
|
**request_kwargs,
|
1298
|
-
) ->
|
1470
|
+
) -> dict:
|
1299
1471
|
...
|
1300
1472
|
@overload
|
1301
1473
|
@staticmethod
|
1302
|
-
def
|
1303
|
-
payload:
|
1474
|
+
def login_authorize_access_token_open(
|
1475
|
+
payload: dict,
|
1304
1476
|
/,
|
1305
1477
|
request: None | Callable = None,
|
1306
|
-
app: str = "web",
|
1307
1478
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1308
1479
|
*,
|
1309
1480
|
async_: Literal[True],
|
1310
1481
|
**request_kwargs,
|
1311
|
-
) -> Coroutine[Any, Any,
|
1482
|
+
) -> Coroutine[Any, Any, dict]:
|
1312
1483
|
...
|
1313
1484
|
@staticmethod
|
1314
|
-
def
|
1315
|
-
payload:
|
1485
|
+
def login_authorize_access_token_open(
|
1486
|
+
payload: dict,
|
1316
1487
|
/,
|
1317
1488
|
request: None | Callable = None,
|
1318
|
-
app: str = "web",
|
1319
1489
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1320
1490
|
*,
|
1321
1491
|
async_: Literal[False, True] = False,
|
1322
1492
|
**request_kwargs,
|
1323
|
-
) ->
|
1324
|
-
"""
|
1493
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
1494
|
+
"""用授权码获取开放接口应用的 access_token
|
1325
1495
|
|
1326
|
-
|
1496
|
+
POST https://qrcodeapi.115.com/open/authCodeToToken
|
1327
1497
|
|
1328
|
-
|
1498
|
+
.. admonition:: Reference
|
1329
1499
|
|
1330
|
-
|
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,表示授权码类型
|
1331
1508
|
"""
|
1332
|
-
api = complete_api(
|
1333
|
-
|
1334
|
-
|
1335
|
-
request_kwargs.setdefault("parse", False)
|
1509
|
+
api = complete_api("/open/authCodeToToken", base_url=base_url)
|
1510
|
+
payload = {"grant_type": "authorization_code", **payload}
|
1511
|
+
request_kwargs.setdefault("parse", default_parse)
|
1336
1512
|
if request is None:
|
1337
|
-
return get_default_request()(url=api,
|
1513
|
+
return get_default_request()(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
1338
1514
|
else:
|
1339
|
-
return request(url=api,
|
1515
|
+
return request(url=api, method="POST", data=payload, **request_kwargs)
|
1340
1516
|
|
1341
1517
|
@overload
|
1342
1518
|
@staticmethod
|
1343
|
-
def
|
1519
|
+
def login_qrcode(
|
1344
1520
|
payload: str | dict,
|
1345
1521
|
/,
|
1346
1522
|
request: None | Callable = None,
|
1523
|
+
app: str = "web",
|
1347
1524
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1348
1525
|
*,
|
1349
1526
|
async_: Literal[False] = False,
|
1350
1527
|
**request_kwargs,
|
1351
|
-
) ->
|
1528
|
+
) -> bytes:
|
1352
1529
|
...
|
1353
1530
|
@overload
|
1354
1531
|
@staticmethod
|
1355
|
-
def
|
1532
|
+
def login_qrcode(
|
1356
1533
|
payload: str | dict,
|
1357
1534
|
/,
|
1358
1535
|
request: None | Callable = None,
|
1536
|
+
app: str = "web",
|
1359
1537
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1360
1538
|
*,
|
1361
1539
|
async_: Literal[True],
|
1362
1540
|
**request_kwargs,
|
1363
|
-
) -> Coroutine[Any, Any,
|
1541
|
+
) -> Coroutine[Any, Any, bytes]:
|
1364
1542
|
...
|
1365
1543
|
@staticmethod
|
1366
|
-
def
|
1544
|
+
def login_qrcode(
|
1367
1545
|
payload: str | dict,
|
1368
1546
|
/,
|
1369
1547
|
request: None | Callable = None,
|
1548
|
+
app: str = "web",
|
1370
1549
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1371
1550
|
*,
|
1372
1551
|
async_: Literal[False, True] = False,
|
1373
1552
|
**request_kwargs,
|
1374
|
-
) ->
|
1375
|
-
"""
|
1376
|
-
|
1377
|
-
POST https://qrcodeapi.115.com/open/deviceCodeToToken
|
1553
|
+
) -> bytes | Coroutine[Any, Any, bytes]:
|
1554
|
+
"""下载登录二维码图片
|
1378
1555
|
|
1379
|
-
|
1556
|
+
GET https://qrcodeapi.115.com/api/1.0/web/1.0/qrcode
|
1380
1557
|
|
1381
|
-
|
1558
|
+
:params uid: 二维码的 uid
|
1382
1559
|
|
1383
|
-
:
|
1384
|
-
- uid: str
|
1385
|
-
- code_verifier: str = <default> 💡 默认字符串是 64 个 "0"
|
1560
|
+
:return: 图片的二进制数据(PNG 图片)
|
1386
1561
|
"""
|
1387
|
-
api = complete_api("/
|
1562
|
+
api = complete_api(f"/api/1.0/{app}/1.0/qrcode", base_url=base_url)
|
1388
1563
|
if isinstance(payload, str):
|
1389
|
-
payload = {"uid": payload
|
1390
|
-
request_kwargs.setdefault("parse",
|
1564
|
+
payload = {"uid": payload}
|
1565
|
+
request_kwargs.setdefault("parse", False)
|
1391
1566
|
if request is None:
|
1392
|
-
return get_default_request()(url=api,
|
1567
|
+
return get_default_request()(url=api, params=payload, async_=async_, **request_kwargs)
|
1393
1568
|
else:
|
1394
|
-
return request(url=api,
|
1569
|
+
return request(url=api, params=payload, **request_kwargs)
|
1395
1570
|
|
1396
1571
|
@overload
|
1397
1572
|
@staticmethod
|
1398
|
-
def
|
1573
|
+
def login_qrcode_access_token_open(
|
1399
1574
|
payload: str | dict,
|
1400
1575
|
/,
|
1401
1576
|
request: None | Callable = None,
|
@@ -1407,7 +1582,7 @@ class ClientRequestMixin:
|
|
1407
1582
|
...
|
1408
1583
|
@overload
|
1409
1584
|
@staticmethod
|
1410
|
-
def
|
1585
|
+
def login_qrcode_access_token_open(
|
1411
1586
|
payload: str | dict,
|
1412
1587
|
/,
|
1413
1588
|
request: None | Callable = None,
|
@@ -1418,7 +1593,7 @@ class ClientRequestMixin:
|
|
1418
1593
|
) -> Coroutine[Any, Any, dict]:
|
1419
1594
|
...
|
1420
1595
|
@staticmethod
|
1421
|
-
def
|
1596
|
+
def login_qrcode_access_token_open(
|
1422
1597
|
payload: str | dict,
|
1423
1598
|
/,
|
1424
1599
|
request: None | Callable = None,
|
@@ -1427,20 +1602,21 @@ class ClientRequestMixin:
|
|
1427
1602
|
async_: Literal[False, True] = False,
|
1428
1603
|
**request_kwargs,
|
1429
1604
|
) -> dict | Coroutine[Any, Any, dict]:
|
1430
|
-
"""
|
1605
|
+
"""绑定扫码并获取开放平台应用的 access_token 和 refresh_token
|
1431
1606
|
|
1432
|
-
POST https://qrcodeapi.115.com/open/
|
1607
|
+
POST https://qrcodeapi.115.com/open/deviceCodeToToken
|
1433
1608
|
|
1434
1609
|
.. admonition:: Reference
|
1435
1610
|
|
1436
|
-
https://www.yuque.com/115yun/open/shtpzfhewv5nag11#
|
1611
|
+
https://www.yuque.com/115yun/open/shtpzfhewv5nag11#QCCVQ
|
1437
1612
|
|
1438
1613
|
:payload:
|
1439
|
-
-
|
1614
|
+
- uid: str
|
1615
|
+
- code_verifier: str = <default> 💡 默认字符串是 64 个 "0"
|
1440
1616
|
"""
|
1441
|
-
api = complete_api("/open/
|
1617
|
+
api = complete_api("/open/deviceCodeToToken", base_url=base_url)
|
1442
1618
|
if isinstance(payload, str):
|
1443
|
-
payload = {"
|
1619
|
+
payload = {"uid": payload, "code_verifier": _default_code_verifier}
|
1444
1620
|
request_kwargs.setdefault("parse", default_parse)
|
1445
1621
|
if request is None:
|
1446
1622
|
return get_default_request()(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
@@ -1766,7 +1942,7 @@ class ClientRequestMixin:
|
|
1766
1942
|
async_: Literal[False, True] = False,
|
1767
1943
|
**request_kwargs,
|
1768
1944
|
) -> dict | Coroutine[Any, Any, dict]:
|
1769
|
-
"""
|
1945
|
+
"""获取开放平台的登录二维码,扫码可用,采用 PKCE (Proof Key for Code Exchange)
|
1770
1946
|
|
1771
1947
|
POST https://qrcodeapi.115.com/open/authDeviceCode
|
1772
1948
|
|
@@ -1807,12 +1983,11 @@ class ClientRequestMixin:
|
|
1807
1983
|
return request(url=api, method="POST", data=payload, **request_kwargs)
|
1808
1984
|
|
1809
1985
|
@overload
|
1810
|
-
@
|
1811
|
-
def
|
1812
|
-
|
1986
|
+
@staticmethod
|
1987
|
+
def login_refresh_token_open(
|
1988
|
+
payload: str | dict,
|
1813
1989
|
/,
|
1814
|
-
|
1815
|
-
console_qrcode: bool = True,
|
1990
|
+
request: None | Callable = None,
|
1816
1991
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1817
1992
|
*,
|
1818
1993
|
async_: Literal[False] = False,
|
@@ -1820,24 +1995,81 @@ class ClientRequestMixin:
|
|
1820
1995
|
) -> dict:
|
1821
1996
|
...
|
1822
1997
|
@overload
|
1823
|
-
@
|
1824
|
-
def
|
1825
|
-
|
1998
|
+
@staticmethod
|
1999
|
+
def login_refresh_token_open(
|
2000
|
+
payload: str | dict,
|
1826
2001
|
/,
|
1827
|
-
|
1828
|
-
console_qrcode: bool = True,
|
2002
|
+
request: None | Callable = None,
|
1829
2003
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1830
2004
|
*,
|
1831
2005
|
async_: Literal[True],
|
1832
2006
|
**request_kwargs,
|
1833
2007
|
) -> Coroutine[Any, Any, dict]:
|
1834
2008
|
...
|
1835
|
-
@
|
1836
|
-
def
|
1837
|
-
|
2009
|
+
@staticmethod
|
2010
|
+
def login_refresh_token_open(
|
2011
|
+
payload: str | dict,
|
1838
2012
|
/,
|
1839
|
-
|
1840
|
-
|
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
|
+
|
2041
|
+
@overload
|
2042
|
+
@classmethod
|
2043
|
+
def login_with_qrcode(
|
2044
|
+
cls,
|
2045
|
+
/,
|
2046
|
+
app: None | str = "",
|
2047
|
+
console_qrcode: bool = True,
|
2048
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
2049
|
+
*,
|
2050
|
+
async_: Literal[False] = False,
|
2051
|
+
**request_kwargs,
|
2052
|
+
) -> dict:
|
2053
|
+
...
|
2054
|
+
@overload
|
2055
|
+
@classmethod
|
2056
|
+
def login_with_qrcode(
|
2057
|
+
cls,
|
2058
|
+
/,
|
2059
|
+
app: None | str = "",
|
2060
|
+
console_qrcode: bool = True,
|
2061
|
+
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
2062
|
+
*,
|
2063
|
+
async_: Literal[True],
|
2064
|
+
**request_kwargs,
|
2065
|
+
) -> Coroutine[Any, Any, dict]:
|
2066
|
+
...
|
2067
|
+
@classmethod
|
2068
|
+
def login_with_qrcode(
|
2069
|
+
cls,
|
2070
|
+
/,
|
2071
|
+
app: None | str = "",
|
2072
|
+
console_qrcode: bool = True,
|
1841
2073
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
1842
2074
|
*,
|
1843
2075
|
async_: Literal[False, True] = False,
|
@@ -1955,7 +2187,7 @@ class ClientRequestMixin:
|
|
1955
2187
|
else:
|
1956
2188
|
url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
|
1957
2189
|
if async_:
|
1958
|
-
yield
|
2190
|
+
yield startfile_async(url)
|
1959
2191
|
else:
|
1960
2192
|
startfile(url)
|
1961
2193
|
while True:
|
@@ -1992,7 +2224,7 @@ class ClientRequestMixin:
|
|
1992
2224
|
)
|
1993
2225
|
else:
|
1994
2226
|
return qrcode_token
|
1995
|
-
return run_gen_step(gen_step, async_=async_)
|
2227
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
1996
2228
|
|
1997
2229
|
@overload
|
1998
2230
|
@classmethod
|
@@ -2059,7 +2291,7 @@ class ClientRequestMixin:
|
|
2059
2291
|
else:
|
2060
2292
|
url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
|
2061
2293
|
if async_:
|
2062
|
-
yield
|
2294
|
+
yield startfile_async(url)
|
2063
2295
|
else:
|
2064
2296
|
startfile(url)
|
2065
2297
|
while True:
|
@@ -2092,7 +2324,7 @@ class ClientRequestMixin:
|
|
2092
2324
|
async_=async_,
|
2093
2325
|
**request_kwargs,
|
2094
2326
|
)
|
2095
|
-
return run_gen_step(gen_step, async_=async_)
|
2327
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2096
2328
|
|
2097
2329
|
########## Upload API ##########
|
2098
2330
|
|
@@ -2475,7 +2707,7 @@ class ClientRequestMixin:
|
|
2475
2707
|
async_=async_,
|
2476
2708
|
**request_kwargs,
|
2477
2709
|
)
|
2478
|
-
return run_gen_step(gen_step, async_=async_)
|
2710
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2479
2711
|
|
2480
2712
|
@overload
|
2481
2713
|
def read_bytes_range(
|
@@ -2590,7 +2822,7 @@ class ClientRequestMixin:
|
|
2590
2822
|
async_=async_,
|
2591
2823
|
**request_kwargs,
|
2592
2824
|
)
|
2593
|
-
return run_gen_step(gen_step, async_=async_)
|
2825
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2594
2826
|
|
2595
2827
|
|
2596
2828
|
class P115OpenClient(ClientRequestMixin):
|
@@ -2668,7 +2900,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2668
2900
|
app_id_or_refresh_token.startswith("0") or
|
2669
2901
|
app_id_or_refresh_token.strip(digits)
|
2670
2902
|
):
|
2671
|
-
resp = yield self.
|
2903
|
+
resp = yield self.login_refresh_token_open(
|
2672
2904
|
app_id_or_refresh_token,
|
2673
2905
|
async_=async_,
|
2674
2906
|
**request_kwargs,
|
@@ -2686,7 +2918,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2686
2918
|
self.refresh_token = data["refresh_token"]
|
2687
2919
|
self.access_token = data["access_token"]
|
2688
2920
|
return self
|
2689
|
-
return run_gen_step(gen_step, async_=async_)
|
2921
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2690
2922
|
|
2691
2923
|
@classmethod
|
2692
2924
|
def from_token(cls, /, access_token: str, refresh_token: str) -> P115OpenClient:
|
@@ -2743,7 +2975,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2743
2975
|
"""更新 access_token 和 refresh_token (⚠️ 目前是 7200 秒内就要求刷新一次)
|
2744
2976
|
"""
|
2745
2977
|
def gen_step():
|
2746
|
-
resp = yield self.
|
2978
|
+
resp = yield self.login_refresh_token_open(
|
2747
2979
|
self.refresh_token,
|
2748
2980
|
async_=async_,
|
2749
2981
|
**request_kwargs,
|
@@ -2753,7 +2985,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2753
2985
|
self.refresh_token = data["refresh_token"]
|
2754
2986
|
access_token = self.access_token = data["access_token"]
|
2755
2987
|
return access_token
|
2756
|
-
return run_gen_step(gen_step, async_=async_)
|
2988
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
2757
2989
|
|
2758
2990
|
@overload
|
2759
2991
|
def download_url(
|
@@ -3136,9 +3368,675 @@ class P115OpenClient(ClientRequestMixin):
|
|
3136
3368
|
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
3137
3369
|
|
3138
3370
|
@overload
|
3139
|
-
def fs_info(
|
3371
|
+
def fs_info(
|
3372
|
+
self,
|
3373
|
+
payload: int | str | dict,
|
3374
|
+
/,
|
3375
|
+
base_url: bool | str | Callable[[], str] = False,
|
3376
|
+
*,
|
3377
|
+
async_: Literal[False] = False,
|
3378
|
+
**request_kwargs,
|
3379
|
+
) -> dict:
|
3380
|
+
...
|
3381
|
+
@overload
|
3382
|
+
def fs_info(
|
3383
|
+
self,
|
3384
|
+
payload: int | str | dict,
|
3385
|
+
/,
|
3386
|
+
base_url: bool | str | Callable[[], str] = False,
|
3387
|
+
*,
|
3388
|
+
async_: Literal[True],
|
3389
|
+
**request_kwargs,
|
3390
|
+
) -> Coroutine[Any, Any, dict]:
|
3391
|
+
...
|
3392
|
+
def fs_info(
|
3393
|
+
self,
|
3394
|
+
payload: int | str | dict,
|
3395
|
+
/,
|
3396
|
+
base_url: bool | str | Callable[[], str] = False,
|
3397
|
+
*,
|
3398
|
+
async_: Literal[False, True] = False,
|
3399
|
+
**request_kwargs,
|
3400
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3401
|
+
"""获取文件或目录详情
|
3402
|
+
|
3403
|
+
GET https://proapi.115.com/open/folder/get_info
|
3404
|
+
|
3405
|
+
.. hint::
|
3406
|
+
相当于 `P115Client.fs_category_get_app`
|
3407
|
+
|
3408
|
+
.. admonition:: Reference
|
3409
|
+
|
3410
|
+
https://www.yuque.com/115yun/open/rl8zrhe2nag21dfw
|
3411
|
+
|
3412
|
+
:payload:
|
3413
|
+
- file_id: int | str 💡 文件或目录的 id
|
3414
|
+
"""
|
3415
|
+
api = complete_proapi("/open/folder/get_info", base_url)
|
3416
|
+
if isinstance(payload, (int, str)):
|
3417
|
+
payload = {"file_id": payload}
|
3418
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
3419
|
+
|
3420
|
+
@overload
|
3421
|
+
def fs_mkdir(
|
3422
|
+
self,
|
3423
|
+
payload: str | dict,
|
3424
|
+
/,
|
3425
|
+
pid: int = 0,
|
3426
|
+
base_url: bool | str | Callable[[], str] = False,
|
3427
|
+
*,
|
3428
|
+
async_: Literal[False] = False,
|
3429
|
+
**request_kwargs,
|
3430
|
+
) -> dict:
|
3431
|
+
...
|
3432
|
+
@overload
|
3433
|
+
def fs_mkdir(
|
3434
|
+
self,
|
3435
|
+
payload: str | dict,
|
3436
|
+
/,
|
3437
|
+
pid: int = 0,
|
3438
|
+
base_url: bool | str | Callable[[], str] = False,
|
3439
|
+
*,
|
3440
|
+
async_: Literal[True],
|
3441
|
+
**request_kwargs,
|
3442
|
+
) -> Coroutine[Any, Any, dict]:
|
3443
|
+
...
|
3444
|
+
def fs_mkdir(
|
3445
|
+
self,
|
3446
|
+
payload: str | dict,
|
3447
|
+
/,
|
3448
|
+
pid: int = 0,
|
3449
|
+
base_url: bool | str | Callable[[], str] = False,
|
3450
|
+
*,
|
3451
|
+
async_: Literal[False, True] = False,
|
3452
|
+
**request_kwargs,
|
3453
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3454
|
+
"""新建目录
|
3455
|
+
|
3456
|
+
POST https://proapi.115.com/open/folder/add
|
3457
|
+
|
3458
|
+
.. admonition:: Reference
|
3459
|
+
|
3460
|
+
https://www.yuque.com/115yun/open/qur839kyx9cgxpxi
|
3461
|
+
|
3462
|
+
:payload:
|
3463
|
+
- file_name: str 💡 新建目录名称,限制255个字符
|
3464
|
+
- pid: int | str = 0 💡 新建目录所在的父目录ID (根目录的ID为0)
|
3465
|
+
"""
|
3466
|
+
api = complete_proapi("/open/folder/add", base_url)
|
3467
|
+
if isinstance(payload, str):
|
3468
|
+
payload = {"pid": pid, "file_name": payload}
|
3469
|
+
else:
|
3470
|
+
payload = {"pid": pid, **payload}
|
3471
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3472
|
+
|
3473
|
+
@overload
|
3474
|
+
def fs_move(
|
3475
|
+
self,
|
3476
|
+
payload: int | str | Iterable[int | str] | dict,
|
3477
|
+
/,
|
3478
|
+
pid: int = 0,
|
3479
|
+
base_url: bool | str | Callable[[], str] = False,
|
3480
|
+
*,
|
3481
|
+
async_: Literal[False] = False,
|
3482
|
+
**request_kwargs,
|
3483
|
+
) -> dict:
|
3484
|
+
...
|
3485
|
+
@overload
|
3486
|
+
def fs_move(
|
3487
|
+
self,
|
3488
|
+
payload: int | str | Iterable[int | str] | dict,
|
3489
|
+
/,
|
3490
|
+
pid: int = 0,
|
3491
|
+
base_url: bool | str | Callable[[], str] = False,
|
3492
|
+
*,
|
3493
|
+
async_: Literal[True],
|
3494
|
+
**request_kwargs,
|
3495
|
+
) -> Coroutine[Any, Any, dict]:
|
3496
|
+
...
|
3497
|
+
def fs_move(
|
3498
|
+
self,
|
3499
|
+
payload: int | str | Iterable[int | str] | dict,
|
3500
|
+
/,
|
3501
|
+
pid: int = 0,
|
3502
|
+
base_url: bool | str | Callable[[], str] = False,
|
3503
|
+
*,
|
3504
|
+
async_: Literal[False, True] = False,
|
3505
|
+
**request_kwargs,
|
3506
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3507
|
+
"""文件移动
|
3508
|
+
|
3509
|
+
POST https://proapi.115.com/open/ufile/move
|
3510
|
+
|
3511
|
+
.. admonition:: Reference
|
3512
|
+
|
3513
|
+
https://www.yuque.com/115yun/open/vc6fhi2mrkenmav2
|
3514
|
+
|
3515
|
+
:payload:
|
3516
|
+
- file_ids: int | str 💡 文件或目录的 id,多个用逗号 "," 隔开
|
3517
|
+
- to_cid: int | str = 0 💡 父目录 id
|
3518
|
+
"""
|
3519
|
+
api = complete_proapi("/open/ufile/move", base_url)
|
3520
|
+
if isinstance(payload, (int, str)):
|
3521
|
+
payload = {"file_ids": payload}
|
3522
|
+
elif isinstance(payload, dict):
|
3523
|
+
payload = dict(payload)
|
3524
|
+
else:
|
3525
|
+
payload = {"file_ids": ",".join(map(str, payload))}
|
3526
|
+
if not payload.get("file_ids"):
|
3527
|
+
return {"state": False, "message": "no op"}
|
3528
|
+
payload = cast(dict, payload)
|
3529
|
+
payload.setdefault("to_cid", pid)
|
3530
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3531
|
+
|
3532
|
+
@overload
|
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(
|
3140
4038
|
self,
|
3141
|
-
payload:
|
4039
|
+
payload: str | Iterable[str] | dict,
|
3142
4040
|
/,
|
3143
4041
|
base_url: bool | str | Callable[[], str] = False,
|
3144
4042
|
*,
|
@@ -3147,9 +4045,9 @@ class P115OpenClient(ClientRequestMixin):
|
|
3147
4045
|
) -> dict:
|
3148
4046
|
...
|
3149
4047
|
@overload
|
3150
|
-
def
|
4048
|
+
def offline_add_urls(
|
3151
4049
|
self,
|
3152
|
-
payload:
|
4050
|
+
payload: str | Iterable[str] | dict,
|
3153
4051
|
/,
|
3154
4052
|
base_url: bool | str | Callable[[], str] = False,
|
3155
4053
|
*,
|
@@ -3157,40 +4055,39 @@ class P115OpenClient(ClientRequestMixin):
|
|
3157
4055
|
**request_kwargs,
|
3158
4056
|
) -> Coroutine[Any, Any, dict]:
|
3159
4057
|
...
|
3160
|
-
def
|
4058
|
+
def offline_add_urls(
|
3161
4059
|
self,
|
3162
|
-
payload:
|
4060
|
+
payload: str | Iterable[str] | dict,
|
3163
4061
|
/,
|
3164
4062
|
base_url: bool | str | Callable[[], str] = False,
|
3165
4063
|
*,
|
3166
4064
|
async_: Literal[False, True] = False,
|
3167
4065
|
**request_kwargs,
|
3168
4066
|
) -> dict | Coroutine[Any, Any, dict]:
|
3169
|
-
"""
|
4067
|
+
"""添加云下载链接任务
|
3170
4068
|
|
3171
|
-
|
3172
|
-
|
3173
|
-
.. hint::
|
3174
|
-
相当于 `P115Client.fs_category_get_app`
|
4069
|
+
POST https://proapi.115.com/open/offline/add_task_urls
|
3175
4070
|
|
3176
4071
|
.. admonition:: Reference
|
3177
4072
|
|
3178
|
-
https://www.yuque.com/115yun/open/
|
4073
|
+
https://www.yuque.com/115yun/open/zkyfq2499gdn3mty
|
3179
4074
|
|
3180
4075
|
:payload:
|
3181
|
-
-
|
4076
|
+
- urls: str 💡 链接,用 "\\n" 分隔,支持HTTP、HTTPS、FTP、磁力链和电驴链接
|
4077
|
+
- wp_path_id: int | str = <default> 💡 保存到目录的 id
|
3182
4078
|
"""
|
3183
|
-
api = complete_proapi("/open/
|
3184
|
-
if isinstance(payload,
|
3185
|
-
payload = {"
|
3186
|
-
|
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)
|
3187
4085
|
|
3188
4086
|
@overload
|
3189
|
-
def
|
4087
|
+
def offline_clear(
|
3190
4088
|
self,
|
3191
|
-
payload:
|
4089
|
+
payload: int | dict = 0,
|
3192
4090
|
/,
|
3193
|
-
pid: int = 0,
|
3194
4091
|
base_url: bool | str | Callable[[], str] = False,
|
3195
4092
|
*,
|
3196
4093
|
async_: Literal[False] = False,
|
@@ -3198,52 +4095,53 @@ class P115OpenClient(ClientRequestMixin):
|
|
3198
4095
|
) -> dict:
|
3199
4096
|
...
|
3200
4097
|
@overload
|
3201
|
-
def
|
4098
|
+
def offline_clear(
|
3202
4099
|
self,
|
3203
|
-
payload:
|
4100
|
+
payload: int | dict = 0,
|
3204
4101
|
/,
|
3205
|
-
pid: int = 0,
|
3206
4102
|
base_url: bool | str | Callable[[], str] = False,
|
3207
4103
|
*,
|
3208
4104
|
async_: Literal[True],
|
3209
4105
|
**request_kwargs,
|
3210
4106
|
) -> Coroutine[Any, Any, dict]:
|
3211
4107
|
...
|
3212
|
-
def
|
4108
|
+
def offline_clear(
|
3213
4109
|
self,
|
3214
|
-
payload:
|
4110
|
+
payload: int | dict = 0,
|
3215
4111
|
/,
|
3216
|
-
pid: int = 0,
|
3217
4112
|
base_url: bool | str | Callable[[], str] = False,
|
3218
4113
|
*,
|
3219
4114
|
async_: Literal[False, True] = False,
|
3220
4115
|
**request_kwargs,
|
3221
4116
|
) -> dict | Coroutine[Any, Any, dict]:
|
3222
|
-
"""
|
4117
|
+
"""清空云下载任务
|
3223
4118
|
|
3224
|
-
POST https://proapi.115.com/open/
|
4119
|
+
POST https://proapi.115.com/open/offline/clear_task
|
3225
4120
|
|
3226
4121
|
.. admonition:: Reference
|
3227
4122
|
|
3228
|
-
https://www.yuque.com/115yun/open/
|
4123
|
+
https://www.yuque.com/115yun/open/uu5i4urb5ylqwfy4
|
3229
4124
|
|
3230
4125
|
:payload:
|
3231
|
-
-
|
3232
|
-
|
4126
|
+
- flag: int = 0 💡 标识,用于对应某种情况
|
4127
|
+
|
4128
|
+
- 0: 已完成
|
4129
|
+
- 1: 全部
|
4130
|
+
- 2: 已失败
|
4131
|
+
- 3: 进行中
|
4132
|
+
- 4: 已完成+删除源文件
|
4133
|
+
- 5: 全部+删除源文件
|
3233
4134
|
"""
|
3234
|
-
api = complete_proapi("/open/
|
3235
|
-
if isinstance(payload,
|
3236
|
-
payload = {"
|
3237
|
-
else:
|
3238
|
-
payload = {"pid": pid, **payload}
|
4135
|
+
api = complete_proapi("/open/offline/clear_task", base_url)
|
4136
|
+
if isinstance(payload, int):
|
4137
|
+
payload = {"flag": payload}
|
3239
4138
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3240
4139
|
|
3241
4140
|
@overload
|
3242
|
-
def
|
4141
|
+
def offline_list(
|
3243
4142
|
self,
|
3244
|
-
payload: int |
|
4143
|
+
payload: int | dict = 1,
|
3245
4144
|
/,
|
3246
|
-
pid: int = 0,
|
3247
4145
|
base_url: bool | str | Callable[[], str] = False,
|
3248
4146
|
*,
|
3249
4147
|
async_: Literal[False] = False,
|
@@ -3251,56 +4149,44 @@ class P115OpenClient(ClientRequestMixin):
|
|
3251
4149
|
) -> dict:
|
3252
4150
|
...
|
3253
4151
|
@overload
|
3254
|
-
def
|
4152
|
+
def offline_list(
|
3255
4153
|
self,
|
3256
|
-
payload: int |
|
4154
|
+
payload: int | dict = 1,
|
3257
4155
|
/,
|
3258
|
-
pid: int = 0,
|
3259
4156
|
base_url: bool | str | Callable[[], str] = False,
|
3260
4157
|
*,
|
3261
4158
|
async_: Literal[True],
|
3262
4159
|
**request_kwargs,
|
3263
4160
|
) -> Coroutine[Any, Any, dict]:
|
3264
4161
|
...
|
3265
|
-
def
|
4162
|
+
def offline_list(
|
3266
4163
|
self,
|
3267
|
-
payload: int |
|
4164
|
+
payload: int | dict = 1,
|
3268
4165
|
/,
|
3269
|
-
pid: int = 0,
|
3270
4166
|
base_url: bool | str | Callable[[], str] = False,
|
3271
4167
|
*,
|
3272
4168
|
async_: Literal[False, True] = False,
|
3273
4169
|
**request_kwargs,
|
3274
4170
|
) -> dict | Coroutine[Any, Any, dict]:
|
3275
|
-
"""
|
4171
|
+
"""获取用户云下载任务列表
|
3276
4172
|
|
3277
|
-
|
4173
|
+
GET https://proapi.115.com/open/offline/get_task_list
|
3278
4174
|
|
3279
4175
|
.. admonition:: Reference
|
3280
4176
|
|
3281
|
-
https://www.yuque.com/115yun/open/
|
4177
|
+
https://www.yuque.com/115yun/open/av2mluz7uwigz74k
|
3282
4178
|
|
3283
4179
|
:payload:
|
3284
|
-
-
|
3285
|
-
- to_cid: int | str = 0 💡 父目录 id
|
4180
|
+
- page: int | str = 1
|
3286
4181
|
"""
|
3287
|
-
api = complete_proapi("/open/
|
3288
|
-
if isinstance(payload,
|
3289
|
-
payload = {"
|
3290
|
-
|
3291
|
-
payload = dict(payload)
|
3292
|
-
else:
|
3293
|
-
payload = {"file_ids": ",".join(map(str, payload))}
|
3294
|
-
if not payload.get("file_ids"):
|
3295
|
-
return {"state": False, "message": "no op"}
|
3296
|
-
payload = cast(dict, payload)
|
3297
|
-
payload.setdefault("to_cid", pid)
|
3298
|
-
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
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)
|
3299
4186
|
|
3300
4187
|
@overload
|
3301
|
-
def
|
4188
|
+
def offline_quota_info(
|
3302
4189
|
self,
|
3303
|
-
payload: str | dict = ".",
|
3304
4190
|
/,
|
3305
4191
|
base_url: bool | str | Callable[[], str] = False,
|
3306
4192
|
*,
|
@@ -3309,9 +4195,8 @@ class P115OpenClient(ClientRequestMixin):
|
|
3309
4195
|
) -> dict:
|
3310
4196
|
...
|
3311
4197
|
@overload
|
3312
|
-
def
|
4198
|
+
def offline_quota_info(
|
3313
4199
|
self,
|
3314
|
-
payload: str | dict = ".",
|
3315
4200
|
/,
|
3316
4201
|
base_url: bool | str | Callable[[], str] = False,
|
3317
4202
|
*,
|
@@ -3319,88 +4204,30 @@ class P115OpenClient(ClientRequestMixin):
|
|
3319
4204
|
**request_kwargs,
|
3320
4205
|
) -> Coroutine[Any, Any, dict]:
|
3321
4206
|
...
|
3322
|
-
def
|
4207
|
+
def offline_quota_info(
|
3323
4208
|
self,
|
3324
|
-
payload: str | dict = ".",
|
3325
4209
|
/,
|
3326
4210
|
base_url: bool | str | Callable[[], str] = False,
|
3327
4211
|
*,
|
3328
4212
|
async_: Literal[False, True] = False,
|
3329
4213
|
**request_kwargs,
|
3330
4214
|
) -> dict | Coroutine[Any, Any, dict]:
|
3331
|
-
"""
|
3332
|
-
|
3333
|
-
GET https://proapi.115.com/open/ufile/search
|
4215
|
+
"""获取云下载配额信息
|
3334
4216
|
|
3335
|
-
|
3336
|
-
相当于 `P115Client.fs_search_app2`
|
4217
|
+
GET https://proapi.115.com/open/offline/get_quota_info
|
3337
4218
|
|
3338
4219
|
.. admonition:: Reference
|
3339
4220
|
|
3340
|
-
https://www.yuque.com/115yun/open/
|
3341
|
-
|
3342
|
-
:payload:
|
3343
|
-
- aid: int | str = 1 💡 area_id。1:正常文件 7:回收站文件 12:瞬间文件 120:彻底删除文件、简历附件
|
3344
|
-
- asc: 0 | 1 = <default> 💡 是否升序排列
|
3345
|
-
- cid: int | str = 0 💡 目录 id。cid=-1 时,表示不返回列表任何内容
|
3346
|
-
- count_folders: 0 | 1 = <default>
|
3347
|
-
- date: str = <default> 💡 筛选日期
|
3348
|
-
- fc: 0 | 1 = <default> 💡 只显示文件或目录。1:只显示目录 2:只显示文件
|
3349
|
-
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
3350
|
-
- file_label: int | str = <default> 💡 标签 id
|
3351
|
-
- format: str = "json" 💡 输出格式(不用管)
|
3352
|
-
- gte_day: str 💡 搜索结果匹配的开始时间;格式:YYYY-MM-DD
|
3353
|
-
- limit: int = 32 💡 一页大小,意思就是 page_size
|
3354
|
-
- lte_day: str 💡 搜索结果匹配的结束时间;格式:YYYY-MM-DD
|
3355
|
-
- o: str = <default> 💡 用某字段排序
|
3356
|
-
|
3357
|
-
- "file_name": 文件名
|
3358
|
-
- "file_size": 文件大小
|
3359
|
-
- "file_type": 文件种类
|
3360
|
-
- "user_utime": 修改时间
|
3361
|
-
- "user_ptime": 创建时间
|
3362
|
-
- "user_otime": 上一次打开时间
|
3363
|
-
|
3364
|
-
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
3365
|
-
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
3366
|
-
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
3367
|
-
- show_dir: 0 | 1 = 1
|
3368
|
-
- source: str = <default>
|
3369
|
-
- star: 0 | 1 = <default>
|
3370
|
-
- suffix: str = <default>
|
3371
|
-
- type: int = <default> 💡 文件类型
|
3372
|
-
|
3373
|
-
- 0: 全部(仅当前目录)
|
3374
|
-
- 1: 文档
|
3375
|
-
- 2: 图片
|
3376
|
-
- 3: 音频
|
3377
|
-
- 4: 视频
|
3378
|
-
- 5: 压缩包
|
3379
|
-
- 6: 软件/应用
|
3380
|
-
- 7: 书籍
|
3381
|
-
- 99: 仅文件
|
3382
|
-
|
3383
|
-
- version: str = <default> 💡 版本号,比如 3.1
|
4221
|
+
https://www.yuque.com/115yun/open/gif2n3smh54kyg0p
|
3384
4222
|
"""
|
3385
|
-
api = complete_proapi("/open/
|
3386
|
-
|
3387
|
-
payload = {
|
3388
|
-
"aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
|
3389
|
-
"show_dir": 1, "search_value": payload,
|
3390
|
-
}
|
3391
|
-
else:
|
3392
|
-
payload = {
|
3393
|
-
"aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
|
3394
|
-
"show_dir": 1, "search_value": ".", **payload,
|
3395
|
-
}
|
3396
|
-
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)
|
3397
4225
|
|
3398
4226
|
@overload
|
3399
|
-
def
|
4227
|
+
def offline_remove(
|
3400
4228
|
self,
|
3401
|
-
payload:
|
4229
|
+
payload: str | dict,
|
3402
4230
|
/,
|
3403
|
-
star: bool = True,
|
3404
4231
|
base_url: bool | str | Callable[[], str] = False,
|
3405
4232
|
*,
|
3406
4233
|
async_: Literal[False] = False,
|
@@ -3408,53 +4235,44 @@ class P115OpenClient(ClientRequestMixin):
|
|
3408
4235
|
) -> dict:
|
3409
4236
|
...
|
3410
4237
|
@overload
|
3411
|
-
def
|
4238
|
+
def offline_remove(
|
3412
4239
|
self,
|
3413
|
-
payload:
|
4240
|
+
payload: str | dict,
|
3414
4241
|
/,
|
3415
|
-
star: bool = True,
|
3416
4242
|
base_url: bool | str | Callable[[], str] = False,
|
3417
4243
|
*,
|
3418
4244
|
async_: Literal[True],
|
3419
4245
|
**request_kwargs,
|
3420
4246
|
) -> Coroutine[Any, Any, dict]:
|
3421
4247
|
...
|
3422
|
-
def
|
4248
|
+
def offline_remove(
|
3423
4249
|
self,
|
3424
|
-
payload:
|
4250
|
+
payload: str | dict,
|
3425
4251
|
/,
|
3426
|
-
star: bool = True,
|
3427
4252
|
base_url: bool | str | Callable[[], str] = False,
|
3428
4253
|
*,
|
3429
4254
|
async_: Literal[False, True] = False,
|
3430
4255
|
**request_kwargs,
|
3431
4256
|
) -> dict | Coroutine[Any, Any, dict]:
|
3432
|
-
"""
|
4257
|
+
"""删除用户云下载任务
|
3433
4258
|
|
3434
|
-
|
3435
|
-
|
4259
|
+
POST https://proapi.115.com/open/offline/del_task
|
4260
|
+
|
4261
|
+
.. admonition:: Reference
|
4262
|
+
|
4263
|
+
https://www.yuque.com/115yun/open/pmgwc86lpcy238nw
|
3436
4264
|
|
3437
4265
|
:payload:
|
3438
|
-
-
|
3439
|
-
-
|
3440
|
-
- file_id[1]: int | str
|
3441
|
-
- ...
|
3442
|
-
- star: 0 | 1 = 1
|
4266
|
+
- info_hash: str 💡 待删除任务的 info_hash
|
4267
|
+
- del_source_file: 0 | 1 = <default> 💡 是否删除源文件 1:删除 0:不删除
|
3443
4268
|
"""
|
3444
|
-
api =
|
3445
|
-
if isinstance(payload,
|
3446
|
-
payload = {"
|
3447
|
-
|
3448
|
-
payload = {f"file_id[{i}]": id for i, id in enumerate(payload)}
|
3449
|
-
if not payload:
|
3450
|
-
return {"state": False, "message": "no op"}
|
3451
|
-
payload["star"] = int(star)
|
3452
|
-
else:
|
3453
|
-
payload = {"star": int(star), **payload}
|
3454
|
-
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)
|
3455
4273
|
|
3456
4274
|
@overload
|
3457
|
-
def
|
4275
|
+
def offline_torrent_info(
|
3458
4276
|
self,
|
3459
4277
|
payload: dict,
|
3460
4278
|
/,
|
@@ -3465,7 +4283,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3465
4283
|
) -> dict:
|
3466
4284
|
...
|
3467
4285
|
@overload
|
3468
|
-
def
|
4286
|
+
def offline_torrent_info(
|
3469
4287
|
self,
|
3470
4288
|
payload: dict,
|
3471
4289
|
/,
|
@@ -3475,7 +4293,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3475
4293
|
**request_kwargs,
|
3476
4294
|
) -> Coroutine[Any, Any, dict]:
|
3477
4295
|
...
|
3478
|
-
def
|
4296
|
+
def offline_torrent_info(
|
3479
4297
|
self,
|
3480
4298
|
payload: dict,
|
3481
4299
|
/,
|
@@ -3484,27 +4302,19 @@ class P115OpenClient(ClientRequestMixin):
|
|
3484
4302
|
async_: Literal[False, True] = False,
|
3485
4303
|
**request_kwargs,
|
3486
4304
|
) -> dict | Coroutine[Any, Any, dict]:
|
3487
|
-
"""
|
3488
|
-
|
3489
|
-
POST https://proapi.115.com/open/ufile/update
|
4305
|
+
"""解析 BT 种子
|
3490
4306
|
|
3491
|
-
|
3492
|
-
即使文件已经被删除,也可以操作成功
|
4307
|
+
POST https://proapi.115.com/open/offline/torrent
|
3493
4308
|
|
3494
4309
|
.. admonition:: Reference
|
3495
4310
|
|
3496
|
-
https://www.yuque.com/115yun/open/
|
4311
|
+
https://www.yuque.com/115yun/open/evez3u50cemoict1
|
3497
4312
|
|
3498
4313
|
:payload:
|
3499
|
-
-
|
3500
|
-
-
|
3501
|
-
- file_id[1]: int | str
|
3502
|
-
- ...
|
3503
|
-
- file_name: str = <default> 💡 文件名
|
3504
|
-
- star: 0 | 1 = <default> 💡 是否星标:0:取消星标 1:设置星标
|
3505
|
-
- ...
|
4314
|
+
- torrent_sha1: str 💡 种子文件的 sha1
|
4315
|
+
- pick_code: str 💡 种子文件的提取码
|
3506
4316
|
"""
|
3507
|
-
api = complete_proapi("/open/
|
4317
|
+
api = complete_proapi("/open/offline/torrent", base_url)
|
3508
4318
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3509
4319
|
|
3510
4320
|
@overload
|
@@ -3542,7 +4352,8 @@ class P115OpenClient(ClientRequestMixin):
|
|
3542
4352
|
|
3543
4353
|
POST https://proapi.115.com/open/rb/del
|
3544
4354
|
|
3545
|
-
..
|
4355
|
+
.. admonition:: Reference
|
4356
|
+
|
3546
4357
|
https://www.yuque.com/115yun/open/gwtof85nmboulrce
|
3547
4358
|
|
3548
4359
|
:payload:
|
@@ -3900,7 +4711,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3900
4711
|
check_response(resp)
|
3901
4712
|
resp["data"] = {**payload, **resp["data"], "sha1": filesha1, "cid": pid}
|
3902
4713
|
return resp
|
3903
|
-
return run_gen_step(gen_step, async_=async_)
|
4714
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
3904
4715
|
|
3905
4716
|
@overload
|
3906
4717
|
def upload_file(
|
@@ -4244,7 +5055,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
4244
5055
|
async_=async_, # type: ignore
|
4245
5056
|
**request_kwargs,
|
4246
5057
|
)
|
4247
|
-
return run_gen_step(gen_step, async_=async_)
|
5058
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4248
5059
|
|
4249
5060
|
@overload
|
4250
5061
|
def user_info(
|
@@ -4295,7 +5106,19 @@ class P115OpenClient(ClientRequestMixin):
|
|
4295
5106
|
fs_move_open = fs_move
|
4296
5107
|
fs_search_open = fs_search
|
4297
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
|
4298
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
|
4299
5122
|
recyclebin_clean_open = recyclebin_clean
|
4300
5123
|
recyclebin_list_open = recyclebin_list
|
4301
5124
|
recyclebin_revert_open = recyclebin_revert
|
@@ -4489,10 +5312,6 @@ class P115Client(P115OpenClient):
|
|
4489
5312
|
"""
|
4490
5313
|
self.cookies = None
|
4491
5314
|
|
4492
|
-
@locked_cacheproperty
|
4493
|
-
def request_kwargs(self, /) -> dict:
|
4494
|
-
return {}
|
4495
|
-
|
4496
5315
|
@locked_cacheproperty
|
4497
5316
|
def user_id(self, /) -> int:
|
4498
5317
|
cookie_uid = self.cookies.get("UID")
|
@@ -4617,7 +5436,7 @@ class P115Client(P115OpenClient):
|
|
4617
5436
|
)
|
4618
5437
|
setattr(self, "check_for_relogin", check_for_relogin)
|
4619
5438
|
return self
|
4620
|
-
return run_gen_step(gen_step, async_=async_)
|
5439
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4621
5440
|
|
4622
5441
|
@locked_cacheproperty
|
4623
5442
|
def request_lock(self, /) -> Lock:
|
@@ -4789,7 +5608,7 @@ class P115Client(P115OpenClient):
|
|
4789
5608
|
check_response(resp)
|
4790
5609
|
setattr(self, "cookies", resp["data"]["cookie"])
|
4791
5610
|
return self
|
4792
|
-
return run_gen_step(gen_step, async_=async_)
|
5611
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4793
5612
|
|
4794
5613
|
@overload
|
4795
5614
|
def login_with_app(
|
@@ -4921,7 +5740,7 @@ class P115Client(P115OpenClient):
|
|
4921
5740
|
async_=async_,
|
4922
5741
|
**request_kwargs,
|
4923
5742
|
)
|
4924
|
-
return run_gen_step(gen_step, async_=async_)
|
5743
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4925
5744
|
|
4926
5745
|
@overload
|
4927
5746
|
def login_without_app(
|
@@ -4979,7 +5798,7 @@ class P115Client(P115OpenClient):
|
|
4979
5798
|
)
|
4980
5799
|
check_response(resp)
|
4981
5800
|
return uid
|
4982
|
-
return run_gen_step(gen_step, async_=async_)
|
5801
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
4983
5802
|
|
4984
5803
|
@overload
|
4985
5804
|
def login_with_open(
|
@@ -5031,7 +5850,7 @@ class P115Client(P115OpenClient):
|
|
5031
5850
|
resp = yield self.login_qrcode_scan_confirm(login_uid, async_=async_, **request_kwargs)
|
5032
5851
|
check_response(resp)
|
5033
5852
|
return self.login_qrcode_access_token_open(login_uid, async_=async_, **request_kwargs)
|
5034
|
-
return run_gen_step(gen_step, async_=async_)
|
5853
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5035
5854
|
|
5036
5855
|
@overload
|
5037
5856
|
def login_another_app(
|
@@ -5175,7 +5994,7 @@ class P115Client(P115OpenClient):
|
|
5175
5994
|
if self is not inst and ssoent == inst.login_ssoent:
|
5176
5995
|
warn(f"login with the same ssoent {ssoent!r}, {self!r} will expire within 60 seconds", category=P115Warning)
|
5177
5996
|
return inst
|
5178
|
-
return run_gen_step(gen_step, async_=async_)
|
5997
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5179
5998
|
|
5180
5999
|
@overload
|
5181
6000
|
def login_another_open(
|
@@ -5269,7 +6088,7 @@ class P115Client(P115OpenClient):
|
|
5269
6088
|
inst.access_token = data["access_token"]
|
5270
6089
|
inst.app_id = app_id
|
5271
6090
|
return inst
|
5272
|
-
return run_gen_step(gen_step, async_=async_)
|
6091
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5273
6092
|
|
5274
6093
|
@overload
|
5275
6094
|
@classmethod
|
@@ -5388,7 +6207,7 @@ class P115Client(P115OpenClient):
|
|
5388
6207
|
resp = yield cls.login_qrcode_scan_result(uid, app, async_=async_, **request_kwargs)
|
5389
6208
|
cookies = check_response(resp)["data"]["cookie"]
|
5390
6209
|
return cls(cookies, check_for_relogin=check_for_relogin)
|
5391
|
-
return run_gen_step(gen_step, async_=async_)
|
6210
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5392
6211
|
|
5393
6212
|
@overload
|
5394
6213
|
def logout(
|
@@ -5540,7 +6359,7 @@ class P115Client(P115OpenClient):
|
|
5540
6359
|
if async_:
|
5541
6360
|
fetch_cert_headers = ensure_async(fetch_cert_headers)
|
5542
6361
|
if fetch_cert_headers_argcount:
|
5543
|
-
fetch_cert_headers =
|
6362
|
+
fetch_cert_headers = cast(Callable, fetch_cert_headers)(async_)
|
5544
6363
|
if revert_cert_headers is not None and async_:
|
5545
6364
|
revert_cert_headers = ensure_async(revert_cert_headers)
|
5546
6365
|
if is_open_api:
|
@@ -5594,8 +6413,7 @@ class P115Client(P115OpenClient):
|
|
5594
6413
|
cert: str = headers["authorization"]
|
5595
6414
|
else:
|
5596
6415
|
cert = headers["cookie"]
|
5597
|
-
resp = yield
|
5598
|
-
cast(Callable, request),
|
6416
|
+
resp = yield cast(Callable, request)(
|
5599
6417
|
url=url,
|
5600
6418
|
method=method,
|
5601
6419
|
**request_kwargs,
|
@@ -5608,10 +6426,10 @@ class P115Client(P115OpenClient):
|
|
5608
6426
|
not is_auth_error and
|
5609
6427
|
get_status_code(e) != 405
|
5610
6428
|
):
|
5611
|
-
yield
|
6429
|
+
yield revert_cert_headers(cert_headers)
|
5612
6430
|
if not need_to_check:
|
5613
6431
|
raise
|
5614
|
-
res = yield
|
6432
|
+
res = yield cast(Callable, check_for_relogin)(e)
|
5615
6433
|
if not res if isinstance(res, bool) else res != 405:
|
5616
6434
|
raise
|
5617
6435
|
if fetch_cert_headers is not None:
|
@@ -5660,11 +6478,11 @@ class P115Client(P115OpenClient):
|
|
5660
6478
|
lock.release()
|
5661
6479
|
else:
|
5662
6480
|
if cert_headers is not None and revert_cert_headers is not None:
|
5663
|
-
yield
|
6481
|
+
yield revert_cert_headers(cert_headers)
|
5664
6482
|
if check and isinstance(resp, dict):
|
5665
6483
|
check_response(resp)
|
5666
6484
|
return resp
|
5667
|
-
return run_gen_step(gen_step, async_=async_)
|
6485
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
5668
6486
|
|
5669
6487
|
def request(
|
5670
6488
|
self,
|
@@ -6516,15 +7334,14 @@ class P115Client(P115OpenClient):
|
|
6516
7334
|
if "sign" not in payload:
|
6517
7335
|
resp = yield self.captcha_sign(async_=async_)
|
6518
7336
|
payload["sign"] = resp["sign"]
|
6519
|
-
return
|
6520
|
-
self.request,
|
7337
|
+
return self.request(
|
6521
7338
|
url=api,
|
6522
7339
|
method="POST",
|
6523
7340
|
data=payload,
|
6524
7341
|
async_=async_,
|
6525
7342
|
**request_kwargs,
|
6526
7343
|
)
|
6527
|
-
return run_gen_step(gen_step, async_=async_)
|
7344
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
6528
7345
|
|
6529
7346
|
########## Download API ##########
|
6530
7347
|
|
@@ -15099,7 +15916,7 @@ class P115Client(P115OpenClient):
|
|
15099
15916
|
if device is None:
|
15100
15917
|
return None
|
15101
15918
|
return device["icon"]
|
15102
|
-
return run_gen_step(gen_step, async_=async_)
|
15919
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
15103
15920
|
|
15104
15921
|
@overload
|
15105
15922
|
def login_open_auth_detail(
|
@@ -15623,7 +16440,7 @@ class P115Client(P115OpenClient):
|
|
15623
16440
|
return get_default_request()(url=api, async_=async_, **request_kwargs)
|
15624
16441
|
else:
|
15625
16442
|
return request(url=api, **request_kwargs)
|
15626
|
-
return run_gen_step(gen_step, async_=async_)
|
16443
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
15627
16444
|
|
15628
16445
|
@overload
|
15629
16446
|
def logout_by_ssoent(
|
@@ -16716,7 +17533,7 @@ class P115Client(P115OpenClient):
|
|
16716
17533
|
method = self._offline_lixianssp_post
|
16717
17534
|
return method(payload, ac, async_=async_, ecdh_encrypt=ecdh_encrypt, **request_kwargs)
|
16718
17535
|
|
16719
|
-
@overload
|
17536
|
+
@overload # type: ignore
|
16720
17537
|
def offline_add_torrent(
|
16721
17538
|
self,
|
16722
17539
|
payload: str | dict,
|
@@ -16758,8 +17575,8 @@ class P115Client(P115OpenClient):
|
|
16758
17575
|
|
16759
17576
|
:payload:
|
16760
17577
|
- info_hash: str 💡 种子文件的 info_hash
|
16761
|
-
- wanted: str = <default> 💡
|
16762
|
-
- savepath: str = <default> 💡
|
17578
|
+
- wanted: str = <default> 💡 选择文件进行下载(是数字索引,从 0 开始计数,用 "," 分隔)
|
17579
|
+
- savepath: str = <default> 💡 保存到 `wp_path_id` 对应目录下的相对路径
|
16763
17580
|
- wp_path_id: int | str = <default> 💡 保存到目录的 id
|
16764
17581
|
"""
|
16765
17582
|
if isinstance(payload, str):
|
@@ -16810,7 +17627,7 @@ class P115Client(P115OpenClient):
|
|
16810
17627
|
payload = {"url": payload}
|
16811
17628
|
return self._offline_post(payload, "add_task_url", use_web_api=use_web_api, async_=async_, **request_kwargs)
|
16812
17629
|
|
16813
|
-
@overload
|
17630
|
+
@overload # type: ignore
|
16814
17631
|
def offline_add_urls(
|
16815
17632
|
self,
|
16816
17633
|
payload: str | Iterable[str] | dict,
|
@@ -16853,7 +17670,7 @@ class P115Client(P115OpenClient):
|
|
16853
17670
|
- wp_path_id: int | str = <default> 💡 保存到目录的 id
|
16854
17671
|
"""
|
16855
17672
|
if isinstance(payload, str):
|
16856
|
-
payload = payload.strip().split("\n")
|
17673
|
+
payload = payload.strip("\n").split("\n")
|
16857
17674
|
if not isinstance(payload, dict):
|
16858
17675
|
payload = {f"url[{i}]": url for i, url in enumerate(payload)}
|
16859
17676
|
if not payload:
|
@@ -16863,7 +17680,7 @@ class P115Client(P115OpenClient):
|
|
16863
17680
|
@overload
|
16864
17681
|
def offline_clear(
|
16865
17682
|
self,
|
16866
|
-
payload: int | dict,
|
17683
|
+
payload: int | dict = 0,
|
16867
17684
|
/,
|
16868
17685
|
base_url: None | bool | str | Callable[[], str] = None,
|
16869
17686
|
*,
|
@@ -16874,7 +17691,7 @@ class P115Client(P115OpenClient):
|
|
16874
17691
|
@overload
|
16875
17692
|
def offline_clear(
|
16876
17693
|
self,
|
16877
|
-
payload: int | dict,
|
17694
|
+
payload: int | dict = 0,
|
16878
17695
|
/,
|
16879
17696
|
base_url: None | bool | str | Callable[[], str] = None,
|
16880
17697
|
*,
|
@@ -16884,7 +17701,7 @@ class P115Client(P115OpenClient):
|
|
16884
17701
|
...
|
16885
17702
|
def offline_clear(
|
16886
17703
|
self,
|
16887
|
-
payload: int | dict =
|
17704
|
+
payload: int | dict = 0,
|
16888
17705
|
/,
|
16889
17706
|
base_url: None | bool | str | Callable[[], str] = None,
|
16890
17707
|
*,
|
@@ -16907,11 +17724,6 @@ class P115Client(P115OpenClient):
|
|
16907
17724
|
"""
|
16908
17725
|
api = complete_lixian_api("?ct=lixian&ac=task_clear", base_url=base_url)
|
16909
17726
|
if isinstance(payload, int):
|
16910
|
-
flag = payload
|
16911
|
-
if flag < 0:
|
16912
|
-
flag = 0
|
16913
|
-
elif flag > 5:
|
16914
|
-
flag = 5
|
16915
17727
|
payload = {"flag": payload}
|
16916
17728
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
16917
17729
|
|
@@ -16985,7 +17797,7 @@ class P115Client(P115OpenClient):
|
|
16985
17797
|
api = complete_api("/?ct=offline&ac=space", base_url=base_url)
|
16986
17798
|
return self.request(url=api, async_=async_, **request_kwargs)
|
16987
17799
|
|
16988
|
-
@overload
|
17800
|
+
@overload # type: ignore
|
16989
17801
|
def offline_list(
|
16990
17802
|
self,
|
16991
17803
|
payload: int | dict = 1,
|
@@ -17021,7 +17833,7 @@ class P115Client(P115OpenClient):
|
|
17021
17833
|
POST https://lixian.115.com/lixian/?ct=lixian&ac=task_lists
|
17022
17834
|
|
17023
17835
|
:payload:
|
17024
|
-
- page: int | str
|
17836
|
+
- page: int | str = 1
|
17025
17837
|
"""
|
17026
17838
|
api = complete_lixian_api("?ct=lixian&ac=task_lists", base_url=base_url)
|
17027
17839
|
if isinstance(payload, int):
|
@@ -17136,7 +17948,7 @@ class P115Client(P115OpenClient):
|
|
17136
17948
|
@overload
|
17137
17949
|
def offline_remove(
|
17138
17950
|
self,
|
17139
|
-
payload: str | dict,
|
17951
|
+
payload: str | Iterable[str] | dict,
|
17140
17952
|
/,
|
17141
17953
|
base_url: None | bool | str | Callable[[], str] = None,
|
17142
17954
|
*,
|
@@ -17147,7 +17959,7 @@ class P115Client(P115OpenClient):
|
|
17147
17959
|
@overload
|
17148
17960
|
def offline_remove(
|
17149
17961
|
self,
|
17150
|
-
payload: str | dict,
|
17962
|
+
payload: str | Iterable[str] | dict,
|
17151
17963
|
/,
|
17152
17964
|
base_url: None | bool | str | Callable[[], str] = None,
|
17153
17965
|
*,
|
@@ -17157,7 +17969,7 @@ class P115Client(P115OpenClient):
|
|
17157
17969
|
...
|
17158
17970
|
def offline_remove(
|
17159
17971
|
self,
|
17160
|
-
payload: str | dict,
|
17972
|
+
payload: str | Iterable[str] | dict,
|
17161
17973
|
/,
|
17162
17974
|
base_url: None | bool | str | Callable[[], str] = None,
|
17163
17975
|
*,
|
@@ -19522,7 +20334,7 @@ class P115Client(P115OpenClient):
|
|
19522
20334
|
if resp["state"]:
|
19523
20335
|
self.user_key = resp["data"]["userkey"]
|
19524
20336
|
return resp
|
19525
|
-
return run_gen_step(gen_step, async_=async_)
|
20337
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
19526
20338
|
|
19527
20339
|
@overload
|
19528
20340
|
def upload_resume(
|
@@ -19889,7 +20701,7 @@ class P115Client(P115OpenClient):
|
|
19889
20701
|
"pickcode": resp["pickcode"],
|
19890
20702
|
}
|
19891
20703
|
return resp
|
19892
|
-
return run_gen_step(gen_step, async_=async_)
|
20704
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
19893
20705
|
|
19894
20706
|
@overload
|
19895
20707
|
def upload_file_sample(
|
@@ -20025,7 +20837,7 @@ class P115Client(P115OpenClient):
|
|
20025
20837
|
async_=async_,
|
20026
20838
|
**request_kwargs,
|
20027
20839
|
)
|
20028
|
-
return run_gen_step(gen_step, async_=async_)
|
20840
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
20029
20841
|
|
20030
20842
|
@overload # type: ignore
|
20031
20843
|
def upload_file(
|
@@ -20384,7 +21196,7 @@ class P115Client(P115OpenClient):
|
|
20384
21196
|
async_=async_, # type: ignore
|
20385
21197
|
**request_kwargs,
|
20386
21198
|
)
|
20387
|
-
return run_gen_step(gen_step, async_=async_)
|
21199
|
+
return run_gen_step(gen_step, simple=True, async_=async_)
|
20388
21200
|
|
20389
21201
|
########## User API ##########
|
20390
21202
|
|