p115client 0.0.5.11.11__py3-none-any.whl → 0.0.5.12.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
@@ -15,6 +15,7 @@ from collections.abc import (
15
15
  AsyncGenerator, AsyncIterable, Awaitable, Buffer, Callable, Coroutine, Generator,
16
16
  ItemsView, Iterable, Iterator, Mapping, MutableMapping, Sequence,
17
17
  )
18
+ from contextlib import contextmanager
18
19
  from datetime import date, datetime, timedelta
19
20
  from functools import partial
20
21
  from hashlib import md5, sha1
@@ -30,11 +31,12 @@ from platform import system
30
31
  from posixpath import splitext
31
32
  from re import compile as re_compile, MULTILINE
32
33
  from string import digits
34
+ from sys import _getframe
33
35
  from tempfile import TemporaryFile
34
36
  from threading import Lock
35
37
  from time import time
36
38
  from typing import cast, overload, Any, Final, Literal, Self, Unpack
37
- from urllib.parse import quote, unquote, urlencode, urlsplit, urlunsplit
39
+ from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit
38
40
  from uuid import uuid4
39
41
  from warnings import warn
40
42
 
@@ -63,7 +65,10 @@ from startfile import startfile, startfile_async # type: ignore
63
65
  from undefined import undefined
64
66
  from yarl import URL
65
67
 
66
- from .const import CLASS_TO_TYPE, CLIENT_API_MAP, SSOENT_TO_APP, SUFFIX_TO_TYPE, errno
68
+ from .const import (
69
+ CLASS_TO_TYPE, CLIENT_API_METHODS_MAP, CLIENT_METHOD_API_MAP,
70
+ SSOENT_TO_APP, SUFFIX_TO_TYPE, errno,
71
+ )
67
72
  from .exception import (
68
73
  AccessTokenError, AuthenticationError, BusyOSError, DataError, LoginError,
69
74
  OpenAppAuthLimitExceeded, NotSupportedError, P115OSError, OperationalError,
@@ -74,7 +79,6 @@ from ._upload import buffer_length, make_dataiter, oss_upload, oss_multipart_upl
74
79
 
75
80
 
76
81
  CRE_SET_COOKIE: Final = re_compile(r"[0-9a-f]{32}=[0-9a-f]{32}.*")
77
- CRE_CLIENT_API_search: Final = re_compile(r"^ +((?:GET|POST) .*)", MULTILINE).search
78
82
  CRE_COOKIES_UID_search: Final = re_compile(r"(?<=\bUID=)[^\s;]+").search
79
83
  CRE_API_match: Final = re_compile(r"http://(web|pro)api.115.com(?=/|\?|#|$)").match
80
84
  ED2K_NAME_TRANSTAB: Final = dict(zip(b"/|", ("%2F", "%7C")))
@@ -229,6 +233,20 @@ def try_parse_int(
229
233
  return int(s)
230
234
 
231
235
 
236
+ @contextmanager
237
+ def temp_globals(f_globals: None | dict = None, /, **ns):
238
+ if f_globals is None:
239
+ f_globals = _getframe(2).f_globals
240
+ old_globals = f_globals.copy()
241
+ if ns:
242
+ f_globals.update(ns)
243
+ try:
244
+ yield f_globals
245
+ finally:
246
+ f_globals.clear()
247
+ f_globals.update(old_globals)
248
+
249
+
232
250
  def json_loads(content: Buffer, /):
233
251
  try:
234
252
  if isinstance(content, (bytes, bytearray, memoryview)):
@@ -1573,6 +1591,19 @@ class ClientRequestMixin:
1573
1591
  """
1574
1592
  api = complete_api("/open/authorize", base_url=base_url)
1575
1593
  payload = {"response_type": "code", **payload}
1594
+ def parse(resp, content, /):
1595
+ if resp.status_code == 302:
1596
+ return {
1597
+ "state": True,
1598
+ "url": resp.headers["location"],
1599
+ "data": dict(parse_qsl(urlsplit(resp.headers["location"]).query)),
1600
+ "headers": dict(resp.headers),
1601
+ }
1602
+ else:
1603
+ return json_loads(content)
1604
+ request_kwargs["parse"] = parse
1605
+ for key in ("allow_redirects", "follow_redirects", "redirect"):
1606
+ request_kwargs[key] = False
1576
1607
  return self.request(url=api, params=payload, async_=async_, **request_kwargs)
1577
1608
 
1578
1609
  @overload
@@ -2615,7 +2646,6 @@ class ClientRequestMixin:
2615
2646
 
2616
2647
  :return: 文件的 ed2k 链接
2617
2648
  """
2618
- trantab = dict(zip(b"/|", ("%2F", "%7C")))
2619
2649
  if async_:
2620
2650
  async def request():
2621
2651
  async with self.open(url, headers=headers, async_=True) as file:
@@ -3481,6 +3511,7 @@ class P115OpenClient(ClientRequestMixin):
3481
3511
  - "user_ptime": 创建时间(无效,效果相当于 "user_utime")
3482
3512
  - "user_otime": 上一次打开时间(无效,效果相当于 "user_utime")
3483
3513
 
3514
+ - qid: int = <default>
3484
3515
  - r_all: 0 | 1 = <default>
3485
3516
  - record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
3486
3517
  - scid: int | str = <default>
@@ -3861,7 +3892,7 @@ class P115OpenClient(ClientRequestMixin):
3861
3892
  return self.fs_update(payload, async_=async_, **request_kwargs)
3862
3893
 
3863
3894
  @overload
3864
- def fs_video_history(
3895
+ def fs_video(
3865
3896
  self,
3866
3897
  payload: str | dict,
3867
3898
  /,
@@ -3872,7 +3903,7 @@ class P115OpenClient(ClientRequestMixin):
3872
3903
  ) -> dict:
3873
3904
  ...
3874
3905
  @overload
3875
- def fs_video_history(
3906
+ def fs_video(
3876
3907
  self,
3877
3908
  payload: str | dict,
3878
3909
  /,
@@ -3882,7 +3913,7 @@ class P115OpenClient(ClientRequestMixin):
3882
3913
  **request_kwargs,
3883
3914
  ) -> Coroutine[Any, Any, dict]:
3884
3915
  ...
3885
- def fs_video_history(
3916
+ def fs_video(
3886
3917
  self,
3887
3918
  payload: str | dict,
3888
3919
  /,
@@ -3891,24 +3922,28 @@ class P115OpenClient(ClientRequestMixin):
3891
3922
  async_: Literal[False, True] = False,
3892
3923
  **request_kwargs,
3893
3924
  ) -> dict | Coroutine[Any, Any, dict]:
3894
- """获取视频播放进度
3895
-
3896
- GET https://proapi.115.com/open/video/history
3925
+ """获取视频在线播放地址(和视频文件相关数据)
3897
3926
 
3927
+ GET https://proapi.115.com/open/video/play
3928
+
3898
3929
  .. admonition:: Reference
3899
3930
 
3900
- https://www.yuque.com/115yun/open/gssqdrsq6vfqigag
3931
+ https://www.yuque.com/115yun/open/hqglxv3cedi3p9dz
3932
+
3933
+ .. hint::
3934
+ 需切换音轨时,在请求返回的播放地址中增加请求参数 `&audio_track=${index}`,值就是接口响应中 `multitrack_list` 中某个成员的索引,从 0 开始计数
3901
3935
 
3902
3936
  :payload:
3903
3937
  - pick_code: str 💡 文件提取码
3938
+ - share_id: int | str = <default> 💡 共享 id,获取共享文件播放地址所需
3904
3939
  """
3905
- api = complete_proapi("/open/video/history", base_url)
3940
+ api = complete_proapi("/open/video/play", base_url)
3906
3941
  if isinstance(payload, str):
3907
3942
  payload = {"pick_code": payload}
3908
3943
  return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3909
3944
 
3910
3945
  @overload
3911
- def fs_video_history_set(
3946
+ def fs_video_history(
3912
3947
  self,
3913
3948
  payload: str | dict,
3914
3949
  /,
@@ -3919,7 +3954,7 @@ class P115OpenClient(ClientRequestMixin):
3919
3954
  ) -> dict:
3920
3955
  ...
3921
3956
  @overload
3922
- def fs_video_history_set(
3957
+ def fs_video_history(
3923
3958
  self,
3924
3959
  payload: str | dict,
3925
3960
  /,
@@ -3929,7 +3964,7 @@ class P115OpenClient(ClientRequestMixin):
3929
3964
  **request_kwargs,
3930
3965
  ) -> Coroutine[Any, Any, dict]:
3931
3966
  ...
3932
- def fs_video_history_set(
3967
+ def fs_video_history(
3933
3968
  self,
3934
3969
  payload: str | dict,
3935
3970
  /,
@@ -3938,26 +3973,24 @@ class P115OpenClient(ClientRequestMixin):
3938
3973
  async_: Literal[False, True] = False,
3939
3974
  **request_kwargs,
3940
3975
  ) -> dict | Coroutine[Any, Any, dict]:
3941
- """记忆视频播放进度
3976
+ """获取视频播放进度
3942
3977
 
3943
- POST https://proapi.115.com/open/video/history
3978
+ GET https://proapi.115.com/open/video/history
3944
3979
 
3945
3980
  .. admonition:: Reference
3946
3981
 
3947
- https://www.yuque.com/115yun/open/bshagbxv1gzqglg4
3982
+ https://www.yuque.com/115yun/open/gssqdrsq6vfqigag
3948
3983
 
3949
3984
  :payload:
3950
3985
  - pick_code: str 💡 文件提取码
3951
- - time: int = <default> 💡 视频播放进度时长 (单位秒)
3952
- - watch_end: int = <default> 💡 视频是否播放播放完毕 0:未完毕 1:完毕
3953
3986
  """
3954
3987
  api = complete_proapi("/open/video/history", base_url)
3955
3988
  if isinstance(payload, str):
3956
3989
  payload = {"pick_code": payload}
3957
- return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
3990
+ return self.request(url=api, params=payload, async_=async_, **request_kwargs)
3958
3991
 
3959
3992
  @overload
3960
- def fs_video_play(
3993
+ def fs_video_history_set(
3961
3994
  self,
3962
3995
  payload: str | dict,
3963
3996
  /,
@@ -3968,7 +4001,7 @@ class P115OpenClient(ClientRequestMixin):
3968
4001
  ) -> dict:
3969
4002
  ...
3970
4003
  @overload
3971
- def fs_video_play(
4004
+ def fs_video_history_set(
3972
4005
  self,
3973
4006
  payload: str | dict,
3974
4007
  /,
@@ -3978,7 +4011,7 @@ class P115OpenClient(ClientRequestMixin):
3978
4011
  **request_kwargs,
3979
4012
  ) -> Coroutine[Any, Any, dict]:
3980
4013
  ...
3981
- def fs_video_play(
4014
+ def fs_video_history_set(
3982
4015
  self,
3983
4016
  payload: str | dict,
3984
4017
  /,
@@ -3987,25 +4020,23 @@ class P115OpenClient(ClientRequestMixin):
3987
4020
  async_: Literal[False, True] = False,
3988
4021
  **request_kwargs,
3989
4022
  ) -> dict | Coroutine[Any, Any, dict]:
3990
- """获取视频在线播放地址(和视频文件相关数据)
4023
+ """记忆视频播放进度
3991
4024
 
3992
- GET https://proapi.115.com/open/video/play
3993
-
3994
- .. admonition:: Reference
4025
+ POST https://proapi.115.com/open/video/history
3995
4026
 
3996
- https://www.yuque.com/115yun/open/hqglxv3cedi3p9dz
4027
+ .. admonition:: Reference
3997
4028
 
3998
- .. hint::
3999
- 需切换音轨时,在请求返回的播放地址中增加请求参数 `&audio_track=${index}`,值就是接口响应中 `multitrack_list` 中某个成员的索引,从 0 开始计数
4029
+ https://www.yuque.com/115yun/open/bshagbxv1gzqglg4
4000
4030
 
4001
4031
  :payload:
4002
4032
  - pick_code: str 💡 文件提取码
4003
- - share_id: int | str = <default> 💡 共享 id,获取共享文件播放地址所需
4033
+ - time: int = <default> 💡 视频播放进度时长 (单位秒)
4034
+ - watch_end: int = <default> 💡 视频是否播放播放完毕 0:未完毕 1:完毕
4004
4035
  """
4005
- api = complete_proapi("/open/video/play", base_url)
4036
+ api = complete_proapi("/open/video/history", base_url)
4006
4037
  if isinstance(payload, str):
4007
4038
  payload = {"pick_code": payload}
4008
- return self.request(url=api, params=payload, async_=async_, **request_kwargs)
4039
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
4009
4040
 
4010
4041
  @overload
4011
4042
  def fs_video_push(
@@ -4048,13 +4079,15 @@ class P115OpenClient(ClientRequestMixin):
4048
4079
 
4049
4080
  :payload:
4050
4081
  - pick_code: str 💡 文件提取码
4051
- - op: str = "vip_push" 💡 提交视频加速转码方式:vip_push:根据;vip 等级加速 pay_push:枫叶加速
4082
+ - op: str = "vip_push" 💡 提交视频加速转码方式
4083
+
4084
+ - "vip_push": 根据;vip 等级加速
4085
+ - "pay_push": 枫叶加速
4052
4086
  """
4053
4087
  api = complete_proapi("/open/video/video_push", base_url)
4054
4088
  if isinstance(payload, str):
4055
- payload = {"pick_code": payload, "op": "vip_push"}
4056
- else:
4057
- payload.setdefault("op", "vip_push")
4089
+ payload = {"pick_code": payload}
4090
+ payload.setdefault("op", "vip_push")
4058
4091
  return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
4059
4092
 
4060
4093
  @overload
@@ -5305,7 +5338,7 @@ class P115OpenClient(ClientRequestMixin):
5305
5338
  ) -> dict | Coroutine[Any, Any, dict]:
5306
5339
  """获取产品列表地址(即引导用户扫码购买 115 的 VIP 服务,以获取提成)
5307
5340
 
5308
- GET https://proapi.115.com/open/open/vip/qr_url
5341
+ GET https://proapi.115.com/open/vip/qr_url
5309
5342
 
5310
5343
  .. admonition:: Reference
5311
5344
 
@@ -5336,9 +5369,9 @@ class P115OpenClient(ClientRequestMixin):
5336
5369
  fs_move_open = fs_move
5337
5370
  fs_search_open = fs_search
5338
5371
  fs_star_set_open = fs_star_set
5372
+ fs_video_open = fs_video
5339
5373
  fs_video_history_open = fs_video_history
5340
5374
  fs_video_history_set_open = fs_video_history_set
5341
- fs_video_play_open = fs_video_play
5342
5375
  fs_video_push_open = fs_video_push
5343
5376
  fs_video_subtitle_open = fs_video_subtitle
5344
5377
  fs_update_open = fs_update
@@ -10960,6 +10993,8 @@ class P115Client(P115OpenClient):
10960
10993
  payload = {"fetch": "one", **payload}
10961
10994
  return self.request(url=api, params=payload, async_=async_, **request_kwargs)
10962
10995
 
10996
+ fs_video_history = fs_files_history
10997
+
10963
10998
  @overload
10964
10999
  def fs_files_history_set(
10965
11000
  self,
@@ -11002,6 +11037,7 @@ class P115Client(P115OpenClient):
11002
11037
  - definition: int = <default> 💡 视频清晰度
11003
11038
  - share_id: int | str = <default>
11004
11039
  - time: int = <default> 💡 播放时间点(用来向服务器同步播放进度)
11040
+ - watch_end: int = <default> 💡 视频是否播放播放完毕 0:未完毕 1:完毕
11005
11041
  - ...(其它未找全的参数)
11006
11042
  """
11007
11043
  api = complete_webapi("/files/history", base_url=base_url)
@@ -11011,6 +11047,8 @@ class P115Client(P115OpenClient):
11011
11047
  payload = {"op": "update", **payload}
11012
11048
  return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
11013
11049
 
11050
+ fs_video_history_set = fs_files_history_set
11051
+
11014
11052
  @overload
11015
11053
  def fs_files_second_type(
11016
11054
  self,
@@ -13232,7 +13270,7 @@ class P115Client(P115OpenClient):
13232
13270
  GET https://proapi.115.com/android/music/musicplay
13233
13271
 
13234
13272
  .. note::
13235
- 即使文件格式不正确或者过大(超过 200MB),也可返回一些信息(包括 parent_id),但如果是目录则信息匮乏(但由此也可判定一个目录)
13273
+ 即使文件格式不正确或者过大(超过 200 MB),也可返回一些信息(包括 parent_id),但如果是目录则信息匮乏(但由此也可判定一个目录)
13236
13274
 
13237
13275
  :payload:
13238
13276
  - pickcode: str 💡 提取码
@@ -15374,11 +15412,21 @@ class P115Client(P115OpenClient):
15374
15412
 
15375
15413
  GET https://webapi.115.com/files/video
15376
15414
 
15415
+ .. caution::
15416
+ `local` 在有些视频上不起作用,无论如何,都相当于 `local=0`,可能是因为文件超过 200 MB
15417
+
15418
+ 但如果 `local=1` 有效,则返回仅可得到下载链接,key 为 "download_url"
15419
+
15377
15420
  .. important::
15378
15421
  仅这几种设备可用:`harmony`, `web`, `desktop`, **wechatmini**, **alipaymini**, **tv**
15379
15422
 
15380
15423
  但是如果要获取 m3u8 文件,则要提供 web 设备的 cookies,否则返回空数据
15381
15424
 
15425
+ .. note::
15426
+ 如果返回信息中有 "queue_url",则可用于查询转码状态
15427
+
15428
+ 如果视频从未被转码过,则会自动推送转码
15429
+
15382
15430
  :payload:
15383
15431
  - pickcode: str 💡 提取码
15384
15432
  - share_id: int | str = <default> 💡 分享 id
@@ -15650,6 +15698,57 @@ class P115Client(P115OpenClient):
15650
15698
  payload = {"pickcode": payload}
15651
15699
  return self.request(url=api, params=payload, async_=async_, **request_kwargs)
15652
15700
 
15701
+ @overload
15702
+ def fs_video_transcode(
15703
+ self,
15704
+ payload: dict | str,
15705
+ /,
15706
+ app: str = "web",
15707
+ base_url: bool | str | Callable[[], str] = False,
15708
+ method: str = "GET",
15709
+ *,
15710
+ async_: Literal[False] = False,
15711
+ **request_kwargs,
15712
+ ) -> dict:
15713
+ ...
15714
+ @overload
15715
+ def fs_video_transcode(
15716
+ self,
15717
+ payload: dict | str,
15718
+ /,
15719
+ app: str = "web",
15720
+ base_url: bool | str | Callable[[], str] = False,
15721
+ method: str = "GET",
15722
+ *,
15723
+ async_: Literal[True],
15724
+ **request_kwargs,
15725
+ ) -> Coroutine[Any, Any, dict]:
15726
+ ...
15727
+ def fs_video_transcode(
15728
+ self,
15729
+ payload: dict | str,
15730
+ /,
15731
+ app: str = "web",
15732
+ base_url: bool | str | Callable[[], str] = False,
15733
+ method: str = "GET",
15734
+ *,
15735
+ async_: Literal[False, True] = False,
15736
+ **request_kwargs,
15737
+ ) -> dict | Coroutine[Any, Any, dict]:
15738
+ """获取视频的转码进度
15739
+
15740
+ GET http://transcode.115.com/api/1.0/android/1.0/trans_code/check_transcode_job
15741
+
15742
+ :payload:
15743
+ - sha1: str
15744
+ - priority: int = 100 💡 优先级
15745
+ """
15746
+ api = complete_api(f"/api/1.0/{app}/1.0/trans_code/check_transcode_job", "transcode", base_url=base_url)
15747
+ if isinstance(payload, str):
15748
+ payload = {"sha1": payload}
15749
+ payload.setdefault("priority", 100)
15750
+ return self.request(url=api, method=method, params=payload, async_=async_, **request_kwargs)
15751
+
15653
15752
  ########## Life API ##########
15654
15753
 
15655
15754
  @overload
@@ -17730,32 +17829,35 @@ class P115Client(P115OpenClient):
17730
17829
  ########## Offline Download API ##########
17731
17830
 
17732
17831
  @overload
17733
- def _offline_web_post(
17832
+ def _offline_web_request(
17734
17833
  self,
17735
- payload: dict,
17834
+ payload: dict = {},
17736
17835
  /,
17737
17836
  ac: str = "",
17837
+ method: str = "POST",
17738
17838
  *,
17739
17839
  async_: Literal[False] = False,
17740
17840
  **request_kwargs,
17741
17841
  ) -> dict:
17742
17842
  ...
17743
17843
  @overload
17744
- def _offline_web_post(
17844
+ def _offline_web_request(
17745
17845
  self,
17746
- payload: dict,
17846
+ payload: dict = {},
17747
17847
  /,
17748
17848
  ac: str = "",
17849
+ method: str = "POST",
17749
17850
  *,
17750
17851
  async_: Literal[True],
17751
17852
  **request_kwargs,
17752
17853
  ) -> Coroutine[Any, Any, dict]:
17753
17854
  ...
17754
- def _offline_web_post(
17855
+ def _offline_web_request(
17755
17856
  self,
17756
- payload: dict,
17857
+ payload: dict = {},
17757
17858
  /,
17758
17859
  ac: str = "",
17860
+ method: str = "POST",
17759
17861
  *,
17760
17862
  async_: Literal[False, True] = False,
17761
17863
  **request_kwargs,
@@ -17763,41 +17865,47 @@ class P115Client(P115OpenClient):
17763
17865
  api = "http://lixian.115.com/web/lixian/"
17764
17866
  if ac:
17765
17867
  payload["ac"] = ac
17868
+ if method.upper() == "POST":
17869
+ request_kwargs["data"] = payload
17870
+ else:
17871
+ request_kwargs["params"] = payload
17766
17872
  return self.request(
17767
17873
  url=api,
17768
- method="POST",
17769
- data=payload,
17874
+ method=method,
17770
17875
  async_=async_,
17771
17876
  **request_kwargs,
17772
17877
  )
17773
17878
 
17774
17879
  @overload
17775
- def _offline_lixian_post(
17880
+ def _offline_lixian_request(
17776
17881
  self,
17777
- payload: dict,
17882
+ payload: dict = {},
17778
17883
  /,
17779
17884
  ac: str = "",
17885
+ method: str = "POST",
17780
17886
  *,
17781
17887
  async_: Literal[False] = False,
17782
17888
  **request_kwargs,
17783
17889
  ) -> dict:
17784
17890
  ...
17785
17891
  @overload
17786
- def _offline_lixian_post(
17892
+ def _offline_lixian_request(
17787
17893
  self,
17788
- payload: dict,
17894
+ payload: dict = {},
17789
17895
  /,
17790
17896
  ac: str = "",
17897
+ method: str = "POST",
17791
17898
  *,
17792
17899
  async_: Literal[True],
17793
17900
  **request_kwargs,
17794
17901
  ) -> Coroutine[Any, Any, dict]:
17795
17902
  ...
17796
- def _offline_lixian_post(
17903
+ def _offline_lixian_request(
17797
17904
  self,
17798
- payload: dict,
17905
+ payload: dict = {},
17799
17906
  /,
17800
17907
  ac: str = "",
17908
+ method: str = "POST",
17801
17909
  *,
17802
17910
  async_: Literal[False, True] = False,
17803
17911
  **request_kwargs,
@@ -17805,19 +17913,22 @@ class P115Client(P115OpenClient):
17805
17913
  api = "http://lixian.115.com/lixian/"
17806
17914
  if ac:
17807
17915
  payload["ac"] = ac
17808
- request_kwargs["ecdh_encrypt"] = True
17916
+ if method.upper() == "POST":
17917
+ request_kwargs["data"] = payload
17918
+ request_kwargs["ecdh_encrypt"] = True
17919
+ else:
17920
+ request_kwargs["params"] = payload
17809
17921
  return self.request(
17810
17922
  url=api,
17811
- method="POST",
17812
- data=payload,
17923
+ method=method,
17813
17924
  async_=async_,
17814
17925
  **request_kwargs,
17815
17926
  )
17816
17927
 
17817
17928
  @overload
17818
- def _offline_lixianssp_post(
17929
+ def _offline_lixianssp_request(
17819
17930
  self,
17820
- payload: dict,
17931
+ payload: dict = {},
17821
17932
  /,
17822
17933
  ac: str = "",
17823
17934
  *,
@@ -17826,9 +17937,9 @@ class P115Client(P115OpenClient):
17826
17937
  ) -> dict:
17827
17938
  ...
17828
17939
  @overload
17829
- def _offline_lixianssp_post(
17940
+ def _offline_lixianssp_request(
17830
17941
  self,
17831
- payload: dict,
17942
+ payload: dict = {},
17832
17943
  /,
17833
17944
  ac: str = "",
17834
17945
  *,
@@ -17836,9 +17947,9 @@ class P115Client(P115OpenClient):
17836
17947
  **request_kwargs,
17837
17948
  ) -> Coroutine[Any, Any, dict]:
17838
17949
  ...
17839
- def _offline_lixianssp_post(
17950
+ def _offline_lixianssp_request(
17840
17951
  self,
17841
- payload: dict,
17952
+ payload: dict = {},
17842
17953
  /,
17843
17954
  ac: str = "",
17844
17955
  *,
@@ -17846,6 +17957,7 @@ class P115Client(P115OpenClient):
17846
17957
  **request_kwargs,
17847
17958
  ) -> dict | Coroutine[Any, Any, dict]:
17848
17959
  api = "http://lixian.115.com/lixianssp/"
17960
+ request_kwargs["method"] = "POST"
17849
17961
  for k, v in payload.items():
17850
17962
  payload[k] = str(v)
17851
17963
  if ac:
@@ -17867,61 +17979,81 @@ class P115Client(P115OpenClient):
17867
17979
  request_kwargs.setdefault("parse", parse)
17868
17980
  return self.request(
17869
17981
  url=api,
17870
- method="POST",
17871
17982
  data={"data": rsa_encode(dumps(payload)).decode("ascii")},
17872
17983
  async_=async_,
17873
17984
  **request_kwargs,
17874
17985
  )
17875
17986
 
17876
17987
  @overload
17877
- def _offline_post(
17988
+ def _offline_request(
17878
17989
  self,
17879
- payload: dict,
17990
+ payload: dict = {},
17880
17991
  /,
17881
17992
  ac: str = "",
17882
- use_web_api: bool = False,
17993
+ method: str = "POST",
17994
+ type: Literal[None, "", "web", "ssp"] = None,
17995
+ base_url: None | bool | str | Callable[[], str] = None,
17883
17996
  *,
17884
17997
  async_: Literal[False] = False,
17885
17998
  **request_kwargs,
17886
17999
  ) -> dict:
17887
18000
  ...
17888
18001
  @overload
17889
- def _offline_post(
18002
+ def _offline_request(
17890
18003
  self,
17891
- payload: dict,
18004
+ payload: dict = {},
17892
18005
  /,
17893
18006
  ac: str = "",
17894
- use_web_api: bool = False,
18007
+ method: str = "POST",
18008
+ type: Literal[None, "", "web", "ssp"] = None,
18009
+ base_url: None | bool | str | Callable[[], str] = None,
17895
18010
  *,
17896
18011
  async_: Literal[True],
17897
18012
  **request_kwargs,
17898
18013
  ) -> Coroutine[Any, Any, dict]:
17899
18014
  ...
17900
- def _offline_post(
18015
+ def _offline_request(
17901
18016
  self,
17902
- payload: dict,
18017
+ payload: dict = {},
17903
18018
  /,
17904
18019
  ac: str = "",
17905
- use_web_api: bool = False,
18020
+ method: str = "POST",
18021
+ type: Literal[None, "", "web", "ssp"] = None,
18022
+ base_url: None | bool | str | Callable[[], str] = None,
17906
18023
  *,
17907
18024
  async_: Literal[False, True] = False,
17908
- ecdh_encrypt: bool = False,
17909
18025
  **request_kwargs,
17910
18026
  ) -> dict | Coroutine[Any, Any, dict]:
17911
- if use_web_api:
17912
- method = self._offline_web_post
17913
- elif ecdh_encrypt:
17914
- method = self._offline_lixian_post
17915
- else:
17916
- method = self._offline_lixianssp_post
17917
- return method(payload, ac, async_=async_, ecdh_encrypt=ecdh_encrypt, **request_kwargs)
18027
+ if type is None:
18028
+ api = complete_lixian_api("?ct=lixian&ac="+ac, base_url=base_url)
18029
+ if method.upper() == "POST":
18030
+ request_kwargs["data"] = payload
18031
+ else:
18032
+ request_kwargs["params"] = payload
18033
+ return self.request(url=api, method=method, async_=async_, **request_kwargs)
18034
+ match type:
18035
+ case "web":
18036
+ call: Callable = self._offline_web_request
18037
+ case "ssp":
18038
+ call = self._offline_lixianssp_request
18039
+ case _:
18040
+ call = self._offline_lixian_request
18041
+ return call(
18042
+ payload,
18043
+ ac,
18044
+ method=method,
18045
+ async_=async_,
18046
+ **request_kwargs,
18047
+ )
17918
18048
 
17919
- @overload # type: ignore
18049
+ @overload
17920
18050
  def offline_add_torrent(
17921
18051
  self,
17922
18052
  payload: str | dict,
17923
18053
  /,
17924
- use_web_api: bool = False,
18054
+ base_url: None | bool | str | Callable[[], str] = None,
18055
+ method: str = "POST",
18056
+ type: Literal[None, "", "web", "ssp"] = "ssp",
17925
18057
  *,
17926
18058
  async_: Literal[False] = False,
17927
18059
  **request_kwargs,
@@ -17932,7 +18064,9 @@ class P115Client(P115OpenClient):
17932
18064
  self,
17933
18065
  payload: str | dict,
17934
18066
  /,
17935
- use_web_api: bool = False,
18067
+ base_url: None | bool | str | Callable[[], str] = None,
18068
+ method: str = "POST",
18069
+ type: Literal[None, "", "web", "ssp"] = "ssp",
17936
18070
  *,
17937
18071
  async_: Literal[True],
17938
18072
  **request_kwargs,
@@ -17942,7 +18076,9 @@ class P115Client(P115OpenClient):
17942
18076
  self,
17943
18077
  payload: str | dict,
17944
18078
  /,
17945
- use_web_api: bool = False,
18079
+ base_url: None | bool | str | Callable[[], str] = None,
18080
+ method: str = "POST",
18081
+ type: Literal[None, "", "web", "ssp"] = "ssp",
17946
18082
  *,
17947
18083
  async_: Literal[False, True] = False,
17948
18084
  **request_kwargs,
@@ -17964,14 +18100,24 @@ class P115Client(P115OpenClient):
17964
18100
  """
17965
18101
  if isinstance(payload, str):
17966
18102
  payload = {"info_hash": payload}
17967
- return self._offline_post(payload, "add_task_bt", use_web_api=use_web_api, async_=async_, **request_kwargs)
18103
+ return self._offline_request(
18104
+ payload,
18105
+ "add_task_bt",
18106
+ method=method,
18107
+ type=type,
18108
+ base_url=base_url,
18109
+ async_=async_,
18110
+ **request_kwargs,
18111
+ )
17968
18112
 
17969
18113
  @overload
17970
18114
  def offline_add_url(
17971
18115
  self,
17972
18116
  payload: str | dict,
17973
18117
  /,
17974
- use_web_api: bool = False,
18118
+ base_url: None | bool | str | Callable[[], str] = None,
18119
+ method: str = "POST",
18120
+ type: Literal[None, "", "web", "ssp"] = "ssp",
17975
18121
  *,
17976
18122
  async_: Literal[False] = False,
17977
18123
  **request_kwargs,
@@ -17982,7 +18128,9 @@ class P115Client(P115OpenClient):
17982
18128
  self,
17983
18129
  payload: str | dict,
17984
18130
  /,
17985
- use_web_api: bool = False,
18131
+ base_url: None | bool | str | Callable[[], str] = None,
18132
+ method: str = "POST",
18133
+ type: Literal[None, "", "web", "ssp"] = "ssp",
17986
18134
  *,
17987
18135
  async_: Literal[True],
17988
18136
  **request_kwargs,
@@ -17992,7 +18140,9 @@ class P115Client(P115OpenClient):
17992
18140
  self,
17993
18141
  payload: str | dict,
17994
18142
  /,
17995
- use_web_api: bool = False,
18143
+ base_url: None | bool | str | Callable[[], str] = None,
18144
+ method: str = "POST",
18145
+ type: Literal[None, "", "web", "ssp"] = "ssp",
17996
18146
  *,
17997
18147
  async_: Literal[False, True] = False,
17998
18148
  **request_kwargs,
@@ -18008,14 +18158,24 @@ class P115Client(P115OpenClient):
18008
18158
  """
18009
18159
  if isinstance(payload, str):
18010
18160
  payload = {"url": payload}
18011
- return self._offline_post(payload, "add_task_url", use_web_api=use_web_api, async_=async_, **request_kwargs)
18161
+ return self._offline_request(
18162
+ payload,
18163
+ "add_task_url",
18164
+ method=method,
18165
+ type=type,
18166
+ base_url=base_url,
18167
+ async_=async_,
18168
+ **request_kwargs,
18169
+ )
18012
18170
 
18013
- @overload # type: ignore
18171
+ @overload
18014
18172
  def offline_add_urls(
18015
18173
  self,
18016
18174
  payload: str | Iterable[str] | dict,
18017
18175
  /,
18018
- use_web_api: bool = False,
18176
+ base_url: None | bool | str | Callable[[], str] = None,
18177
+ method: str = "POST",
18178
+ type: Literal[None, "", "web", "ssp"] = "ssp",
18019
18179
  *,
18020
18180
  async_: Literal[False] = False,
18021
18181
  **request_kwargs,
@@ -18026,7 +18186,9 @@ class P115Client(P115OpenClient):
18026
18186
  self,
18027
18187
  payload: str | Iterable[str] | dict,
18028
18188
  /,
18029
- use_web_api: bool = False,
18189
+ base_url: None | bool | str | Callable[[], str] = None,
18190
+ method: str = "POST",
18191
+ type: Literal[None, "", "web", "ssp"] = "ssp",
18030
18192
  *,
18031
18193
  async_: Literal[True],
18032
18194
  **request_kwargs,
@@ -18036,7 +18198,9 @@ class P115Client(P115OpenClient):
18036
18198
  self,
18037
18199
  payload: str | Iterable[str] | dict,
18038
18200
  /,
18039
- use_web_api: bool = False,
18201
+ base_url: None | bool | str | Callable[[], str] = None,
18202
+ method: str = "POST",
18203
+ type: Literal[None, "", "web", "ssp"] = "ssp",
18040
18204
  *,
18041
18205
  async_: Literal[False, True] = False,
18042
18206
  **request_kwargs,
@@ -18059,7 +18223,15 @@ class P115Client(P115OpenClient):
18059
18223
  payload = {f"url[{i}]": url for i, url in enumerate(payload) if url}
18060
18224
  if not payload:
18061
18225
  raise ValueError("no `url` specified")
18062
- return self._offline_post(payload, "add_task_urls", use_web_api=use_web_api, async_=async_, **request_kwargs)
18226
+ return self._offline_request(
18227
+ payload,
18228
+ "add_task_urls",
18229
+ method=method,
18230
+ type=type,
18231
+ base_url=base_url,
18232
+ async_=async_,
18233
+ **request_kwargs,
18234
+ )
18063
18235
 
18064
18236
  @overload
18065
18237
  def offline_clear(
@@ -18067,6 +18239,8 @@ class P115Client(P115OpenClient):
18067
18239
  payload: int | dict = 0,
18068
18240
  /,
18069
18241
  base_url: None | bool | str | Callable[[], str] = None,
18242
+ method: str = "POST",
18243
+ type: Literal[None, "", "web", "ssp"] = None,
18070
18244
  *,
18071
18245
  async_: Literal[False] = False,
18072
18246
  **request_kwargs,
@@ -18078,6 +18252,8 @@ class P115Client(P115OpenClient):
18078
18252
  payload: int | dict = 0,
18079
18253
  /,
18080
18254
  base_url: None | bool | str | Callable[[], str] = None,
18255
+ method: str = "POST",
18256
+ type: Literal[None, "", "web", "ssp"] = None,
18081
18257
  *,
18082
18258
  async_: Literal[True],
18083
18259
  **request_kwargs,
@@ -18088,13 +18264,15 @@ class P115Client(P115OpenClient):
18088
18264
  payload: int | dict = 0,
18089
18265
  /,
18090
18266
  base_url: None | bool | str | Callable[[], str] = None,
18267
+ method: str = "POST",
18268
+ type: Literal[None, "", "web", "ssp"] = None,
18091
18269
  *,
18092
18270
  async_: Literal[False, True] = False,
18093
18271
  **request_kwargs,
18094
18272
  ) -> dict | Coroutine[Any, Any, dict]:
18095
18273
  """清空离线任务列表
18096
18274
 
18097
- POST https://115.com/web/lixian/?ct=lixian&ac=task_clear
18275
+ POST https://lixian.115.com/lixian/?ac=task_clear
18098
18276
 
18099
18277
  :payload:
18100
18278
  - flag: int = 0 💡 标识,用于对应某种情况
@@ -18106,10 +18284,17 @@ class P115Client(P115OpenClient):
18106
18284
  - 4: 已完成+删除源文件
18107
18285
  - 5: 全部+删除源文件
18108
18286
  """
18109
- api = complete_lixian_api("?ct=lixian&ac=task_clear", base_url=base_url)
18110
18287
  if isinstance(payload, int):
18111
18288
  payload = {"flag": payload}
18112
- return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
18289
+ return self._offline_request(
18290
+ payload,
18291
+ "task_clear",
18292
+ method=method,
18293
+ type=type,
18294
+ base_url=base_url,
18295
+ async_=async_,
18296
+ **request_kwargs,
18297
+ )
18113
18298
 
18114
18299
  @overload
18115
18300
  def offline_download_path(
@@ -18146,6 +18331,49 @@ class P115Client(P115OpenClient):
18146
18331
  api = complete_webapi("/offine/downpath", base_url=base_url)
18147
18332
  return self.request(url=api, async_=async_, **request_kwargs)
18148
18333
 
18334
+ @overload
18335
+ def offline_download_path_set(
18336
+ self,
18337
+ payload: int | str | dict,
18338
+ /,
18339
+ base_url: bool | str | Callable[[], str] = False,
18340
+ *,
18341
+ async_: Literal[False] = False,
18342
+ **request_kwargs,
18343
+ ) -> dict:
18344
+ ...
18345
+ @overload
18346
+ def offline_download_path_set(
18347
+ self,
18348
+ payload: int | str | dict,
18349
+ /,
18350
+ base_url: bool | str | Callable[[], str] = False,
18351
+ *,
18352
+ async_: Literal[True],
18353
+ **request_kwargs,
18354
+ ) -> Coroutine[Any, Any, dict]:
18355
+ ...
18356
+ def offline_download_path_set(
18357
+ self,
18358
+ payload: int | str | dict,
18359
+ /,
18360
+ base_url: bool | str | Callable[[], str] = False,
18361
+ *,
18362
+ async_: Literal[False, True] = False,
18363
+ **request_kwargs,
18364
+ ) -> dict | Coroutine[Any, Any, dict]:
18365
+ """设置默认选择的离线下载到的目录信息
18366
+
18367
+ POST https://webapi.115.com/offine/downpath
18368
+
18369
+ :payload:
18370
+ - file_id: int | str 💡 目录 id
18371
+ """
18372
+ api = complete_webapi("/offine/downpath", base_url=base_url)
18373
+ if isinstance(payload, (int, str)):
18374
+ payload = {"file_id": payload}
18375
+ return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
18376
+
18149
18377
  @overload
18150
18378
  def offline_info(
18151
18379
  self,
@@ -18181,12 +18409,14 @@ class P115Client(P115OpenClient):
18181
18409
  api = complete_api("/?ct=offline&ac=space", base_url=base_url)
18182
18410
  return self.request(url=api, async_=async_, **request_kwargs)
18183
18411
 
18184
- @overload # type: ignore
18412
+ @overload
18185
18413
  def offline_list(
18186
18414
  self,
18187
18415
  payload: int | dict = 1,
18188
18416
  /,
18189
18417
  base_url: None | bool | str | Callable[[], str] = None,
18418
+ method: str = "GET",
18419
+ type: Literal[None, "", "web", "ssp"] = None,
18190
18420
  *,
18191
18421
  async_: Literal[False] = False,
18192
18422
  **request_kwargs,
@@ -18195,9 +18425,11 @@ class P115Client(P115OpenClient):
18195
18425
  @overload
18196
18426
  def offline_list(
18197
18427
  self,
18198
- payload: int | dict,
18428
+ payload: int | dict = 1,
18199
18429
  /,
18200
18430
  base_url: None | bool | str | Callable[[], str] = None,
18431
+ method: str = "GET",
18432
+ type: Literal[None, "", "web", "ssp"] = None,
18201
18433
  *,
18202
18434
  async_: Literal[True],
18203
18435
  **request_kwargs,
@@ -18208,27 +18440,38 @@ class P115Client(P115OpenClient):
18208
18440
  payload: int | dict = 1,
18209
18441
  /,
18210
18442
  base_url: None | bool | str | Callable[[], str] = None,
18443
+ method: str = "GET",
18444
+ type: Literal[None, "", "web", "ssp"] = None,
18211
18445
  *,
18212
18446
  async_: Literal[False, True] = False,
18213
18447
  **request_kwargs,
18214
18448
  ) -> dict | Coroutine[Any, Any, dict]:
18215
18449
  """获取当前的离线任务列表
18216
18450
 
18217
- POST https://lixian.115.com/lixian/?ct=lixian&ac=task_lists
18451
+ GET https://lixian.115.com/lixian/?ac=task_lists
18218
18452
 
18219
18453
  :payload:
18220
18454
  - page: int | str = 1
18221
18455
  """
18222
- api = complete_lixian_api("?ct=lixian&ac=task_lists", base_url=base_url)
18223
18456
  if isinstance(payload, int):
18224
18457
  payload = {"page": payload}
18225
- return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
18458
+ return self._offline_request(
18459
+ payload,
18460
+ "task_lists",
18461
+ method=method,
18462
+ type=type,
18463
+ base_url=base_url,
18464
+ async_=async_,
18465
+ **request_kwargs,
18466
+ )
18226
18467
 
18227
18468
  @overload
18228
18469
  def offline_quota_info(
18229
18470
  self,
18230
18471
  /,
18231
18472
  base_url: None | bool | str | Callable[[], str] = None,
18473
+ method: str = "GET",
18474
+ type: Literal[None, "", "web", "ssp"] = None,
18232
18475
  *,
18233
18476
  async_: Literal[False] = False,
18234
18477
  **request_kwargs,
@@ -18239,6 +18482,8 @@ class P115Client(P115OpenClient):
18239
18482
  self,
18240
18483
  /,
18241
18484
  base_url: None | bool | str | Callable[[], str] = None,
18485
+ method: str = "GET",
18486
+ type: Literal[None, "", "web", "ssp"] = None,
18242
18487
  *,
18243
18488
  async_: Literal[True],
18244
18489
  **request_kwargs,
@@ -18248,22 +18493,32 @@ class P115Client(P115OpenClient):
18248
18493
  self,
18249
18494
  /,
18250
18495
  base_url: None | bool | str | Callable[[], str] = None,
18496
+ method: str = "GET",
18497
+ type: Literal[None, "", "web", "ssp"] = None,
18251
18498
  *,
18252
18499
  async_: Literal[False, True] = False,
18253
18500
  **request_kwargs,
18254
18501
  ) -> dict | Coroutine[Any, Any, dict]:
18255
18502
  """获取当前离线配额信息(简略)
18256
18503
 
18257
- GET https://lixian.115.com/lixian/?ct=lixian&ac=get_quota_info
18504
+ GET https://lixian.115.com/lixian/?ac=get_quota_info
18258
18505
  """
18259
- api = complete_lixian_api("?ct=lixian&ac=get_quota_info", base_url=base_url)
18260
- return self.request(url=api, async_=async_, **request_kwargs)
18506
+ return self._offline_request(
18507
+ ac="get_quota_info",
18508
+ method=method,
18509
+ type=type,
18510
+ base_url=base_url,
18511
+ async_=async_,
18512
+ **request_kwargs,
18513
+ )
18261
18514
 
18262
18515
  @overload
18263
18516
  def offline_quota_package_array(
18264
18517
  self,
18265
18518
  /,
18266
18519
  base_url: None | bool | str | Callable[[], str] = None,
18520
+ method: str = "GET",
18521
+ type: Literal[None, "", "web", "ssp"] = None,
18267
18522
  *,
18268
18523
  async_: Literal[False] = False,
18269
18524
  **request_kwargs,
@@ -18274,6 +18529,8 @@ class P115Client(P115OpenClient):
18274
18529
  self,
18275
18530
  /,
18276
18531
  base_url: None | bool | str | Callable[[], str] = None,
18532
+ method: str = "GET",
18533
+ type: Literal[None, "", "web", "ssp"] = None,
18277
18534
  *,
18278
18535
  async_: Literal[True],
18279
18536
  **request_kwargs,
@@ -18283,22 +18540,32 @@ class P115Client(P115OpenClient):
18283
18540
  self,
18284
18541
  /,
18285
18542
  base_url: None | bool | str | Callable[[], str] = None,
18543
+ method: str = "GET",
18544
+ type: Literal[None, "", "web", "ssp"] = None,
18286
18545
  *,
18287
18546
  async_: Literal[False, True] = False,
18288
18547
  **request_kwargs,
18289
18548
  ) -> dict | Coroutine[Any, Any, dict]:
18290
18549
  """获取当前离线配额信息(详细)
18291
18550
 
18292
- GET https://lixian.115.com/lixian/?ct=lixian&ac=get_quota_package_array
18551
+ GET https://lixian.115.com/lixian/?ac=get_quota_package_array
18293
18552
  """
18294
- api = complete_lixian_api("?ct=lixian&ac=get_quota_package_array", base_url=base_url)
18295
- return self.request(url=api, async_=async_, **request_kwargs)
18553
+ return self._offline_request(
18554
+ ac="get_quota_package_array",
18555
+ method=method,
18556
+ type=type,
18557
+ base_url=base_url,
18558
+ async_=async_,
18559
+ **request_kwargs,
18560
+ )
18296
18561
 
18297
18562
  @overload
18298
18563
  def offline_quota_package_info(
18299
18564
  self,
18300
18565
  /,
18301
18566
  base_url: None | bool | str | Callable[[], str] = None,
18567
+ method: str = "GET",
18568
+ type: Literal[None, "", "web", "ssp"] = None,
18302
18569
  *,
18303
18570
  async_: Literal[False] = False,
18304
18571
  **request_kwargs,
@@ -18309,6 +18576,8 @@ class P115Client(P115OpenClient):
18309
18576
  self,
18310
18577
  /,
18311
18578
  base_url: None | bool | str | Callable[[], str] = None,
18579
+ method: str = "GET",
18580
+ type: Literal[None, "", "web", "ssp"] = None,
18312
18581
  *,
18313
18582
  async_: Literal[True],
18314
18583
  **request_kwargs,
@@ -18318,16 +18587,24 @@ class P115Client(P115OpenClient):
18318
18587
  self,
18319
18588
  /,
18320
18589
  base_url: None | bool | str | Callable[[], str] = None,
18590
+ method: str = "GET",
18591
+ type: Literal[None, "", "web", "ssp"] = None,
18321
18592
  *,
18322
18593
  async_: Literal[False, True] = False,
18323
18594
  **request_kwargs,
18324
18595
  ) -> dict | Coroutine[Any, Any, dict]:
18325
18596
  """获取当前离线配额信息(详细)
18326
18597
 
18327
- GET https://lixian.115.com/lixian/?ct=lixian&ac=get_quota_package_info
18598
+ GET https://lixian.115.com/lixian/?ac=get_quota_package_info
18328
18599
  """
18329
- api = complete_lixian_api("?ct=lixian&ac=get_quota_package_info", base_url=base_url)
18330
- return self.request(url=api, async_=async_, **request_kwargs)
18600
+ return self._offline_request(
18601
+ ac="get_quota_package_info",
18602
+ method=method,
18603
+ type=type,
18604
+ base_url=base_url,
18605
+ async_=async_,
18606
+ **request_kwargs,
18607
+ )
18331
18608
 
18332
18609
  @overload
18333
18610
  def offline_remove(
@@ -18335,6 +18612,8 @@ class P115Client(P115OpenClient):
18335
18612
  payload: str | Iterable[str] | dict,
18336
18613
  /,
18337
18614
  base_url: None | bool | str | Callable[[], str] = None,
18615
+ method: str = "POST",
18616
+ type: Literal[None, "", "web", "ssp"] = None,
18338
18617
  *,
18339
18618
  async_: Literal[False] = False,
18340
18619
  **request_kwargs,
@@ -18346,6 +18625,8 @@ class P115Client(P115OpenClient):
18346
18625
  payload: str | Iterable[str] | dict,
18347
18626
  /,
18348
18627
  base_url: None | bool | str | Callable[[], str] = None,
18628
+ method: str = "POST",
18629
+ type: Literal[None, "", "web", "ssp"] = None,
18349
18630
  *,
18350
18631
  async_: Literal[True],
18351
18632
  **request_kwargs,
@@ -18356,6 +18637,8 @@ class P115Client(P115OpenClient):
18356
18637
  payload: str | Iterable[str] | dict,
18357
18638
  /,
18358
18639
  base_url: None | bool | str | Callable[[], str] = None,
18640
+ method: str = "POST",
18641
+ type: Literal[None, "", "web", "ssp"] = None,
18359
18642
  *,
18360
18643
  async_: Literal[False, True] = False,
18361
18644
  **request_kwargs,
@@ -18370,14 +18653,21 @@ class P115Client(P115OpenClient):
18370
18653
  - ...
18371
18654
  - flag: 0 | 1 = <default> 💡 是否删除源文件
18372
18655
  """
18373
- api = complete_lixian_api("?ct=lixian&ac=task_del", base_url=base_url)
18374
18656
  if isinstance(payload, str):
18375
18657
  payload = {"hash[0]": payload}
18376
18658
  elif not isinstance(payload, dict):
18377
18659
  payload = {f"hash[{i}]": hash for i, hash in enumerate(payload)}
18378
18660
  if not payload:
18379
18661
  raise ValueError("no `hash` (info_hash) specified")
18380
- return self.request(api, method="POST", data=payload, async_=async_, **request_kwargs)
18662
+ return self._offline_request(
18663
+ payload,
18664
+ "task_del",
18665
+ method=method,
18666
+ type=type,
18667
+ base_url=base_url,
18668
+ async_=async_,
18669
+ **request_kwargs,
18670
+ )
18381
18671
 
18382
18672
  @overload
18383
18673
  def offline_restart(
@@ -18386,6 +18676,7 @@ class P115Client(P115OpenClient):
18386
18676
  /,
18387
18677
  base_url: None | bool | str | Callable[[], str] = None,
18388
18678
  method: str = "POST",
18679
+ type: Literal[None, "", "web", "ssp"] = None,
18389
18680
  *,
18390
18681
  async_: Literal[False] = False,
18391
18682
  **request_kwargs,
@@ -18398,6 +18689,7 @@ class P115Client(P115OpenClient):
18398
18689
  /,
18399
18690
  base_url: None | bool | str | Callable[[], str] = None,
18400
18691
  method: str = "POST",
18692
+ type: Literal[None, "", "web", "ssp"] = None,
18401
18693
  *,
18402
18694
  async_: Literal[True],
18403
18695
  **request_kwargs,
@@ -18409,6 +18701,7 @@ class P115Client(P115OpenClient):
18409
18701
  /,
18410
18702
  base_url: None | bool | str | Callable[[], str] = None,
18411
18703
  method: str = "POST",
18704
+ type: Literal[None, "", "web", "ssp"] = None,
18412
18705
  *,
18413
18706
  async_: Literal[False, True] = False,
18414
18707
  **request_kwargs,
@@ -18420,20 +18713,26 @@ class P115Client(P115OpenClient):
18420
18713
  :payload:
18421
18714
  - info_hash: str 💡 待重试任务的 info_hash
18422
18715
  """
18423
- api = complete_lixian_api("?ct=lixian&ac=restart", base_url=base_url)
18424
18716
  if isinstance(payload, str):
18425
18717
  payload = {"info_hash": payload}
18426
- if method.upper() == "POST":
18427
- request_kwargs["data"] = payload
18428
- else:
18429
- request_kwargs["params"] = payload
18430
- return self.request(api, method=method, async_=async_, **request_kwargs)
18718
+ return self._offline_request(
18719
+ payload,
18720
+ "restart",
18721
+ method=method,
18722
+ type=type,
18723
+ base_url=base_url,
18724
+ async_=async_,
18725
+ **request_kwargs,
18726
+ )
18431
18727
 
18432
18728
  @overload
18433
18729
  def offline_task_count(
18434
18730
  self,
18731
+ payload: dict | int = 0,
18435
18732
  /,
18436
18733
  base_url: None | bool | str | Callable[[], str] = None,
18734
+ method: str = "GET",
18735
+ type: Literal[None, "", "web", "ssp"] = None,
18437
18736
  *,
18438
18737
  async_: Literal[False] = False,
18439
18738
  **request_kwargs,
@@ -18442,8 +18741,11 @@ class P115Client(P115OpenClient):
18442
18741
  @overload
18443
18742
  def offline_task_count(
18444
18743
  self,
18744
+ payload: dict | int = 0,
18445
18745
  /,
18446
18746
  base_url: None | bool | str | Callable[[], str] = None,
18747
+ method: str = "GET",
18748
+ type: Literal[None, "", "web", "ssp"] = None,
18447
18749
  *,
18448
18750
  async_: Literal[True],
18449
18751
  **request_kwargs,
@@ -18451,18 +18753,33 @@ class P115Client(P115OpenClient):
18451
18753
  ...
18452
18754
  def offline_task_count(
18453
18755
  self,
18756
+ payload: dict | int = 0,
18454
18757
  /,
18455
18758
  base_url: None | bool | str | Callable[[], str] = None,
18759
+ method: str = "GET",
18760
+ type: Literal[None, "", "web", "ssp"] = None,
18456
18761
  *,
18457
18762
  async_: Literal[False, True] = False,
18458
18763
  **request_kwargs,
18459
18764
  ) -> dict | Coroutine[Any, Any, dict]:
18460
18765
  """获取当前正在运行的离线任务数
18461
18766
 
18462
- GET https://lixian.115.com/lixian/?ct=lixian&ac=get_task_cnt&flag=0
18767
+ GET https://lixian.115.com/lixian/?ac=get_task_cnt
18768
+
18769
+ :payload:
18770
+ flag: int = 0
18463
18771
  """
18464
- api = complete_lixian_api("?ct=lixian&ac=get_task_cnt&flag=0", base_url=base_url)
18465
- return self.request(url=api, async_=async_, **request_kwargs)
18772
+ if isinstance(payload, int):
18773
+ payload = {"flag": 0}
18774
+ return self._offline_request(
18775
+ payload,
18776
+ "get_task_cnt",
18777
+ method=method,
18778
+ type=type,
18779
+ base_url=base_url,
18780
+ async_=async_,
18781
+ **request_kwargs,
18782
+ )
18466
18783
 
18467
18784
  @overload
18468
18785
  def offline_torrent_info(
@@ -18470,6 +18787,8 @@ class P115Client(P115OpenClient):
18470
18787
  payload: str | dict,
18471
18788
  /,
18472
18789
  base_url: None | bool | str | Callable[[], str] = None,
18790
+ method: str = "GET",
18791
+ type: Literal[None, "", "web", "ssp"] = None,
18473
18792
  *,
18474
18793
  async_: Literal[False] = False,
18475
18794
  **request_kwargs,
@@ -18481,6 +18800,8 @@ class P115Client(P115OpenClient):
18481
18800
  payload: str | dict,
18482
18801
  /,
18483
18802
  base_url: None | bool | str | Callable[[], str] = None,
18803
+ method: str = "GET",
18804
+ type: Literal[None, "", "web", "ssp"] = None,
18484
18805
  *,
18485
18806
  async_: Literal[True],
18486
18807
  **request_kwargs,
@@ -18491,27 +18812,39 @@ class P115Client(P115OpenClient):
18491
18812
  payload: str | dict,
18492
18813
  /,
18493
18814
  base_url: None | bool | str | Callable[[], str] = None,
18815
+ method: str = "GET",
18816
+ type: Literal[None, "", "web", "ssp"] = None,
18494
18817
  *,
18495
18818
  async_: Literal[False, True] = False,
18496
18819
  **request_kwargs,
18497
18820
  ) -> dict | Coroutine[Any, Any, dict]:
18498
18821
  """查看种子的文件列表等信息
18499
18822
 
18500
- POST https://lixian.115.com/lixian/?ct=lixian&ac=torrent
18823
+ GET https://lixian.115.com/lixian/?ac=torrent
18501
18824
 
18502
18825
  :payload:
18503
18826
  - sha1: str
18504
18827
  """
18505
- api = complete_lixian_api("?ct=lixian&ac=torrent", base_url=base_url)
18506
18828
  if isinstance(payload, str):
18507
18829
  payload = {"sha1": payload}
18508
- return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
18830
+ return self._offline_request(
18831
+ payload,
18832
+ "torrent",
18833
+ method=method,
18834
+ type=type,
18835
+ base_url=base_url,
18836
+ async_=async_,
18837
+ **request_kwargs,
18838
+ )
18509
18839
 
18510
18840
  @overload
18511
18841
  def offline_upload_torrent_path(
18512
18842
  self,
18843
+ payload: dict | int = 1,
18513
18844
  /,
18514
- base_url: bool | str | Callable[[], str] = False,
18845
+ base_url: None | bool | str | Callable[[], str] = None,
18846
+ method: str = "GET",
18847
+ type: Literal[None, "", "web", "ssp"] = None,
18515
18848
  *,
18516
18849
  async_: Literal[False] = False,
18517
18850
  **request_kwargs,
@@ -18520,8 +18853,11 @@ class P115Client(P115OpenClient):
18520
18853
  @overload
18521
18854
  def offline_upload_torrent_path(
18522
18855
  self,
18856
+ payload: dict | int = 1,
18523
18857
  /,
18524
- base_url: bool | str | Callable[[], str] = False,
18858
+ base_url: None | bool | str | Callable[[], str] = None,
18859
+ method: str = "GET",
18860
+ type: Literal[None, "", "web", "ssp"] = None,
18525
18861
  *,
18526
18862
  async_: Literal[True],
18527
18863
  **request_kwargs,
@@ -18529,18 +18865,33 @@ class P115Client(P115OpenClient):
18529
18865
  ...
18530
18866
  def offline_upload_torrent_path(
18531
18867
  self,
18868
+ payload: dict | int = 1,
18532
18869
  /,
18533
- base_url: bool | str | Callable[[], str] = False,
18870
+ base_url: None | bool | str | Callable[[], str] = None,
18871
+ method: str = "GET",
18872
+ type: Literal[None, "", "web", "ssp"] = None,
18534
18873
  *,
18535
18874
  async_: Literal[False, True] = False,
18536
18875
  **request_kwargs,
18537
18876
  ) -> dict | Coroutine[Any, Any, dict]:
18538
18877
  """获取当前的种子上传到的目录,当你添加种子任务后,这个种子会在此目录中保存
18539
18878
 
18540
- GET https://115.com/?ct=lixian&ac=get_id&torrent=1
18879
+ GET https://lixian.115.com/lixian/?ac=get_id
18880
+
18881
+ :payload:
18882
+ - torrent: int = 1
18541
18883
  """
18542
- api = complete_api("/?ct=lixian&ac=get_id&torrent=1", base_url=base_url)
18543
- return self.request(url=api, async_=async_, **request_kwargs)
18884
+ if isinstance(payload, int):
18885
+ payload = {"torrent": payload}
18886
+ return self._offline_request(
18887
+ payload,
18888
+ "get_id",
18889
+ method=method,
18890
+ type=type,
18891
+ base_url=base_url,
18892
+ async_=async_,
18893
+ **request_kwargs,
18894
+ )
18544
18895
 
18545
18896
  ########## Recyclebin API ##########
18546
18897
 
@@ -22669,13 +23020,22 @@ class P115Client(P115OpenClient):
22669
23020
  return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
22670
23021
 
22671
23022
 
22672
- for name, method in P115Client.__dict__.items():
22673
- if not (callable(method) and method.__doc__):
22674
- continue
22675
- match = CRE_CLIENT_API_search(method.__doc__)
22676
- if match is not None:
22677
- CLIENT_API_MAP[match[1]] = "P115Client." + name
23023
+ with temp_globals():
23024
+ CRE_CLIENT_API_search: Final = re_compile(r"^ +((?:GET|POST|PUT|DELETE|PATCH) .*)", MULTILINE).search
23025
+ for name in dir(P115Client):
23026
+ method = getattr(P115Client, name)
23027
+ if not (callable(method) and method.__doc__):
23028
+ continue
23029
+ match = CRE_CLIENT_API_search(method.__doc__)
23030
+ if match is not None:
23031
+ api = match[1]
23032
+ name = "P115Client." + name
23033
+ CLIENT_METHOD_API_MAP[name] = api
23034
+ try:
23035
+ CLIENT_API_METHODS_MAP[api].append(name)
23036
+ except KeyError:
23037
+ CLIENT_API_METHODS_MAP[api] = [name]
23038
+
22678
23039
 
22679
23040
  # TODO: 提供一个可随时终止和暂停的上传功能,并且可以输出进度条和获取进度
22680
23041
  # TODO: 更新一下,p115client._upload,做更多的封装,至少让断点续传更易于使用
22681
-