p115client 0.0.5.10.9__py3-none-any.whl → 0.0.5.11.1__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/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 in ("open", "aps", "web"):
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(resp, content: bytes, /) -> dict:
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:
@@ -566,13 +596,34 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
566
596
  raise P115OSError(errno.EIO, resp)
567
597
 
568
598
 
599
+ @overload
569
600
  def normalize_attr_web(
570
601
  info: Mapping,
571
602
  /,
572
603
  simple: bool = False,
573
604
  keep_raw: bool = False,
574
- dict_cls: None | type[dict] = None,
605
+ *,
606
+ dict_cls: None = None,
575
607
  ) -> dict[str, Any]:
608
+ ...
609
+ @overload
610
+ def normalize_attr_web[D: dict[str, Any]](
611
+ info: Mapping,
612
+ /,
613
+ simple: bool = False,
614
+ keep_raw: bool = False,
615
+ *,
616
+ dict_cls: type[D],
617
+ ) -> D:
618
+ ...
619
+ def normalize_attr_web[D: dict[str, Any]](
620
+ info: Mapping,
621
+ /,
622
+ simple: bool = False,
623
+ keep_raw: bool = False,
624
+ *,
625
+ dict_cls: None | type[D] = None,
626
+ ) -> dict[str, Any] | D:
576
627
  """翻译 `P115Client.fs_files`、`P115Client.fs_search`、`P115Client.share_snap` 等接口响应的文件信息数据,使之便于阅读
577
628
 
578
629
  :param info: 原始数据
@@ -583,10 +634,7 @@ def normalize_attr_web(
583
634
  :return: 翻译后的 dict 类型数据
584
635
  """
585
636
  if dict_cls is None:
586
- if simple:
587
- dict_cls = dict
588
- else:
589
- dict_cls = AttrDict
637
+ dict_cls = cast(type[D], dict)
590
638
  attr: dict[str, Any] = dict_cls()
591
639
  is_directory = attr["is_dir"] = "fid" not in info
592
640
  if not simple:
@@ -690,10 +738,10 @@ def normalize_attr_web(
690
738
  attr["type"] = 0
691
739
  elif info.get("iv") or "vdi" in info:
692
740
  attr["type"] = 4
693
- elif type := CLASS_TO_TYPE.get(attr.get("class", "")):
694
- attr["type"] = type
695
- elif type := SUFFIX_TO_TYPE.get(splitext(attr["name"])[1].lower()):
696
- attr["type"] = type
741
+ elif type_ := CLASS_TO_TYPE.get(attr.get("class", "")):
742
+ attr["type"] = type_
743
+ elif type_ := SUFFIX_TO_TYPE.get(splitext(attr["name"])[1].lower()):
744
+ attr["type"] = type_
697
745
  else:
698
746
  attr["type"] = 99
699
747
  if keep_raw:
@@ -701,13 +749,33 @@ def normalize_attr_web(
701
749
  return attr
702
750
 
703
751
 
752
+ @overload
704
753
  def normalize_attr_app(
705
754
  info: Mapping,
706
755
  /,
707
756
  simple: bool = False,
708
757
  keep_raw: bool = False,
709
- dict_cls: None | type[dict] = None,
758
+ *,
759
+ dict_cls: None = None,
710
760
  ) -> dict[str, Any]:
761
+ ...
762
+ @overload
763
+ def normalize_attr_app[D: dict[str, Any]](
764
+ info: Mapping,
765
+ /,
766
+ simple: bool = False,
767
+ keep_raw: bool = False,
768
+ *,
769
+ dict_cls: None | type[D] = None,
770
+ ) -> D:
771
+ ...
772
+ def normalize_attr_app[D: dict[str, Any]](
773
+ info: Mapping,
774
+ /,
775
+ simple: bool = False,
776
+ keep_raw: bool = False,
777
+ dict_cls: None | type[D] = None,
778
+ ) -> dict[str, Any] | D:
711
779
  """翻译 `P115Client.fs_files_app` 接口响应的文件信息数据,使之便于阅读
712
780
 
713
781
  :param info: 原始数据
@@ -718,10 +786,7 @@ def normalize_attr_app(
718
786
  :return: 翻译后的 dict 类型数据
719
787
  """
720
788
  if dict_cls is None:
721
- if simple:
722
- dict_cls = dict
723
- else:
724
- dict_cls = AttrDict
789
+ dict_cls = cast(type[D], dict)
725
790
  attr: dict[str, Any] = dict_cls()
726
791
  is_directory = attr["is_dir"] = info["fc"] == "0" # fc => file_category
727
792
  if not simple:
@@ -805,8 +870,8 @@ def normalize_attr_app(
805
870
  attr["type"] = 3
806
871
  elif info.get("isv") or "def" in info or "def2" in info or "v_img" in info:
807
872
  attr["type"] = 4
808
- elif type := SUFFIX_TO_TYPE.get(splitext(attr["name"])[1].lower()):
809
- attr["type"] = type
873
+ elif type_ := SUFFIX_TO_TYPE.get(splitext(attr["name"])[1].lower()):
874
+ attr["type"] = type_
810
875
  else:
811
876
  attr["type"] = 99
812
877
  if keep_raw:
@@ -814,13 +879,33 @@ def normalize_attr_app(
814
879
  return attr
815
880
 
816
881
 
882
+ @overload
817
883
  def normalize_attr_app2(
818
884
  info: Mapping,
819
885
  /,
820
886
  simple: bool = False,
821
887
  keep_raw: bool = False,
822
- dict_cls: None | type[dict] = None,
888
+ *,
889
+ dict_cls: None = None,
823
890
  ) -> dict[str, Any]:
891
+ ...
892
+ @overload
893
+ def normalize_attr_app2[D: dict[str, Any]](
894
+ info: Mapping,
895
+ /,
896
+ simple: bool = False,
897
+ keep_raw: bool = False,
898
+ *,
899
+ dict_cls: None | type[D] = None,
900
+ ) -> D:
901
+ ...
902
+ def normalize_attr_app2[D: dict[str, Any]](
903
+ info: Mapping,
904
+ /,
905
+ simple: bool = False,
906
+ keep_raw: bool = False,
907
+ dict_cls: None | type[D] = None,
908
+ ) -> dict[str, Any] | D:
824
909
  """翻译 `P115Client.fs_files_app2` 接口响应的文件信息数据,使之便于阅读
825
910
 
826
911
  :param info: 原始数据
@@ -831,10 +916,7 @@ def normalize_attr_app2(
831
916
  :return: 翻译后的 dict 类型数据
832
917
  """
833
918
  if dict_cls is None:
834
- if simple:
835
- dict_cls = dict
836
- else:
837
- dict_cls = AttrDict
919
+ dict_cls = cast(type[D], dict)
838
920
  attr: dict[str, Any] = dict_cls()
839
921
  if "file_id" in info and "parent_id" in info:
840
922
  if "file_category" in info:
@@ -940,8 +1022,8 @@ def normalize_attr_app2(
940
1022
  attr["type"] = 3
941
1023
  elif info.get("is_video") or "definition" in info or "definition2" in info or "video_img_url" in info:
942
1024
  attr["type"] = 4
943
- elif type := SUFFIX_TO_TYPE.get(splitext(attr["name"])[1].lower()):
944
- attr["type"] = type
1025
+ elif type_ := SUFFIX_TO_TYPE.get(splitext(attr["name"])[1].lower()):
1026
+ attr["type"] = type_
945
1027
  else:
946
1028
  attr["type"] = 99
947
1029
  if keep_raw:
@@ -949,13 +1031,34 @@ def normalize_attr_app2(
949
1031
  return attr
950
1032
 
951
1033
 
1034
+ @overload
952
1035
  def normalize_attr(
953
1036
  info: Mapping,
954
1037
  /,
955
1038
  simple: bool = False,
956
1039
  keep_raw: bool = False,
957
- dict_cls: None | type[dict] = None,
1040
+ *,
1041
+ dict_cls: None,
958
1042
  ) -> dict[str, Any]:
1043
+ ...
1044
+ @overload
1045
+ def normalize_attr[D: dict[str, Any]](
1046
+ info: Mapping,
1047
+ /,
1048
+ simple: bool = False,
1049
+ keep_raw: bool = False,
1050
+ *,
1051
+ dict_cls: type[D] = AttrDict, # type: ignore
1052
+ ) -> D:
1053
+ ...
1054
+ def normalize_attr[D: dict[str, Any]](
1055
+ info: Mapping,
1056
+ /,
1057
+ simple: bool = False,
1058
+ keep_raw: bool = False,
1059
+ *,
1060
+ dict_cls: None | type[D] = AttrDict, # type: ignore
1061
+ ) -> dict[str, Any] | D:
959
1062
  """翻译获取自罗列目录、搜索、获取文件信息等接口的数据,使之便于阅读
960
1063
 
961
1064
  :param info: 原始数据
@@ -973,12 +1076,32 @@ def normalize_attr(
973
1076
  return normalize_attr_web(info, simple=simple, keep_raw=keep_raw, dict_cls=dict_cls)
974
1077
 
975
1078
 
1079
+ @overload
976
1080
  def normalize_attr_simple(
977
1081
  info: Mapping,
978
1082
  /,
979
1083
  keep_raw: bool = False,
1084
+ *,
1085
+ dict_cls: None = None,
980
1086
  ) -> dict[str, Any]:
981
- return normalize_attr(info, simple=True, keep_raw=keep_raw)
1087
+ ...
1088
+ @overload
1089
+ def normalize_attr_simple[D: dict[str, Any]](
1090
+ info: Mapping,
1091
+ /,
1092
+ keep_raw: bool = False,
1093
+ *,
1094
+ dict_cls: type[D],
1095
+ ) -> D:
1096
+ ...
1097
+ def normalize_attr_simple[D: dict[str, Any]](
1098
+ info: Mapping,
1099
+ /,
1100
+ keep_raw: bool = False,
1101
+ *,
1102
+ dict_cls: None | type[D] = None,
1103
+ ) -> dict[str, Any] | D:
1104
+ return normalize_attr(info, simple=True, keep_raw=keep_raw, dict_cls=dict_cls)
982
1105
 
983
1106
 
984
1107
  class IgnoreCaseDict[V](dict[str, V]):
@@ -2157,7 +2280,7 @@ class ClientRequestMixin:
2157
2280
  else:
2158
2281
  url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
2159
2282
  if async_:
2160
- yield partial(startfile_async, url)
2283
+ yield startfile_async(url)
2161
2284
  else:
2162
2285
  startfile(url)
2163
2286
  while True:
@@ -2194,7 +2317,7 @@ class ClientRequestMixin:
2194
2317
  )
2195
2318
  else:
2196
2319
  return qrcode_token
2197
- return run_gen_step(gen_step, async_=async_)
2320
+ return run_gen_step(gen_step, simple=True, async_=async_)
2198
2321
 
2199
2322
  @overload
2200
2323
  @classmethod
@@ -2261,7 +2384,7 @@ class ClientRequestMixin:
2261
2384
  else:
2262
2385
  url = complete_api(f"/api/1.0/web/1.0/qrcode?uid={login_uid}", base_url=base_url)
2263
2386
  if async_:
2264
- yield partial(startfile_async, url)
2387
+ yield startfile_async(url)
2265
2388
  else:
2266
2389
  startfile(url)
2267
2390
  while True:
@@ -2294,7 +2417,7 @@ class ClientRequestMixin:
2294
2417
  async_=async_,
2295
2418
  **request_kwargs,
2296
2419
  )
2297
- return run_gen_step(gen_step, async_=async_)
2420
+ return run_gen_step(gen_step, simple=True, async_=async_)
2298
2421
 
2299
2422
  ########## Upload API ##########
2300
2423
 
@@ -2677,7 +2800,7 @@ class ClientRequestMixin:
2677
2800
  async_=async_,
2678
2801
  **request_kwargs,
2679
2802
  )
2680
- return run_gen_step(gen_step, async_=async_)
2803
+ return run_gen_step(gen_step, simple=True, async_=async_)
2681
2804
 
2682
2805
  @overload
2683
2806
  def read_bytes_range(
@@ -2792,7 +2915,7 @@ class ClientRequestMixin:
2792
2915
  async_=async_,
2793
2916
  **request_kwargs,
2794
2917
  )
2795
- return run_gen_step(gen_step, async_=async_)
2918
+ return run_gen_step(gen_step, simple=True, async_=async_)
2796
2919
 
2797
2920
 
2798
2921
  class P115OpenClient(ClientRequestMixin):
@@ -2888,7 +3011,7 @@ class P115OpenClient(ClientRequestMixin):
2888
3011
  self.refresh_token = data["refresh_token"]
2889
3012
  self.access_token = data["access_token"]
2890
3013
  return self
2891
- return run_gen_step(gen_step, async_=async_)
3014
+ return run_gen_step(gen_step, simple=True, async_=async_)
2892
3015
 
2893
3016
  @classmethod
2894
3017
  def from_token(cls, /, access_token: str, refresh_token: str) -> P115OpenClient:
@@ -2955,7 +3078,7 @@ class P115OpenClient(ClientRequestMixin):
2955
3078
  self.refresh_token = data["refresh_token"]
2956
3079
  access_token = self.access_token = data["access_token"]
2957
3080
  return access_token
2958
- return run_gen_step(gen_step, async_=async_)
3081
+ return run_gen_step(gen_step, simple=True, async_=async_)
2959
3082
 
2960
3083
  @overload
2961
3084
  def download_url(
@@ -3338,9 +3461,675 @@ class P115OpenClient(ClientRequestMixin):
3338
3461
  return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3339
3462
 
3340
3463
  @overload
3341
- def fs_info(
3464
+ def fs_info(
3465
+ self,
3466
+ payload: int | str | dict,
3467
+ /,
3468
+ base_url: bool | str | Callable[[], str] = False,
3469
+ *,
3470
+ async_: Literal[False] = False,
3471
+ **request_kwargs,
3472
+ ) -> dict:
3473
+ ...
3474
+ @overload
3475
+ def fs_info(
3476
+ self,
3477
+ payload: int | str | dict,
3478
+ /,
3479
+ base_url: bool | str | Callable[[], str] = False,
3480
+ *,
3481
+ async_: Literal[True],
3482
+ **request_kwargs,
3483
+ ) -> Coroutine[Any, Any, dict]:
3484
+ ...
3485
+ def fs_info(
3486
+ self,
3487
+ payload: int | str | dict,
3488
+ /,
3489
+ base_url: bool | str | Callable[[], str] = False,
3490
+ *,
3491
+ async_: Literal[False, True] = False,
3492
+ **request_kwargs,
3493
+ ) -> dict | Coroutine[Any, Any, dict]:
3494
+ """获取文件或目录详情
3495
+
3496
+ GET https://proapi.115.com/open/folder/get_info
3497
+
3498
+ .. hint::
3499
+ 相当于 `P115Client.fs_category_get_app`
3500
+
3501
+ .. admonition:: Reference
3502
+
3503
+ https://www.yuque.com/115yun/open/rl8zrhe2nag21dfw
3504
+
3505
+ :payload:
3506
+ - file_id: int | str 💡 文件或目录的 id
3507
+ """
3508
+ api = complete_proapi("/open/folder/get_info", base_url)
3509
+ if isinstance(payload, (int, str)):
3510
+ payload = {"file_id": payload}
3511
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3512
+
3513
+ @overload
3514
+ def fs_mkdir(
3515
+ self,
3516
+ payload: str | dict,
3517
+ /,
3518
+ pid: int = 0,
3519
+ base_url: bool | str | Callable[[], str] = False,
3520
+ *,
3521
+ async_: Literal[False] = False,
3522
+ **request_kwargs,
3523
+ ) -> dict:
3524
+ ...
3525
+ @overload
3526
+ def fs_mkdir(
3527
+ self,
3528
+ payload: str | dict,
3529
+ /,
3530
+ pid: int = 0,
3531
+ base_url: bool | str | Callable[[], str] = False,
3532
+ *,
3533
+ async_: Literal[True],
3534
+ **request_kwargs,
3535
+ ) -> Coroutine[Any, Any, dict]:
3536
+ ...
3537
+ def fs_mkdir(
3538
+ self,
3539
+ payload: str | dict,
3540
+ /,
3541
+ pid: int = 0,
3542
+ base_url: bool | str | Callable[[], str] = False,
3543
+ *,
3544
+ async_: Literal[False, True] = False,
3545
+ **request_kwargs,
3546
+ ) -> dict | Coroutine[Any, Any, dict]:
3547
+ """新建目录
3548
+
3549
+ POST https://proapi.115.com/open/folder/add
3550
+
3551
+ .. admonition:: Reference
3552
+
3553
+ https://www.yuque.com/115yun/open/qur839kyx9cgxpxi
3554
+
3555
+ :payload:
3556
+ - file_name: str 💡 新建目录名称,限制255个字符
3557
+ - pid: int | str = 0 💡 新建目录所在的父目录ID (根目录的ID为0)
3558
+ """
3559
+ api = complete_proapi("/open/folder/add", base_url)
3560
+ if isinstance(payload, str):
3561
+ payload = {"pid": pid, "file_name": payload}
3562
+ else:
3563
+ payload = {"pid": pid, **payload}
3564
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3565
+
3566
+ @overload
3567
+ def fs_move(
3568
+ self,
3569
+ payload: int | str | Iterable[int | str] | dict,
3570
+ /,
3571
+ pid: int = 0,
3572
+ base_url: bool | str | Callable[[], str] = False,
3573
+ *,
3574
+ async_: Literal[False] = False,
3575
+ **request_kwargs,
3576
+ ) -> dict:
3577
+ ...
3578
+ @overload
3579
+ def fs_move(
3580
+ self,
3581
+ payload: int | str | Iterable[int | str] | dict,
3582
+ /,
3583
+ pid: int = 0,
3584
+ base_url: bool | str | Callable[[], str] = False,
3585
+ *,
3586
+ async_: Literal[True],
3587
+ **request_kwargs,
3588
+ ) -> Coroutine[Any, Any, dict]:
3589
+ ...
3590
+ def fs_move(
3591
+ self,
3592
+ payload: int | str | Iterable[int | str] | dict,
3593
+ /,
3594
+ pid: int = 0,
3595
+ base_url: bool | str | Callable[[], str] = False,
3596
+ *,
3597
+ async_: Literal[False, True] = False,
3598
+ **request_kwargs,
3599
+ ) -> dict | Coroutine[Any, Any, dict]:
3600
+ """文件移动
3601
+
3602
+ POST https://proapi.115.com/open/ufile/move
3603
+
3604
+ .. admonition:: Reference
3605
+
3606
+ https://www.yuque.com/115yun/open/vc6fhi2mrkenmav2
3607
+
3608
+ :payload:
3609
+ - file_ids: int | str 💡 文件或目录的 id,多个用逗号 "," 隔开
3610
+ - to_cid: int | str = 0 💡 父目录 id
3611
+ """
3612
+ api = complete_proapi("/open/ufile/move", base_url)
3613
+ if isinstance(payload, (int, str)):
3614
+ payload = {"file_ids": payload}
3615
+ elif isinstance(payload, dict):
3616
+ payload = dict(payload)
3617
+ else:
3618
+ payload = {"file_ids": ",".join(map(str, payload))}
3619
+ if not payload.get("file_ids"):
3620
+ return {"state": False, "message": "no op"}
3621
+ payload = cast(dict, payload)
3622
+ payload.setdefault("to_cid", pid)
3623
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3624
+
3625
+ @overload
3626
+ def fs_search(
3627
+ self,
3628
+ payload: str | dict = ".",
3629
+ /,
3630
+ base_url: bool | str | Callable[[], str] = False,
3631
+ *,
3632
+ async_: Literal[False] = False,
3633
+ **request_kwargs,
3634
+ ) -> dict:
3635
+ ...
3636
+ @overload
3637
+ def fs_search(
3638
+ self,
3639
+ payload: str | dict = ".",
3640
+ /,
3641
+ base_url: bool | str | Callable[[], str] = False,
3642
+ *,
3643
+ async_: Literal[True],
3644
+ **request_kwargs,
3645
+ ) -> Coroutine[Any, Any, dict]:
3646
+ ...
3647
+ def fs_search(
3648
+ self,
3649
+ payload: str | dict = ".",
3650
+ /,
3651
+ base_url: bool | str | Callable[[], str] = False,
3652
+ *,
3653
+ async_: Literal[False, True] = False,
3654
+ **request_kwargs,
3655
+ ) -> dict | Coroutine[Any, Any, dict]:
3656
+ """搜索文件或目录
3657
+
3658
+ GET https://proapi.115.com/open/ufile/search
3659
+
3660
+ .. hint::
3661
+ 相当于 `P115Client.fs_search_app2`
3662
+
3663
+ .. admonition:: Reference
3664
+
3665
+ https://www.yuque.com/115yun/open/ft2yelxzopusus38
3666
+
3667
+ :payload:
3668
+ - aid: int | str = 1 💡 area_id。1:正常文件 7:回收站文件 12:瞬间文件 120:彻底删除文件、简历附件
3669
+ - asc: 0 | 1 = <default> 💡 是否升序排列
3670
+ - cid: int | str = 0 💡 目录 id。cid=-1 时,表示不返回列表任何内容
3671
+ - count_folders: 0 | 1 = <default>
3672
+ - date: str = <default> 💡 筛选日期
3673
+ - fc: 0 | 1 = <default> 💡 只显示文件或目录。1:只显示目录 2:只显示文件
3674
+ - fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
3675
+ - file_label: int | str = <default> 💡 标签 id
3676
+ - format: str = "json" 💡 输出格式(不用管)
3677
+ - gte_day: str 💡 搜索结果匹配的开始时间;格式:YYYY-MM-DD
3678
+ - limit: int = 32 💡 一页大小,意思就是 page_size
3679
+ - lte_day: str 💡 搜索结果匹配的结束时间;格式:YYYY-MM-DD
3680
+ - o: str = <default> 💡 用某字段排序
3681
+
3682
+ - "file_name": 文件名
3683
+ - "file_size": 文件大小
3684
+ - "file_type": 文件种类
3685
+ - "user_utime": 修改时间
3686
+ - "user_ptime": 创建时间
3687
+ - "user_otime": 上一次打开时间
3688
+
3689
+ - offset: int = 0 💡 索引偏移,索引从 0 开始计算
3690
+ - pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
3691
+ - search_value: str = "." 💡 搜索文本,可以是 sha1
3692
+ - show_dir: 0 | 1 = 1
3693
+ - source: str = <default>
3694
+ - star: 0 | 1 = <default>
3695
+ - suffix: str = <default>
3696
+ - type: int = <default> 💡 文件类型
3697
+
3698
+ - 0: 全部(仅当前目录)
3699
+ - 1: 文档
3700
+ - 2: 图片
3701
+ - 3: 音频
3702
+ - 4: 视频
3703
+ - 5: 压缩包
3704
+ - 6: 软件/应用
3705
+ - 7: 书籍
3706
+ - 99: 仅文件
3707
+
3708
+ - version: str = <default> 💡 版本号,比如 3.1
3709
+ """
3710
+ api = complete_proapi("/open/ufile/search", base_url)
3711
+ if isinstance(payload, str):
3712
+ payload = {
3713
+ "aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
3714
+ "show_dir": 1, "search_value": payload,
3715
+ }
3716
+ else:
3717
+ payload = {
3718
+ "aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
3719
+ "show_dir": 1, "search_value": ".", **payload,
3720
+ }
3721
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3722
+
3723
+ @overload
3724
+ def fs_star_set(
3725
+ self,
3726
+ payload: int | str | Iterable[int | str] | dict,
3727
+ /,
3728
+ star: bool = True,
3729
+ base_url: bool | str | Callable[[], str] = False,
3730
+ *,
3731
+ async_: Literal[False] = False,
3732
+ **request_kwargs,
3733
+ ) -> dict:
3734
+ ...
3735
+ @overload
3736
+ def fs_star_set(
3737
+ self,
3738
+ payload: int | str | Iterable[int | str] | dict,
3739
+ /,
3740
+ star: bool = True,
3741
+ base_url: bool | str | Callable[[], str] = False,
3742
+ *,
3743
+ async_: Literal[True],
3744
+ **request_kwargs,
3745
+ ) -> Coroutine[Any, Any, dict]:
3746
+ ...
3747
+ def fs_star_set(
3748
+ self,
3749
+ payload: int | str | Iterable[int | str] | dict,
3750
+ /,
3751
+ star: bool = True,
3752
+ base_url: bool | str | Callable[[], str] = False,
3753
+ *,
3754
+ async_: Literal[False, True] = False,
3755
+ **request_kwargs,
3756
+ ) -> dict | Coroutine[Any, Any, dict]:
3757
+ """为文件或目录设置或取消星标,此接口是对 `fs_update_open` 的封装
3758
+
3759
+ .. note::
3760
+ 即使其中任何一个 id 目前已经被删除,也可以操作成功
3761
+
3762
+ :payload:
3763
+ - file_id: int | str 💡 只能传入 1 个
3764
+ - file_id[0]: int | str 💡 如果有多个,则按顺序给出
3765
+ - file_id[1]: int | str
3766
+ - ...
3767
+ - star: 0 | 1 = 1
3768
+ """
3769
+ api = complete_webapi("/files/star", base_url=base_url)
3770
+ if isinstance(payload, (int, str)):
3771
+ payload = {"file_id": payload, "star": int(star)}
3772
+ elif not isinstance(payload, dict):
3773
+ payload = {f"file_id[{i}]": id for i, id in enumerate(payload)}
3774
+ if not payload:
3775
+ return {"state": False, "message": "no op"}
3776
+ payload["star"] = int(star)
3777
+ else:
3778
+ payload = {"star": int(star), **payload}
3779
+ return self.fs_update(payload, async_=async_, **request_kwargs)
3780
+
3781
+ @overload
3782
+ def fs_video_history(
3783
+ self,
3784
+ payload: str | dict,
3785
+ /,
3786
+ base_url: bool | str | Callable[[], str] = False,
3787
+ *,
3788
+ async_: Literal[False] = False,
3789
+ **request_kwargs,
3790
+ ) -> dict:
3791
+ ...
3792
+ @overload
3793
+ def fs_video_history(
3794
+ self,
3795
+ payload: str | dict,
3796
+ /,
3797
+ base_url: bool | str | Callable[[], str] = False,
3798
+ *,
3799
+ async_: Literal[True],
3800
+ **request_kwargs,
3801
+ ) -> Coroutine[Any, Any, dict]:
3802
+ ...
3803
+ def fs_video_history(
3804
+ self,
3805
+ payload: str | dict,
3806
+ /,
3807
+ base_url: bool | str | Callable[[], str] = False,
3808
+ *,
3809
+ async_: Literal[False, True] = False,
3810
+ **request_kwargs,
3811
+ ) -> dict | Coroutine[Any, Any, dict]:
3812
+ """获取视频播放进度
3813
+
3814
+ GET https://proapi.115.com/open/video/history
3815
+
3816
+ .. admonition:: Reference
3817
+
3818
+ https://www.yuque.com/115yun/open/gssqdrsq6vfqigag
3819
+
3820
+ :payload:
3821
+ - pick_code: str 💡 文件提取码
3822
+ """
3823
+ api = complete_proapi("/open/video/history", base_url)
3824
+ if isinstance(payload, str):
3825
+ payload = {"pick_code": payload}
3826
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3827
+
3828
+ @overload
3829
+ def fs_video_history_set(
3830
+ self,
3831
+ payload: str | dict,
3832
+ /,
3833
+ base_url: bool | str | Callable[[], str] = False,
3834
+ *,
3835
+ async_: Literal[False] = False,
3836
+ **request_kwargs,
3837
+ ) -> dict:
3838
+ ...
3839
+ @overload
3840
+ def fs_video_history_set(
3841
+ self,
3842
+ payload: str | dict,
3843
+ /,
3844
+ base_url: bool | str | Callable[[], str] = False,
3845
+ *,
3846
+ async_: Literal[True],
3847
+ **request_kwargs,
3848
+ ) -> Coroutine[Any, Any, dict]:
3849
+ ...
3850
+ def fs_video_history_set(
3851
+ self,
3852
+ payload: str | dict,
3853
+ /,
3854
+ base_url: bool | str | Callable[[], str] = False,
3855
+ *,
3856
+ async_: Literal[False, True] = False,
3857
+ **request_kwargs,
3858
+ ) -> dict | Coroutine[Any, Any, dict]:
3859
+ """记忆视频播放进度
3860
+
3861
+ POST https://proapi.115.com/open/video/history
3862
+
3863
+ .. admonition:: Reference
3864
+
3865
+ https://www.yuque.com/115yun/open/bshagbxv1gzqglg4
3866
+
3867
+ :payload:
3868
+ - pick_code: str 💡 文件提取码
3869
+ - time: int = <default> 💡 视频播放进度时长 (单位秒)
3870
+ - watch_end: int = <default> 💡 视频是否播放播放完毕 0:未完毕 1:完毕
3871
+ """
3872
+ api = complete_proapi("/open/video/history", base_url)
3873
+ if isinstance(payload, str):
3874
+ payload = {"pick_code": payload}
3875
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3876
+
3877
+ @overload
3878
+ def fs_video_play(
3879
+ self,
3880
+ payload: str | dict,
3881
+ /,
3882
+ base_url: bool | str | Callable[[], str] = False,
3883
+ *,
3884
+ async_: Literal[False] = False,
3885
+ **request_kwargs,
3886
+ ) -> dict:
3887
+ ...
3888
+ @overload
3889
+ def fs_video_play(
3890
+ self,
3891
+ payload: str | dict,
3892
+ /,
3893
+ base_url: bool | str | Callable[[], str] = False,
3894
+ *,
3895
+ async_: Literal[True],
3896
+ **request_kwargs,
3897
+ ) -> Coroutine[Any, Any, dict]:
3898
+ ...
3899
+ def fs_video_play(
3900
+ self,
3901
+ payload: str | dict,
3902
+ /,
3903
+ base_url: bool | str | Callable[[], str] = False,
3904
+ *,
3905
+ async_: Literal[False, True] = False,
3906
+ **request_kwargs,
3907
+ ) -> dict | Coroutine[Any, Any, dict]:
3908
+ """获取视频在线播放地址(和视频文件相关数据)
3909
+
3910
+ GET https://proapi.115.com/open/video/play
3911
+
3912
+ .. admonition:: Reference
3913
+
3914
+ https://www.yuque.com/115yun/open/hqglxv3cedi3p9dz
3915
+
3916
+ .. hint::
3917
+ 需切换音轨时,在请求返回的播放地址中增加请求参数 `&audio_track=${index}`,值就是接口响应中 `multitrack_list` 中某个成员的索引,从 0 开始计数
3918
+
3919
+ :payload:
3920
+ - pick_code: str 💡 文件提取码
3921
+ - share_id: int | str = <default> 💡 共享 id,获取共享文件播放地址所需
3922
+ """
3923
+ api = complete_proapi("/open/video/play", base_url)
3924
+ if isinstance(payload, str):
3925
+ payload = {"pick_code": payload}
3926
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3927
+
3928
+ @overload
3929
+ def fs_video_push(
3930
+ self,
3931
+ payload: str | dict,
3932
+ /,
3933
+ base_url: bool | str | Callable[[], str] = False,
3934
+ *,
3935
+ async_: Literal[False] = False,
3936
+ **request_kwargs,
3937
+ ) -> dict:
3938
+ ...
3939
+ @overload
3940
+ def fs_video_push(
3941
+ self,
3942
+ payload: str | dict,
3943
+ /,
3944
+ base_url: bool | str | Callable[[], str] = False,
3945
+ *,
3946
+ async_: Literal[True],
3947
+ **request_kwargs,
3948
+ ) -> Coroutine[Any, Any, dict]:
3949
+ ...
3950
+ def fs_video_push(
3951
+ self,
3952
+ payload: str | dict,
3953
+ /,
3954
+ base_url: bool | str | Callable[[], str] = False,
3955
+ *,
3956
+ async_: Literal[False, True] = False,
3957
+ **request_kwargs,
3958
+ ) -> dict | Coroutine[Any, Any, dict]:
3959
+ """提交视频转码
3960
+
3961
+ POST https://proapi.115.com/open/video/video_push
3962
+
3963
+ .. admonition:: Reference
3964
+
3965
+ https://www.yuque.com/115yun/open/nxt8r1qcktmg3oan
3966
+
3967
+ :payload:
3968
+ - pick_code: str 💡 文件提取码
3969
+ - op: str = "vip_push" 💡 提交视频加速转码方式:vip_push:根据;vip 等级加速 pay_push:枫叶加速
3970
+ """
3971
+ api = complete_proapi("/open/video/video_push", base_url)
3972
+ if isinstance(payload, str):
3973
+ payload = {"pick_code": payload, "op": "vip_push"}
3974
+ else:
3975
+ payload.setdefault("op", "vip_push")
3976
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3977
+
3978
+ @overload
3979
+ def fs_video_subtitle(
3980
+ self,
3981
+ payload: str | dict,
3982
+ /,
3983
+ base_url: bool | str | Callable[[], str] = False,
3984
+ *,
3985
+ async_: Literal[False] = False,
3986
+ **request_kwargs,
3987
+ ) -> dict:
3988
+ ...
3989
+ @overload
3990
+ def fs_video_subtitle(
3991
+ self,
3992
+ payload: str | dict,
3993
+ /,
3994
+ base_url: bool | str | Callable[[], str] = False,
3995
+ *,
3996
+ async_: Literal[True],
3997
+ **request_kwargs,
3998
+ ) -> Coroutine[Any, Any, dict]:
3999
+ ...
4000
+ def fs_video_subtitle(
4001
+ self,
4002
+ payload: str | dict,
4003
+ /,
4004
+ base_url: bool | str | Callable[[], str] = False,
4005
+ *,
4006
+ async_: Literal[False, True] = False,
4007
+ **request_kwargs,
4008
+ ) -> dict | Coroutine[Any, Any, dict]:
4009
+ """视频字幕列表
4010
+
4011
+ GET https://proapi.115.com/open/video/subtitle
4012
+
4013
+ .. admonition:: Reference
4014
+
4015
+ https://www.yuque.com/115yun/open/nx076h3glapoyh7u
4016
+
4017
+ :payload:
4018
+ - pick_code: str 💡 文件提取码
4019
+ """
4020
+ api = complete_proapi("/open/video/subtitle", base_url)
4021
+ if isinstance(payload, str):
4022
+ payload = {"pick_code": payload}
4023
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
4024
+
4025
+ @overload
4026
+ def fs_update(
4027
+ self,
4028
+ payload: dict,
4029
+ /,
4030
+ base_url: bool | str | Callable[[], str] = False,
4031
+ *,
4032
+ async_: Literal[False] = False,
4033
+ **request_kwargs,
4034
+ ) -> dict:
4035
+ ...
4036
+ @overload
4037
+ def fs_update(
4038
+ self,
4039
+ payload: dict,
4040
+ /,
4041
+ base_url: bool | str | Callable[[], str] = False,
4042
+ *,
4043
+ async_: Literal[True],
4044
+ **request_kwargs,
4045
+ ) -> Coroutine[Any, Any, dict]:
4046
+ ...
4047
+ def fs_update(
4048
+ self,
4049
+ payload: dict,
4050
+ /,
4051
+ base_url: bool | str | Callable[[], str] = False,
4052
+ *,
4053
+ async_: Literal[False, True] = False,
4054
+ **request_kwargs,
4055
+ ) -> dict | Coroutine[Any, Any, dict]:
4056
+ """设置文件或目录(备注、标签等)
4057
+
4058
+ POST https://proapi.115.com/open/ufile/update
4059
+
4060
+ .. hint::
4061
+ 即使文件已经被删除,也可以操作成功
4062
+
4063
+ .. admonition:: Reference
4064
+
4065
+ https://www.yuque.com/115yun/open/gyrpw5a0zc4sengm
4066
+
4067
+ :payload:
4068
+ - file_id: int | str 💡 只能传入 1 个
4069
+ - file_id[0]: int | str 💡 如果有多个,则按顺序给出
4070
+ - file_id[1]: int | str
4071
+ - ...
4072
+ - file_name: str = <default> 💡 文件名
4073
+ - star: 0 | 1 = <default> 💡 是否星标:0:取消星标 1:设置星标
4074
+ - ...
4075
+ """
4076
+ api = complete_proapi("/open/ufile/update", base_url)
4077
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
4078
+
4079
+ @overload
4080
+ def offline_add_torrent(
4081
+ self,
4082
+ payload: dict,
4083
+ /,
4084
+ base_url: bool | str | Callable[[], str] = False,
4085
+ *,
4086
+ async_: Literal[False] = False,
4087
+ **request_kwargs,
4088
+ ) -> dict:
4089
+ ...
4090
+ @overload
4091
+ def offline_add_torrent(
4092
+ self,
4093
+ payload: dict,
4094
+ /,
4095
+ base_url: bool | str | Callable[[], str] = False,
4096
+ *,
4097
+ async_: Literal[True],
4098
+ **request_kwargs,
4099
+ ) -> Coroutine[Any, Any, dict]:
4100
+ ...
4101
+ def offline_add_torrent(
4102
+ self,
4103
+ payload: dict,
4104
+ /,
4105
+ base_url: bool | str | Callable[[], str] = False,
4106
+ *,
4107
+ async_: Literal[False, True] = False,
4108
+ **request_kwargs,
4109
+ ) -> dict | Coroutine[Any, Any, dict]:
4110
+ """添加云下载 BT 任务
4111
+
4112
+ POST https://proapi.115.com/open/offline/add_task_bt
4113
+
4114
+ .. admonition:: Reference
4115
+
4116
+ https://www.yuque.com/115yun/open/svfe4unlhayvluly
4117
+
4118
+ :payload:
4119
+ - info_hash: str 💡 种子文件的 info_hash
4120
+ - pick_code: str 💡 种子文件的提取码
4121
+ - save_path: str 💡 保存到 `wp_path_id` 对应目录下的相对路径
4122
+ - torrent_sha1: str 💡 种子文件的 sha1
4123
+ - wanted: str 💡 选择文件进行下载(是数字索引,从 0 开始计数,用 "," 分隔)
4124
+ - wp_path_id: int | str = <default> 💡 保存目标文件夹 id
4125
+ """
4126
+ api = complete_proapi("/open/offline/add_task_bt ", base_url)
4127
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
4128
+
4129
+ @overload
4130
+ def offline_add_urls(
3342
4131
  self,
3343
- payload: int | str | dict,
4132
+ payload: str | Iterable[str] | dict,
3344
4133
  /,
3345
4134
  base_url: bool | str | Callable[[], str] = False,
3346
4135
  *,
@@ -3349,9 +4138,9 @@ class P115OpenClient(ClientRequestMixin):
3349
4138
  ) -> dict:
3350
4139
  ...
3351
4140
  @overload
3352
- def fs_info(
4141
+ def offline_add_urls(
3353
4142
  self,
3354
- payload: int | str | dict,
4143
+ payload: str | Iterable[str] | dict,
3355
4144
  /,
3356
4145
  base_url: bool | str | Callable[[], str] = False,
3357
4146
  *,
@@ -3359,40 +4148,39 @@ class P115OpenClient(ClientRequestMixin):
3359
4148
  **request_kwargs,
3360
4149
  ) -> Coroutine[Any, Any, dict]:
3361
4150
  ...
3362
- def fs_info(
4151
+ def offline_add_urls(
3363
4152
  self,
3364
- payload: int | str | dict,
4153
+ payload: str | Iterable[str] | dict,
3365
4154
  /,
3366
4155
  base_url: bool | str | Callable[[], str] = False,
3367
4156
  *,
3368
4157
  async_: Literal[False, True] = False,
3369
4158
  **request_kwargs,
3370
4159
  ) -> dict | Coroutine[Any, Any, dict]:
3371
- """获取文件或目录详情
4160
+ """添加云下载链接任务
3372
4161
 
3373
- GET https://proapi.115.com/open/folder/get_info
3374
-
3375
- .. hint::
3376
- 相当于 `P115Client.fs_category_get_app`
4162
+ POST https://proapi.115.com/open/offline/add_task_urls
3377
4163
 
3378
4164
  .. admonition:: Reference
3379
4165
 
3380
- https://www.yuque.com/115yun/open/rl8zrhe2nag21dfw
4166
+ https://www.yuque.com/115yun/open/zkyfq2499gdn3mty
3381
4167
 
3382
4168
  :payload:
3383
- - file_id: int | str 💡 文件或目录的 id
4169
+ - urls: str 💡 链接,用 "\\n" 分隔,支持HTTP、HTTPS、FTP、磁力链和电驴链接
4170
+ - wp_path_id: int | str = <default> 💡 保存到目录的 id
3384
4171
  """
3385
- api = complete_proapi("/open/folder/get_info", base_url)
3386
- if isinstance(payload, (int, str)):
3387
- payload = {"file_id": payload}
3388
- return self.request(url=api, params=payload, async_=async_, **request_kwargs)
4172
+ api = complete_proapi("/open/offline/add_task_urls", base_url)
4173
+ if isinstance(payload, str):
4174
+ payload = {"urls": payload.strip("\n")}
4175
+ elif not isinstance(payload, dict):
4176
+ payload = {"urls": ",".join(payload)}
4177
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3389
4178
 
3390
4179
  @overload
3391
- def fs_mkdir(
4180
+ def offline_clear(
3392
4181
  self,
3393
- payload: str | dict,
4182
+ payload: int | dict = 0,
3394
4183
  /,
3395
- pid: int = 0,
3396
4184
  base_url: bool | str | Callable[[], str] = False,
3397
4185
  *,
3398
4186
  async_: Literal[False] = False,
@@ -3400,52 +4188,53 @@ class P115OpenClient(ClientRequestMixin):
3400
4188
  ) -> dict:
3401
4189
  ...
3402
4190
  @overload
3403
- def fs_mkdir(
4191
+ def offline_clear(
3404
4192
  self,
3405
- payload: str | dict,
4193
+ payload: int | dict = 0,
3406
4194
  /,
3407
- pid: int = 0,
3408
4195
  base_url: bool | str | Callable[[], str] = False,
3409
4196
  *,
3410
4197
  async_: Literal[True],
3411
4198
  **request_kwargs,
3412
4199
  ) -> Coroutine[Any, Any, dict]:
3413
4200
  ...
3414
- def fs_mkdir(
4201
+ def offline_clear(
3415
4202
  self,
3416
- payload: str | dict,
4203
+ payload: int | dict = 0,
3417
4204
  /,
3418
- pid: int = 0,
3419
4205
  base_url: bool | str | Callable[[], str] = False,
3420
4206
  *,
3421
4207
  async_: Literal[False, True] = False,
3422
4208
  **request_kwargs,
3423
4209
  ) -> dict | Coroutine[Any, Any, dict]:
3424
- """新建目录
4210
+ """清空云下载任务
3425
4211
 
3426
- POST https://proapi.115.com/open/folder/add
4212
+ POST https://proapi.115.com/open/offline/clear_task
3427
4213
 
3428
4214
  .. admonition:: Reference
3429
4215
 
3430
- https://www.yuque.com/115yun/open/qur839kyx9cgxpxi
4216
+ https://www.yuque.com/115yun/open/uu5i4urb5ylqwfy4
3431
4217
 
3432
4218
  :payload:
3433
- - file_name: str 💡 新建目录名称,限制255个字符
3434
- - pid: int | str = 0 💡 新建目录所在的父目录ID (根目录的ID为0)
4219
+ - flag: int = 0 💡 标识,用于对应某种情况
4220
+
4221
+ - 0: 已完成
4222
+ - 1: 全部
4223
+ - 2: 已失败
4224
+ - 3: 进行中
4225
+ - 4: 已完成+删除源文件
4226
+ - 5: 全部+删除源文件
3435
4227
  """
3436
- api = complete_proapi("/open/folder/add", base_url)
3437
- if isinstance(payload, str):
3438
- payload = {"pid": pid, "file_name": payload}
3439
- else:
3440
- payload = {"pid": pid, **payload}
4228
+ api = complete_proapi("/open/offline/clear_task", base_url)
4229
+ if isinstance(payload, int):
4230
+ payload = {"flag": payload}
3441
4231
  return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3442
4232
 
3443
4233
  @overload
3444
- def fs_move(
4234
+ def offline_list(
3445
4235
  self,
3446
- payload: int | str | Iterable[int | str] | dict,
4236
+ payload: int | dict = 1,
3447
4237
  /,
3448
- pid: int = 0,
3449
4238
  base_url: bool | str | Callable[[], str] = False,
3450
4239
  *,
3451
4240
  async_: Literal[False] = False,
@@ -3453,56 +4242,44 @@ class P115OpenClient(ClientRequestMixin):
3453
4242
  ) -> dict:
3454
4243
  ...
3455
4244
  @overload
3456
- def fs_move(
4245
+ def offline_list(
3457
4246
  self,
3458
- payload: int | str | Iterable[int | str] | dict,
4247
+ payload: int | dict = 1,
3459
4248
  /,
3460
- pid: int = 0,
3461
4249
  base_url: bool | str | Callable[[], str] = False,
3462
4250
  *,
3463
4251
  async_: Literal[True],
3464
4252
  **request_kwargs,
3465
4253
  ) -> Coroutine[Any, Any, dict]:
3466
4254
  ...
3467
- def fs_move(
4255
+ def offline_list(
3468
4256
  self,
3469
- payload: int | str | Iterable[int | str] | dict,
4257
+ payload: int | dict = 1,
3470
4258
  /,
3471
- pid: int = 0,
3472
4259
  base_url: bool | str | Callable[[], str] = False,
3473
4260
  *,
3474
4261
  async_: Literal[False, True] = False,
3475
4262
  **request_kwargs,
3476
4263
  ) -> dict | Coroutine[Any, Any, dict]:
3477
- """文件移动
4264
+ """获取用户云下载任务列表
3478
4265
 
3479
- POST https://proapi.115.com/open/ufile/move
4266
+ GET https://proapi.115.com/open/offline/get_task_list
3480
4267
 
3481
4268
  .. admonition:: Reference
3482
4269
 
3483
- https://www.yuque.com/115yun/open/vc6fhi2mrkenmav2
4270
+ https://www.yuque.com/115yun/open/av2mluz7uwigz74k
3484
4271
 
3485
4272
  :payload:
3486
- - file_ids: int | str 💡 文件或目录的 id,多个用逗号 "," 隔开
3487
- - to_cid: int | str = 0 💡 父目录 id
4273
+ - page: int | str = 1
3488
4274
  """
3489
- api = complete_proapi("/open/ufile/move", base_url)
3490
- if isinstance(payload, (int, str)):
3491
- payload = {"file_ids": payload}
3492
- elif isinstance(payload, dict):
3493
- payload = dict(payload)
3494
- else:
3495
- payload = {"file_ids": ",".join(map(str, payload))}
3496
- if not payload.get("file_ids"):
3497
- return {"state": False, "message": "no op"}
3498
- payload = cast(dict, payload)
3499
- payload.setdefault("to_cid", pid)
3500
- return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
4275
+ api = complete_proapi("/open/offline/get_task_list", base_url)
4276
+ if isinstance(payload, int):
4277
+ payload = {"page": payload}
4278
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3501
4279
 
3502
4280
  @overload
3503
- def fs_search(
4281
+ def offline_quota_info(
3504
4282
  self,
3505
- payload: str | dict = ".",
3506
4283
  /,
3507
4284
  base_url: bool | str | Callable[[], str] = False,
3508
4285
  *,
@@ -3511,9 +4288,8 @@ class P115OpenClient(ClientRequestMixin):
3511
4288
  ) -> dict:
3512
4289
  ...
3513
4290
  @overload
3514
- def fs_search(
4291
+ def offline_quota_info(
3515
4292
  self,
3516
- payload: str | dict = ".",
3517
4293
  /,
3518
4294
  base_url: bool | str | Callable[[], str] = False,
3519
4295
  *,
@@ -3521,88 +4297,30 @@ class P115OpenClient(ClientRequestMixin):
3521
4297
  **request_kwargs,
3522
4298
  ) -> Coroutine[Any, Any, dict]:
3523
4299
  ...
3524
- def fs_search(
4300
+ def offline_quota_info(
3525
4301
  self,
3526
- payload: str | dict = ".",
3527
4302
  /,
3528
4303
  base_url: bool | str | Callable[[], str] = False,
3529
4304
  *,
3530
4305
  async_: Literal[False, True] = False,
3531
4306
  **request_kwargs,
3532
4307
  ) -> dict | Coroutine[Any, Any, dict]:
3533
- """搜索文件或目录
3534
-
3535
- GET https://proapi.115.com/open/ufile/search
4308
+ """获取云下载配额信息
3536
4309
 
3537
- .. hint::
3538
- 相当于 `P115Client.fs_search_app2`
4310
+ GET https://proapi.115.com/open/offline/get_quota_info
3539
4311
 
3540
4312
  .. admonition:: Reference
3541
4313
 
3542
- https://www.yuque.com/115yun/open/ft2yelxzopusus38
3543
-
3544
- :payload:
3545
- - aid: int | str = 1 💡 area_id。1:正常文件 7:回收站文件 12:瞬间文件 120:彻底删除文件、简历附件
3546
- - asc: 0 | 1 = <default> 💡 是否升序排列
3547
- - cid: int | str = 0 💡 目录 id。cid=-1 时,表示不返回列表任何内容
3548
- - count_folders: 0 | 1 = <default>
3549
- - date: str = <default> 💡 筛选日期
3550
- - fc: 0 | 1 = <default> 💡 只显示文件或目录。1:只显示目录 2:只显示文件
3551
- - fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
3552
- - file_label: int | str = <default> 💡 标签 id
3553
- - format: str = "json" 💡 输出格式(不用管)
3554
- - gte_day: str 💡 搜索结果匹配的开始时间;格式:YYYY-MM-DD
3555
- - limit: int = 32 💡 一页大小,意思就是 page_size
3556
- - lte_day: str 💡 搜索结果匹配的结束时间;格式:YYYY-MM-DD
3557
- - o: str = <default> 💡 用某字段排序
3558
-
3559
- - "file_name": 文件名
3560
- - "file_size": 文件大小
3561
- - "file_type": 文件种类
3562
- - "user_utime": 修改时间
3563
- - "user_ptime": 创建时间
3564
- - "user_otime": 上一次打开时间
3565
-
3566
- - offset: int = 0 💡 索引偏移,索引从 0 开始计算
3567
- - pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
3568
- - search_value: str = "." 💡 搜索文本,可以是 sha1
3569
- - show_dir: 0 | 1 = 1
3570
- - source: str = <default>
3571
- - star: 0 | 1 = <default>
3572
- - suffix: str = <default>
3573
- - type: int = <default> 💡 文件类型
3574
-
3575
- - 0: 全部(仅当前目录)
3576
- - 1: 文档
3577
- - 2: 图片
3578
- - 3: 音频
3579
- - 4: 视频
3580
- - 5: 压缩包
3581
- - 6: 软件/应用
3582
- - 7: 书籍
3583
- - 99: 仅文件
3584
-
3585
- - version: str = <default> 💡 版本号,比如 3.1
4314
+ https://www.yuque.com/115yun/open/gif2n3smh54kyg0p
3586
4315
  """
3587
- api = complete_proapi("/open/ufile/search", base_url)
3588
- if isinstance(payload, str):
3589
- payload = {
3590
- "aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
3591
- "show_dir": 1, "search_value": payload,
3592
- }
3593
- else:
3594
- payload = {
3595
- "aid": 1, "cid": 0, "format": "json", "limit": 32, "offset": 0,
3596
- "show_dir": 1, "search_value": ".", **payload,
3597
- }
3598
- return self.request(url=api, params=payload, async_=async_, **request_kwargs)
4316
+ api = complete_proapi("/open/offline/get_quota_info", base_url)
4317
+ return self.request(url=api, async_=async_, **request_kwargs)
3599
4318
 
3600
4319
  @overload
3601
- def fs_star_set(
4320
+ def offline_remove(
3602
4321
  self,
3603
- payload: int | str | Iterable[int | str] | dict,
4322
+ payload: str | dict,
3604
4323
  /,
3605
- star: bool = True,
3606
4324
  base_url: bool | str | Callable[[], str] = False,
3607
4325
  *,
3608
4326
  async_: Literal[False] = False,
@@ -3610,53 +4328,44 @@ class P115OpenClient(ClientRequestMixin):
3610
4328
  ) -> dict:
3611
4329
  ...
3612
4330
  @overload
3613
- def fs_star_set(
4331
+ def offline_remove(
3614
4332
  self,
3615
- payload: int | str | Iterable[int | str] | dict,
4333
+ payload: str | dict,
3616
4334
  /,
3617
- star: bool = True,
3618
4335
  base_url: bool | str | Callable[[], str] = False,
3619
4336
  *,
3620
4337
  async_: Literal[True],
3621
4338
  **request_kwargs,
3622
4339
  ) -> Coroutine[Any, Any, dict]:
3623
4340
  ...
3624
- def fs_star_set(
4341
+ def offline_remove(
3625
4342
  self,
3626
- payload: int | str | Iterable[int | str] | dict,
4343
+ payload: str | dict,
3627
4344
  /,
3628
- star: bool = True,
3629
4345
  base_url: bool | str | Callable[[], str] = False,
3630
4346
  *,
3631
4347
  async_: Literal[False, True] = False,
3632
4348
  **request_kwargs,
3633
4349
  ) -> dict | Coroutine[Any, Any, dict]:
3634
- """为文件或目录设置或取消星标,此接口是对 `fs_update_open` 的封装
4350
+ """删除用户云下载任务
3635
4351
 
3636
- .. note::
3637
- 即使其中任何一个 id 目前已经被删除,也可以操作成功
4352
+ POST https://proapi.115.com/open/offline/del_task
4353
+
4354
+ .. admonition:: Reference
4355
+
4356
+ https://www.yuque.com/115yun/open/pmgwc86lpcy238nw
3638
4357
 
3639
4358
  :payload:
3640
- - file_id: int | str 💡 只能传入 1 个
3641
- - file_id[0]: int | str 💡 如果有多个,则按顺序给出
3642
- - file_id[1]: int | str
3643
- - ...
3644
- - star: 0 | 1 = 1
4359
+ - info_hash: str 💡 待删除任务的 info_hash
4360
+ - del_source_file: 0 | 1 = <default> 💡 是否删除源文件 1:删除 0:不删除
3645
4361
  """
3646
- api = complete_webapi("/files/star", base_url=base_url)
3647
- if isinstance(payload, (int, str)):
3648
- payload = {"file_id": payload, "star": int(star)}
3649
- elif not isinstance(payload, dict):
3650
- payload = {f"file_id[{i}]": id for i, id in enumerate(payload)}
3651
- if not payload:
3652
- return {"state": False, "message": "no op"}
3653
- payload["star"] = int(star)
3654
- else:
3655
- payload = {"star": int(star), **payload}
3656
- return self.fs_update(payload, async_=async_, **request_kwargs)
4362
+ api = complete_proapi("/open/offline/del_task", base_url)
4363
+ if isinstance(payload, str):
4364
+ payload = {"info_hash": payload}
4365
+ return self.request(api, method="POST", data=payload, async_=async_, **request_kwargs)
3657
4366
 
3658
4367
  @overload
3659
- def fs_update(
4368
+ def offline_torrent_info(
3660
4369
  self,
3661
4370
  payload: dict,
3662
4371
  /,
@@ -3667,7 +4376,7 @@ class P115OpenClient(ClientRequestMixin):
3667
4376
  ) -> dict:
3668
4377
  ...
3669
4378
  @overload
3670
- def fs_update(
4379
+ def offline_torrent_info(
3671
4380
  self,
3672
4381
  payload: dict,
3673
4382
  /,
@@ -3677,7 +4386,7 @@ class P115OpenClient(ClientRequestMixin):
3677
4386
  **request_kwargs,
3678
4387
  ) -> Coroutine[Any, Any, dict]:
3679
4388
  ...
3680
- def fs_update(
4389
+ def offline_torrent_info(
3681
4390
  self,
3682
4391
  payload: dict,
3683
4392
  /,
@@ -3686,27 +4395,19 @@ class P115OpenClient(ClientRequestMixin):
3686
4395
  async_: Literal[False, True] = False,
3687
4396
  **request_kwargs,
3688
4397
  ) -> dict | Coroutine[Any, Any, dict]:
3689
- """设置文件或目录(备注、标签等)
3690
-
3691
- POST https://proapi.115.com/open/ufile/update
4398
+ """解析 BT 种子
3692
4399
 
3693
- .. hint::
3694
- 即使文件已经被删除,也可以操作成功
4400
+ POST https://proapi.115.com/open/offline/torrent
3695
4401
 
3696
4402
  .. admonition:: Reference
3697
4403
 
3698
- https://www.yuque.com/115yun/open/gyrpw5a0zc4sengm
4404
+ https://www.yuque.com/115yun/open/evez3u50cemoict1
3699
4405
 
3700
4406
  :payload:
3701
- - file_id: int | str 💡 只能传入 1 个
3702
- - file_id[0]: int | str 💡 如果有多个,则按顺序给出
3703
- - file_id[1]: int | str
3704
- - ...
3705
- - file_name: str = <default> 💡 文件名
3706
- - star: 0 | 1 = <default> 💡 是否星标:0:取消星标 1:设置星标
3707
- - ...
4407
+ - torrent_sha1: str 💡 种子文件的 sha1
4408
+ - pick_code: str 💡 种子文件的提取码
3708
4409
  """
3709
- api = complete_proapi("/open/ufile/update", base_url)
4410
+ api = complete_proapi("/open/offline/torrent", base_url)
3710
4411
  return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3711
4412
 
3712
4413
  @overload
@@ -3744,7 +4445,8 @@ class P115OpenClient(ClientRequestMixin):
3744
4445
 
3745
4446
  POST https://proapi.115.com/open/rb/del
3746
4447
 
3747
- .. note:
4448
+ .. admonition:: Reference
4449
+
3748
4450
  https://www.yuque.com/115yun/open/gwtof85nmboulrce
3749
4451
 
3750
4452
  :payload:
@@ -4102,7 +4804,7 @@ class P115OpenClient(ClientRequestMixin):
4102
4804
  check_response(resp)
4103
4805
  resp["data"] = {**payload, **resp["data"], "sha1": filesha1, "cid": pid}
4104
4806
  return resp
4105
- return run_gen_step(gen_step, async_=async_)
4807
+ return run_gen_step(gen_step, simple=True, async_=async_)
4106
4808
 
4107
4809
  @overload
4108
4810
  def upload_file(
@@ -4446,7 +5148,7 @@ class P115OpenClient(ClientRequestMixin):
4446
5148
  async_=async_, # type: ignore
4447
5149
  **request_kwargs,
4448
5150
  )
4449
- return run_gen_step(gen_step, async_=async_)
5151
+ return run_gen_step(gen_step, simple=True, async_=async_)
4450
5152
 
4451
5153
  @overload
4452
5154
  def user_info(
@@ -4497,7 +5199,19 @@ class P115OpenClient(ClientRequestMixin):
4497
5199
  fs_move_open = fs_move
4498
5200
  fs_search_open = fs_search
4499
5201
  fs_star_set_open = fs_star_set
5202
+ fs_video_history_open = fs_video_history
5203
+ fs_video_history_set_open = fs_video_history_set
5204
+ fs_video_play_open = fs_video_play
5205
+ fs_video_push_open = fs_video_push
5206
+ fs_video_subtitle_open = fs_video_subtitle
4500
5207
  fs_update_open = fs_update
5208
+ offline_add_torrent_open = offline_add_torrent
5209
+ offline_add_urls_open = offline_add_urls
5210
+ offline_clear_open = offline_clear
5211
+ offline_list_open = offline_list
5212
+ offline_quota_info_open = offline_quota_info
5213
+ offline_remove_open = offline_remove
5214
+ offline_torrent_info_open = offline_torrent_info
4501
5215
  recyclebin_clean_open = recyclebin_clean
4502
5216
  recyclebin_list_open = recyclebin_list
4503
5217
  recyclebin_revert_open = recyclebin_revert
@@ -4815,7 +5529,7 @@ class P115Client(P115OpenClient):
4815
5529
  )
4816
5530
  setattr(self, "check_for_relogin", check_for_relogin)
4817
5531
  return self
4818
- return run_gen_step(gen_step, async_=async_)
5532
+ return run_gen_step(gen_step, simple=True, async_=async_)
4819
5533
 
4820
5534
  @locked_cacheproperty
4821
5535
  def request_lock(self, /) -> Lock:
@@ -4987,7 +5701,7 @@ class P115Client(P115OpenClient):
4987
5701
  check_response(resp)
4988
5702
  setattr(self, "cookies", resp["data"]["cookie"])
4989
5703
  return self
4990
- return run_gen_step(gen_step, async_=async_)
5704
+ return run_gen_step(gen_step, simple=True, async_=async_)
4991
5705
 
4992
5706
  @overload
4993
5707
  def login_with_app(
@@ -5119,7 +5833,7 @@ class P115Client(P115OpenClient):
5119
5833
  async_=async_,
5120
5834
  **request_kwargs,
5121
5835
  )
5122
- return run_gen_step(gen_step, async_=async_)
5836
+ return run_gen_step(gen_step, simple=True, async_=async_)
5123
5837
 
5124
5838
  @overload
5125
5839
  def login_without_app(
@@ -5177,7 +5891,7 @@ class P115Client(P115OpenClient):
5177
5891
  )
5178
5892
  check_response(resp)
5179
5893
  return uid
5180
- return run_gen_step(gen_step, async_=async_)
5894
+ return run_gen_step(gen_step, simple=True, async_=async_)
5181
5895
 
5182
5896
  @overload
5183
5897
  def login_with_open(
@@ -5229,7 +5943,7 @@ class P115Client(P115OpenClient):
5229
5943
  resp = yield self.login_qrcode_scan_confirm(login_uid, async_=async_, **request_kwargs)
5230
5944
  check_response(resp)
5231
5945
  return self.login_qrcode_access_token_open(login_uid, async_=async_, **request_kwargs)
5232
- return run_gen_step(gen_step, async_=async_)
5946
+ return run_gen_step(gen_step, simple=True, async_=async_)
5233
5947
 
5234
5948
  @overload
5235
5949
  def login_another_app(
@@ -5373,7 +6087,7 @@ class P115Client(P115OpenClient):
5373
6087
  if self is not inst and ssoent == inst.login_ssoent:
5374
6088
  warn(f"login with the same ssoent {ssoent!r}, {self!r} will expire within 60 seconds", category=P115Warning)
5375
6089
  return inst
5376
- return run_gen_step(gen_step, async_=async_)
6090
+ return run_gen_step(gen_step, simple=True, async_=async_)
5377
6091
 
5378
6092
  @overload
5379
6093
  def login_another_open(
@@ -5467,7 +6181,7 @@ class P115Client(P115OpenClient):
5467
6181
  inst.access_token = data["access_token"]
5468
6182
  inst.app_id = app_id
5469
6183
  return inst
5470
- return run_gen_step(gen_step, async_=async_)
6184
+ return run_gen_step(gen_step, simple=True, async_=async_)
5471
6185
 
5472
6186
  @overload
5473
6187
  @classmethod
@@ -5586,7 +6300,7 @@ class P115Client(P115OpenClient):
5586
6300
  resp = yield cls.login_qrcode_scan_result(uid, app, async_=async_, **request_kwargs)
5587
6301
  cookies = check_response(resp)["data"]["cookie"]
5588
6302
  return cls(cookies, check_for_relogin=check_for_relogin)
5589
- return run_gen_step(gen_step, async_=async_)
6303
+ return run_gen_step(gen_step, simple=True, async_=async_)
5590
6304
 
5591
6305
  @overload
5592
6306
  def logout(
@@ -5738,7 +6452,7 @@ class P115Client(P115OpenClient):
5738
6452
  if async_:
5739
6453
  fetch_cert_headers = ensure_async(fetch_cert_headers)
5740
6454
  if fetch_cert_headers_argcount:
5741
- fetch_cert_headers = partial(fetch_cert_headers, async_)
6455
+ fetch_cert_headers = cast(Callable, fetch_cert_headers)(async_)
5742
6456
  if revert_cert_headers is not None and async_:
5743
6457
  revert_cert_headers = ensure_async(revert_cert_headers)
5744
6458
  if is_open_api:
@@ -5768,7 +6482,7 @@ class P115Client(P115OpenClient):
5768
6482
  def gen_step():
5769
6483
  cert_headers: None | Mapping = None
5770
6484
  if need_fetch_cert_first:
5771
- cert_headers = yield fetch_cert_headers
6485
+ cert_headers = yield cast(Callable, fetch_cert_headers)()
5772
6486
  headers.update(cert_headers)
5773
6487
  if async_:
5774
6488
  lock: Lock | AsyncLock = self.request_alock
@@ -5792,8 +6506,7 @@ class P115Client(P115OpenClient):
5792
6506
  cert: str = headers["authorization"]
5793
6507
  else:
5794
6508
  cert = headers["cookie"]
5795
- resp = yield partial(
5796
- cast(Callable, request),
6509
+ resp = yield cast(Callable, request)(
5797
6510
  url=url,
5798
6511
  method=method,
5799
6512
  **request_kwargs,
@@ -5806,14 +6519,14 @@ class P115Client(P115OpenClient):
5806
6519
  not is_auth_error and
5807
6520
  get_status_code(e) != 405
5808
6521
  ):
5809
- yield partial(revert_cert_headers, cert_headers)
6522
+ yield revert_cert_headers(cert_headers)
5810
6523
  if not need_to_check:
5811
6524
  raise
5812
- res = yield partial(cast(Callable, check_for_relogin), e)
6525
+ res = yield cast(Callable, check_for_relogin)(e)
5813
6526
  if not res if isinstance(res, bool) else res != 405:
5814
6527
  raise
5815
6528
  if fetch_cert_headers is not None:
5816
- cert_headers = yield fetch_cert_headers
6529
+ cert_headers = yield fetch_cert_headers()
5817
6530
  headers.update(cert_headers)
5818
6531
  elif is_open_api:
5819
6532
  yield lock.acquire
@@ -5858,11 +6571,11 @@ class P115Client(P115OpenClient):
5858
6571
  lock.release()
5859
6572
  else:
5860
6573
  if cert_headers is not None and revert_cert_headers is not None:
5861
- yield partial(revert_cert_headers, cert_headers)
6574
+ yield revert_cert_headers(cert_headers)
5862
6575
  if check and isinstance(resp, dict):
5863
6576
  check_response(resp)
5864
6577
  return resp
5865
- return run_gen_step(gen_step, async_=async_)
6578
+ return run_gen_step(gen_step, simple=True, async_=async_)
5866
6579
 
5867
6580
  def request(
5868
6581
  self,
@@ -6714,15 +7427,14 @@ class P115Client(P115OpenClient):
6714
7427
  if "sign" not in payload:
6715
7428
  resp = yield self.captcha_sign(async_=async_)
6716
7429
  payload["sign"] = resp["sign"]
6717
- return partial(
6718
- self.request,
7430
+ return self.request(
6719
7431
  url=api,
6720
7432
  method="POST",
6721
7433
  data=payload,
6722
7434
  async_=async_,
6723
7435
  **request_kwargs,
6724
7436
  )
6725
- return run_gen_step(gen_step, async_=async_)
7437
+ return run_gen_step(gen_step, simple=True, async_=async_)
6726
7438
 
6727
7439
  ########## Download API ##########
6728
7440
 
@@ -15297,7 +16009,7 @@ class P115Client(P115OpenClient):
15297
16009
  if device is None:
15298
16010
  return None
15299
16011
  return device["icon"]
15300
- return run_gen_step(gen_step, async_=async_)
16012
+ return run_gen_step(gen_step, simple=True, async_=async_)
15301
16013
 
15302
16014
  @overload
15303
16015
  def login_open_auth_detail(
@@ -15821,7 +16533,7 @@ class P115Client(P115OpenClient):
15821
16533
  return get_default_request()(url=api, async_=async_, **request_kwargs)
15822
16534
  else:
15823
16535
  return request(url=api, **request_kwargs)
15824
- return run_gen_step(gen_step, async_=async_)
16536
+ return run_gen_step(gen_step, simple=True, async_=async_)
15825
16537
 
15826
16538
  @overload
15827
16539
  def logout_by_ssoent(
@@ -16914,7 +17626,7 @@ class P115Client(P115OpenClient):
16914
17626
  method = self._offline_lixianssp_post
16915
17627
  return method(payload, ac, async_=async_, ecdh_encrypt=ecdh_encrypt, **request_kwargs)
16916
17628
 
16917
- @overload
17629
+ @overload # type: ignore
16918
17630
  def offline_add_torrent(
16919
17631
  self,
16920
17632
  payload: str | dict,
@@ -16956,8 +17668,8 @@ class P115Client(P115OpenClient):
16956
17668
 
16957
17669
  :payload:
16958
17670
  - info_hash: str 💡 种子文件的 info_hash
16959
- - wanted: str = <default> 💡 选择文件进行下载(是数字用 "," 分隔)
16960
- - savepath: str = <default> 💡 保存到目录下的相对路径
17671
+ - wanted: str = <default> 💡 选择文件进行下载(是数字索引,从 0 开始计数,用 "," 分隔)
17672
+ - savepath: str = <default> 💡 保存到 `wp_path_id` 对应目录下的相对路径
16961
17673
  - wp_path_id: int | str = <default> 💡 保存到目录的 id
16962
17674
  """
16963
17675
  if isinstance(payload, str):
@@ -17008,7 +17720,7 @@ class P115Client(P115OpenClient):
17008
17720
  payload = {"url": payload}
17009
17721
  return self._offline_post(payload, "add_task_url", use_web_api=use_web_api, async_=async_, **request_kwargs)
17010
17722
 
17011
- @overload
17723
+ @overload # type: ignore
17012
17724
  def offline_add_urls(
17013
17725
  self,
17014
17726
  payload: str | Iterable[str] | dict,
@@ -17051,7 +17763,7 @@ class P115Client(P115OpenClient):
17051
17763
  - wp_path_id: int | str = <default> 💡 保存到目录的 id
17052
17764
  """
17053
17765
  if isinstance(payload, str):
17054
- payload = payload.strip().split("\n")
17766
+ payload = payload.strip("\n").split("\n")
17055
17767
  if not isinstance(payload, dict):
17056
17768
  payload = {f"url[{i}]": url for i, url in enumerate(payload)}
17057
17769
  if not payload:
@@ -17061,7 +17773,7 @@ class P115Client(P115OpenClient):
17061
17773
  @overload
17062
17774
  def offline_clear(
17063
17775
  self,
17064
- payload: int | dict,
17776
+ payload: int | dict = 0,
17065
17777
  /,
17066
17778
  base_url: None | bool | str | Callable[[], str] = None,
17067
17779
  *,
@@ -17072,7 +17784,7 @@ class P115Client(P115OpenClient):
17072
17784
  @overload
17073
17785
  def offline_clear(
17074
17786
  self,
17075
- payload: int | dict,
17787
+ payload: int | dict = 0,
17076
17788
  /,
17077
17789
  base_url: None | bool | str | Callable[[], str] = None,
17078
17790
  *,
@@ -17082,7 +17794,7 @@ class P115Client(P115OpenClient):
17082
17794
  ...
17083
17795
  def offline_clear(
17084
17796
  self,
17085
- payload: int | dict = {"flag": 0},
17797
+ payload: int | dict = 0,
17086
17798
  /,
17087
17799
  base_url: None | bool | str | Callable[[], str] = None,
17088
17800
  *,
@@ -17105,11 +17817,6 @@ class P115Client(P115OpenClient):
17105
17817
  """
17106
17818
  api = complete_lixian_api("?ct=lixian&ac=task_clear", base_url=base_url)
17107
17819
  if isinstance(payload, int):
17108
- flag = payload
17109
- if flag < 0:
17110
- flag = 0
17111
- elif flag > 5:
17112
- flag = 5
17113
17820
  payload = {"flag": payload}
17114
17821
  return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
17115
17822
 
@@ -17183,7 +17890,7 @@ class P115Client(P115OpenClient):
17183
17890
  api = complete_api("/?ct=offline&ac=space", base_url=base_url)
17184
17891
  return self.request(url=api, async_=async_, **request_kwargs)
17185
17892
 
17186
- @overload
17893
+ @overload # type: ignore
17187
17894
  def offline_list(
17188
17895
  self,
17189
17896
  payload: int | dict = 1,
@@ -17219,7 +17926,7 @@ class P115Client(P115OpenClient):
17219
17926
  POST https://lixian.115.com/lixian/?ct=lixian&ac=task_lists
17220
17927
 
17221
17928
  :payload:
17222
- - page: int | str
17929
+ - page: int | str = 1
17223
17930
  """
17224
17931
  api = complete_lixian_api("?ct=lixian&ac=task_lists", base_url=base_url)
17225
17932
  if isinstance(payload, int):
@@ -17334,7 +18041,7 @@ class P115Client(P115OpenClient):
17334
18041
  @overload
17335
18042
  def offline_remove(
17336
18043
  self,
17337
- payload: str | dict,
18044
+ payload: str | Iterable[str] | dict,
17338
18045
  /,
17339
18046
  base_url: None | bool | str | Callable[[], str] = None,
17340
18047
  *,
@@ -17345,7 +18052,7 @@ class P115Client(P115OpenClient):
17345
18052
  @overload
17346
18053
  def offline_remove(
17347
18054
  self,
17348
- payload: str | dict,
18055
+ payload: str | Iterable[str] | dict,
17349
18056
  /,
17350
18057
  base_url: None | bool | str | Callable[[], str] = None,
17351
18058
  *,
@@ -17355,7 +18062,7 @@ class P115Client(P115OpenClient):
17355
18062
  ...
17356
18063
  def offline_remove(
17357
18064
  self,
17358
- payload: str | dict,
18065
+ payload: str | Iterable[str] | dict,
17359
18066
  /,
17360
18067
  base_url: None | bool | str | Callable[[], str] = None,
17361
18068
  *,
@@ -19720,7 +20427,7 @@ class P115Client(P115OpenClient):
19720
20427
  if resp["state"]:
19721
20428
  self.user_key = resp["data"]["userkey"]
19722
20429
  return resp
19723
- return run_gen_step(gen_step, async_=async_)
20430
+ return run_gen_step(gen_step, simple=True, async_=async_)
19724
20431
 
19725
20432
  @overload
19726
20433
  def upload_resume(
@@ -20087,7 +20794,7 @@ class P115Client(P115OpenClient):
20087
20794
  "pickcode": resp["pickcode"],
20088
20795
  }
20089
20796
  return resp
20090
- return run_gen_step(gen_step, async_=async_)
20797
+ return run_gen_step(gen_step, simple=True, async_=async_)
20091
20798
 
20092
20799
  @overload
20093
20800
  def upload_file_sample(
@@ -20223,7 +20930,7 @@ class P115Client(P115OpenClient):
20223
20930
  async_=async_,
20224
20931
  **request_kwargs,
20225
20932
  )
20226
- return run_gen_step(gen_step, async_=async_)
20933
+ return run_gen_step(gen_step, simple=True, async_=async_)
20227
20934
 
20228
20935
  @overload # type: ignore
20229
20936
  def upload_file(
@@ -20582,7 +21289,7 @@ class P115Client(P115OpenClient):
20582
21289
  async_=async_, # type: ignore
20583
21290
  **request_kwargs,
20584
21291
  )
20585
- return run_gen_step(gen_step, async_=async_)
21292
+ return run_gen_step(gen_step, simple=True, async_=async_)
20586
21293
 
20587
21294
  ########## User API ##########
20588
21295