p115client 0.0.5.11.10.1__py3-none-any.whl → 0.0.5.11.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
p115client/client.py CHANGED
@@ -377,6 +377,9 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
377
377
  # {"state": false, "errno": 911, "error": "请验证账号"}
378
378
  case 911:
379
379
  raise AuthenticationError(errno.EAUTH, resp)
380
+ # {"state": false, "errno": 10004, "error": "错误的链接"}
381
+ case 10004:
382
+ raise OperationalError(errno.EINVAL, resp)
380
383
  # {"state": false, "errno": 20001, "error": "目录名称不能为空"}
381
384
  case 20001:
382
385
  raise OperationalError(errno.EINVAL, resp)
@@ -3180,8 +3183,8 @@ class P115OpenClient(ClientRequestMixin):
3180
3183
  - `c`: 允许同时打开次数,如果为 0,则是无限次数
3181
3184
  - `f`: 请求时要求携带请求头
3182
3185
  - 如果为空,则无要求
3183
- - 如果为 1,则需要 User-Agent(和请求直链时的一致)
3184
- - 如果为 3,则需要 User-Agent(和请求直链时的一致) 和 Cookie(由请求直链时的响应所返回的 Set-Cookie 响应头)
3186
+ - 如果为 1,则需要 user-agent(和请求直链时的一致)
3187
+ - 如果为 3,则需要 user-agent(和请求直链时的一致) 和 Cookie(由请求直链时的响应所返回的 Set-Cookie 响应头)
3185
3188
 
3186
3189
  :param pickcode: 提取码
3187
3190
  :param strict: 如果为 True,当目标是目录时,会抛出 IsADirectoryError 异常
@@ -7857,8 +7860,8 @@ class P115Client(P115OpenClient):
7857
7860
  - `c`: 允许同时打开次数,如果为 0,则是无限次数
7858
7861
  - `f`: 请求时要求携带请求头
7859
7862
  - 如果为空,则无要求
7860
- - 如果为 1,则需要 User-Agent(和请求直链时的一致)
7861
- - 如果为 3,则需要 User-Agent(和请求直链时的一致) 和 Cookie(由请求直链时的响应所返回的 Set-Cookie 响应头)
7863
+ - 如果为 1,则需要 user-agent(和请求直链时的一致)
7864
+ - 如果为 3,则需要 user-agent(和请求直链时的一致) 和 Cookie(由请求直链时的响应所返回的 Set-Cookie 响应头)
7862
7865
 
7863
7866
  :param pickcode: 提取码
7864
7867
  :param strict: 如果为 True,当目标是目录时,会抛出 IsADirectoryError 异常
@@ -18043,6 +18046,7 @@ class P115Client(P115OpenClient):
18043
18046
  POST https://lixian.115.com/lixianssp/?ac=add_task_urls
18044
18047
 
18045
18048
  :payload:
18049
+ - url: str 💡 链接,支持HTTP、HTTPS、FTP、磁力链和电驴链接
18046
18050
  - url[0]: str 💡 链接,支持HTTP、HTTPS、FTP、磁力链和电驴链接
18047
18051
  - url[1]: str
18048
18052
  - ...
@@ -18052,7 +18056,7 @@ class P115Client(P115OpenClient):
18052
18056
  if isinstance(payload, str):
18053
18057
  payload = payload.strip("\n").split("\n")
18054
18058
  if not isinstance(payload, dict):
18055
- payload = {f"url[{i}]": url for i, url in enumerate(payload)}
18059
+ payload = {f"url[{i}]": url for i, url in enumerate(payload) if url}
18056
18060
  if not payload:
18057
18061
  raise ValueError("no `url` specified")
18058
18062
  return self._offline_post(payload, "add_task_urls", use_web_api=use_web_api, async_=async_, **request_kwargs)
@@ -21014,14 +21018,14 @@ class P115Client(P115OpenClient):
21014
21018
  "sign_key": sign_key,
21015
21019
  "sign_val": sign_val,
21016
21020
  "target": target,
21017
- "topupload": 1,
21021
+ "topupload": "true",
21018
21022
  "userid": self.user_id,
21019
21023
  "userkey": self.user_key,
21020
21024
  }
21021
21025
  request_kwargs.update(make_upload_payload(data))
21022
21026
  request_kwargs["headers"] = {
21023
21027
  **(request_kwargs.get("headers") or {}),
21024
- "Content-Type": "application/x-www-form-urlencoded",
21028
+ "content-type": "application/x-www-form-urlencoded",
21025
21029
  "user-agent": "Mozilla/5.0 115disk/99.99.99.99 115Browser/99.99.99.99 115wangpan_android/99.99.99.99",
21026
21030
  }
21027
21031
  request_kwargs.setdefault("parse", parse_upload_init_response)
@@ -12,6 +12,7 @@ from .fs_files import *
12
12
  from .history import *
13
13
  from .iterdir import *
14
14
  from .life import *
15
+ from .offline import *
15
16
  from .pool import *
16
17
  from .request import *
17
18
  from .upload import *
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env python3
2
+ # encoding: utf-8
3
+
4
+ __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
+ __all__ = ["offline_iter", "offline_restart_iter"]
6
+ __doc__ = "这个模块提供了一些和离线下载有关的函数"
7
+
8
+ from asyncio import sleep as async_sleep
9
+ from collections.abc import AsyncIterator, Callable, Iterable, Iterator
10
+ from itertools import count
11
+ from time import sleep, time
12
+ from typing import overload, Literal
13
+
14
+ from iterutils import run_gen_step_iter, with_iter_next, Yield, YieldFrom
15
+ from p115client import check_response, P115Client, P115OpenClient
16
+
17
+
18
+ @overload
19
+ def offline_iter(
20
+ client: str | P115Client | P115OpenClient,
21
+ /,
22
+ page_start: int = 1,
23
+ page_stop: int = -1,
24
+ cooldown: float = 0,
25
+ use_open_api: bool = False,
26
+ *,
27
+ async_: Literal[False] = False,
28
+ **request_kwargs,
29
+ ) -> Iterator[dict]:
30
+ ...
31
+ @overload
32
+ def offline_iter(
33
+ client: str | P115Client | P115OpenClient,
34
+ /,
35
+ page_start: int = 1,
36
+ page_stop: int = -1,
37
+ cooldown: float = 0,
38
+ use_open_api: bool = False,
39
+ *,
40
+ async_: Literal[True],
41
+ **request_kwargs,
42
+ ) -> AsyncIterator[dict]:
43
+ ...
44
+ def offline_iter(
45
+ client: str | P115Client | P115OpenClient,
46
+ /,
47
+ page_start: int = 1,
48
+ page_stop: int = -1,
49
+ cooldown: float = 0,
50
+ use_open_api: bool = False,
51
+ *,
52
+ async_: Literal[False, True] = False,
53
+ **request_kwargs,
54
+ ) -> Iterator[dict] | AsyncIterator[dict]:
55
+ """遍历任务列表,获取任务信息
56
+
57
+ :param client: 115 客户端或 cookies
58
+ :param page_start: 开始页数
59
+ :param page_stop: 结束页数(不含),如果 <= 0,则不限
60
+ :param cooldown: 接口调用冷却时间,单位:秒
61
+ :param use_open_api: 是否使用 open api
62
+ :param async_: 是否异步
63
+ :param request_kwargs: 其它请求参数
64
+
65
+ :return: 迭代器,返回任务信息
66
+ """
67
+ if isinstance(client, str):
68
+ client = P115Client(client, check_for_relogin=True)
69
+ if page_start < 1:
70
+ page_start = 1
71
+ if page_stop > 0:
72
+ pages: Iterable[int] = range(page_start, page_stop)
73
+ else:
74
+ pages = count(page_start)
75
+ if not isinstance(client, P115Client):
76
+ use_open_api = True
77
+ def gen_step():
78
+ if use_open_api:
79
+ offline_list = client.offline_list_open
80
+ else:
81
+ offline_list = client.offline_list
82
+ if cooldown > 0:
83
+ do_sleep = async_sleep if async_ else sleep
84
+ last_t: float = 0
85
+ for page in pages:
86
+ if last_t and (diff := last_t + cooldown - time()) > 0:
87
+ yield do_sleep(diff)
88
+ last_t = time()
89
+ resp = yield offline_list(page, async_=async_, **request_kwargs)
90
+ check_response(resp)
91
+ if use_open_api:
92
+ resp = resp["data"]
93
+ tasks = resp["tasks"]
94
+ if not tasks:
95
+ break
96
+ yield YieldFrom(resp["tasks"])
97
+ if len(tasks) < 30 or page >= resp["page_count"]:
98
+ break
99
+ return run_gen_step_iter(gen_step, async_=async_)
100
+
101
+
102
+ @overload
103
+ def offline_restart_iter(
104
+ client: str | P115Client,
105
+ /,
106
+ predicate: None | Callable[[dict], bool] = None,
107
+ *,
108
+ async_: Literal[False] = False,
109
+ **request_kwargs,
110
+ ) -> Iterator[dict]:
111
+ ...
112
+ @overload
113
+ def offline_restart_iter(
114
+ client: str | P115Client,
115
+ /,
116
+ predicate: None | Callable[[dict], bool] = None,
117
+ *,
118
+ async_: Literal[True],
119
+ **request_kwargs,
120
+ ) -> AsyncIterator[dict]:
121
+ ...
122
+ def offline_restart_iter(
123
+ client: str | P115Client,
124
+ /,
125
+ predicate: None | Callable[[dict], bool] = None,
126
+ *,
127
+ async_: Literal[False, True] = False,
128
+ **request_kwargs,
129
+ ) -> Iterator[dict] | AsyncIterator[dict]:
130
+ """重试任务:重试那些因为空间不足而转存失败的任务
131
+
132
+ :param client: 115 客户端或 cookies
133
+ :param predicate: 断言,用于筛选
134
+ :param async_: 是否异步
135
+ :param request_kwargs: 其它请求参数
136
+
137
+ :return: 迭代器,逐个任务返回执行重试后的响应
138
+ """
139
+ if isinstance(client, str):
140
+ client = P115Client(client, check_for_relogin=True)
141
+ def gen_step():
142
+ left_no_space: list[dict] = []
143
+ add_task = left_no_space.append
144
+ with with_iter_next(offline_iter(
145
+ client,
146
+ async_=async_,
147
+ **request_kwargs,
148
+ )) as do_next:
149
+ while True:
150
+ task = yield do_next()
151
+ if task["move"] == -1:
152
+ add_task(task)
153
+ elif task["status"] == 2:
154
+ break
155
+ for task in filter(predicate, left_no_space):
156
+ resp = yield client.offline_restart(
157
+ task["info_hash"],
158
+ async_=async_,
159
+ **request_kwargs,
160
+ )
161
+ resp["task"] = task
162
+ yield Yield(resp)
163
+ return run_gen_step_iter(gen_step, async_=async_)
164
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p115client
3
- Version: 0.0.5.11.10.1
3
+ Version: 0.0.5.11.11
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -1,11 +1,11 @@
1
1
  LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
2
  p115client/__init__.py,sha256=1mx7njuAlqcuEWONTjSiiGnXyyNyqOcJyNX1FMHqQ-4,214
3
3
  p115client/_upload.py,sha256=3uXwgFsXkZ4X5hjL1N2mx0y8tA8MjVxe49N0BoyYyno,31253
4
- p115client/client.py,sha256=RmP5hmMX-qmEKP1ZA6hXRZqa3iGmF1djRQGk1ZfPox8,783893
4
+ p115client/client.py,sha256=sXqO2jxXtP58r4xyoYzcfJ3eu4zTvMy7EbUBLca8Cp4,784167
5
5
  p115client/const.py,sha256=KqDGr9KsOnSkNVM3RIdQGptCMHbidMmZ_ffyFPiniww,7654
6
6
  p115client/exception.py,sha256=4SZ8ubOLMRxtcqc0u1kNzXqH1a6wwXJFwGnRDURoEgQ,3708
7
7
  p115client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- p115client/tool/__init__.py,sha256=TdGjEH7SD_6BaBdNg9Wd2Zd91KCycDOVN9JbH21z5SA,406
8
+ p115client/tool/__init__.py,sha256=IwwzbCQ7jpRoFGTQUCfGBx8zvjqjgSFs98yKpYyI46s,429
9
9
  p115client/tool/attr.py,sha256=RmNm5uar2PVv1Me7xOWyM0JtZr-JqoglIIpF0WHGues,2979
10
10
  p115client/tool/auth.py,sha256=jUkVaCACg_K38RzpHTMGvve1xvhAdBeyPGtlNIfA_9M,1679
11
11
  p115client/tool/download.py,sha256=CZJE5f1SHi26eCNTPcF5VjSoht8WTUYravEG219i4gk,61534
@@ -15,13 +15,14 @@ p115client/tool/fs_files.py,sha256=cRUa-GNjoOMoLtLJxG-Zp6C6QFoM1Au0B_Z19KhLzn8,1
15
15
  p115client/tool/history.py,sha256=qquCiiOIRpxOqmyXbmdwS_qpfPkduJilM6AGuOufrYU,7462
16
16
  p115client/tool/iterdir.py,sha256=dXBMPfxPzRcFhBpnBT3X1LYkhc3l31rYCLRKRFbggSk,200498
17
17
  p115client/tool/life.py,sha256=ceweN2uNKYxigSOaBQ4Abo5u05zqppRm_P7k-_rHjcA,17301
18
+ p115client/tool/offline.py,sha256=5I7ooTaxB3bGncfNtTnBNGDmErjCJae6Q9jkLAS34Is,4978
18
19
  p115client/tool/pool.py,sha256=H65VhoNxQC6xWSL1THq_PximWnBOqB4EfU6kWBTAnlA,13946
19
20
  p115client/tool/request.py,sha256=rjXuQwRganE5Z-4rfgnyPFjE4jzdQSLdIs9s0cIDshU,7043
20
21
  p115client/tool/upload.py,sha256=D2TPJlS--bGX-oHgTm6ktoqnX1_gwOMwxwMkiOwGuIY,32695
21
22
  p115client/tool/util.py,sha256=pAa8gc4BcnVTpNcXbNZU4tBUMjSB04DGOpzDdzfbto8,3934
22
23
  p115client/tool/xys.py,sha256=vU28Px2yeQzIxxGkopJIpvV6TdOnWJ5xB6NPXpTgM0Y,10306
23
24
  p115client/type.py,sha256=7kOp98uLaYqcTTCgCrb3DRcl8ukMpn7ibsnVvtw2nG8,6250
24
- p115client-0.0.5.11.10.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
25
- p115client-0.0.5.11.10.1.dist-info/METADATA,sha256=iykoz-kKA3NrhI_I-ePJ5cfDFnTJp0eqsiriFa-Tus0,8195
26
- p115client-0.0.5.11.10.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
27
- p115client-0.0.5.11.10.1.dist-info/RECORD,,
25
+ p115client-0.0.5.11.11.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
26
+ p115client-0.0.5.11.11.dist-info/METADATA,sha256=wOD1JB3jSbUZi0McSiXPL98BiBtZd019jevjlL0hdD8,8193
27
+ p115client-0.0.5.11.11.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
28
+ p115client-0.0.5.11.11.dist-info/RECORD,,