p115client 0.0.5.9.3__py3-none-any.whl → 0.0.5.10__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 +159 -74
- p115client/const.py +183 -1
- p115client/exception.py +42 -18
- p115client/tool/__init__.py +2 -0
- p115client/tool/attr.py +104 -0
- p115client/tool/download.py +7 -22
- p115client/tool/edit.py +1 -2
- p115client/tool/fs_files.py +4 -13
- p115client/tool/iterdir.py +56 -101
- p115client/tool/life.py +1 -1
- p115client/tool/pool.py +6 -29
- p115client/tool/request.py +1 -0
- p115client/tool/util.py +107 -0
- p115client/tool/xys.py +317 -50
- p115client/type.py +16 -1
- {p115client-0.0.5.9.3.dist-info → p115client-0.0.5.10.dist-info}/METADATA +3 -3
- p115client-0.0.5.10.dist-info/RECORD +26 -0
- p115client-0.0.5.9.3.dist-info/RECORD +0 -24
- {p115client-0.0.5.9.3.dist-info → p115client-0.0.5.10.dist-info}/LICENSE +0 -0
- {p115client-0.0.5.9.3.dist-info → p115client-0.0.5.10.dist-info}/WHEEL +0 -0
p115client/tool/pool.py
CHANGED
@@ -18,12 +18,14 @@ from itertools import cycle, repeat
|
|
18
18
|
from math import inf, isinf
|
19
19
|
from threading import Lock
|
20
20
|
from time import time
|
21
|
-
from typing import cast, Any
|
22
21
|
|
23
22
|
from iterutils import run_gen_step
|
24
23
|
from p115client import check_response, P115Client
|
24
|
+
from p115client.const import AVAILABLE_APP_IDS
|
25
25
|
from p115client.exception import P115OSError, AuthenticationError, LoginError
|
26
26
|
|
27
|
+
from .util import get_status, is_timeouterror
|
28
|
+
|
27
29
|
|
28
30
|
@total_ordering
|
29
31
|
class ComparedWithID[T]:
|
@@ -51,35 +53,9 @@ class ComparedWithID[T]:
|
|
51
53
|
return f"{type(self).__qualname__}({self.value!r})"
|
52
54
|
|
53
55
|
|
54
|
-
def get_status(e: BaseException, /) -> None | int:
|
55
|
-
status = (
|
56
|
-
getattr(e, "status", None) or
|
57
|
-
getattr(e, "code", None) or
|
58
|
-
getattr(e, "status_code", None)
|
59
|
-
)
|
60
|
-
if status is None and hasattr(e, "response"):
|
61
|
-
response = e.response
|
62
|
-
status = (
|
63
|
-
getattr(response, "status", None) or
|
64
|
-
getattr(response, "code", None) or
|
65
|
-
getattr(response, "status_code", None)
|
66
|
-
)
|
67
|
-
return status
|
68
|
-
|
69
|
-
|
70
|
-
def is_timeouterror(exc: Exception) -> bool:
|
71
|
-
exctype = type(exc)
|
72
|
-
for exctype in exctype.mro():
|
73
|
-
if exctype is Exception:
|
74
|
-
break
|
75
|
-
if "Timeout" in exctype.__name__:
|
76
|
-
return True
|
77
|
-
return False
|
78
|
-
|
79
|
-
|
80
56
|
def generate_auth_factory(
|
81
57
|
client: str | P115Client,
|
82
|
-
app_ids: Iterable[int] =
|
58
|
+
app_ids: Iterable[int] = AVAILABLE_APP_IDS,
|
83
59
|
**request_kwargs,
|
84
60
|
) -> Callable:
|
85
61
|
"""利用一个已登录设备的 cookies,产生若干开放应用的 access_token
|
@@ -262,7 +238,7 @@ def make_pool[T](
|
|
262
238
|
|
263
239
|
def auth_pool(
|
264
240
|
client: str | P115Client,
|
265
|
-
app_ids: Iterable[int] =
|
241
|
+
app_ids: Iterable[int] = AVAILABLE_APP_IDS,
|
266
242
|
heap: None | list[tuple[float, dict | ComparedWithID[dict]]] = None,
|
267
243
|
cooldown_time: int | float = 1,
|
268
244
|
live_time: int | float = 7000,
|
@@ -404,6 +380,7 @@ def call_wrap_with_pool(get_cert_headers: Callable, /, func: Callable) -> Callab
|
|
404
380
|
return run_gen_step(gen_step, async_=async_)
|
405
381
|
return update_wrapper(wrapper, func)
|
406
382
|
|
383
|
+
|
407
384
|
# TODO: 需要完整的类型签名
|
408
385
|
# TODO: 池子可以被导出,下次继续使用
|
409
386
|
# TODO: 支持多个不同设备的 cookies 组成池,以及刷新(自己刷新自己,或者由另一个 cookies 辅助刷新)
|
p115client/tool/request.py
CHANGED
@@ -126,6 +126,7 @@ def make_request(
|
|
126
126
|
case _:
|
127
127
|
raise ValueError(f"can't make request for {module!r}")
|
128
128
|
|
129
|
+
|
129
130
|
# TODO: 基于 http.client 实现一个 request,并且支持连接池
|
130
131
|
# TODO: 基于 https://asks.readthedocs.io/en/latest/ 实现一个 request
|
131
132
|
# TODO: 基于 https://pypi.org/project/pycurl/ 实现一个 request
|
p115client/tool/util.py
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
5
|
+
__all__ = [
|
6
|
+
"get_status", "is_timeouterror", "posix_escape_name", "reduce_image_url_layers",
|
7
|
+
"share_extract_payload", "unescape_115_charref",
|
8
|
+
]
|
9
|
+
__doc__ = "这个模块提供了一些工具函数"
|
10
|
+
|
11
|
+
from re import compile as re_compile
|
12
|
+
from typing import cast, Final, TypedDict
|
13
|
+
from urllib.parse import urlsplit
|
14
|
+
|
15
|
+
|
16
|
+
CRE_115_CHARREF_sub: Final = re_compile("\\[\x02([0-9]+)\\]").sub
|
17
|
+
CRE_SHARE_LINK_search1 = re_compile(r"(?:/s/|share\.115\.com/)(?P<share_code>[a-z0-9]+)\?password=(?:(?P<receive_code>[a-z0-9]{4}))?").search
|
18
|
+
CRE_SHARE_LINK_search2 = re_compile(r"(?P<share_code>[a-z0-9]+)(?:-(?P<receive_code>[a-z0-9]{4}))?").search
|
19
|
+
|
20
|
+
|
21
|
+
class SharePayload(TypedDict):
|
22
|
+
share_code: str
|
23
|
+
receive_code: None | str
|
24
|
+
|
25
|
+
|
26
|
+
def get_status(e: BaseException, /) -> None | int:
|
27
|
+
"""获取 HTTP 请求异常的状态码(如果有的话)
|
28
|
+
"""
|
29
|
+
status = (
|
30
|
+
getattr(e, "status", None) or
|
31
|
+
getattr(e, "code", None) or
|
32
|
+
getattr(e, "status_code", None)
|
33
|
+
)
|
34
|
+
if status is None and hasattr(e, "response"):
|
35
|
+
response = e.response
|
36
|
+
status = (
|
37
|
+
getattr(response, "status", None) or
|
38
|
+
getattr(response, "code", None) or
|
39
|
+
getattr(response, "status_code", None)
|
40
|
+
)
|
41
|
+
return status
|
42
|
+
|
43
|
+
|
44
|
+
def is_timeouterror(exc: BaseException) -> bool:
|
45
|
+
"""判断是不是超时异常
|
46
|
+
"""
|
47
|
+
exctype = type(exc)
|
48
|
+
if issubclass(exctype, TimeoutError):
|
49
|
+
return True
|
50
|
+
for exctype in exctype.mro():
|
51
|
+
if "Timeout" in exctype.__name__:
|
52
|
+
return True
|
53
|
+
return False
|
54
|
+
|
55
|
+
|
56
|
+
def posix_escape_name(name: str, /, repl: str = "|") -> str:
|
57
|
+
"""把文件名中的 "/" 转换为另一个字符(默认为 "|")
|
58
|
+
|
59
|
+
:param name: 文件名
|
60
|
+
:param repl: 替换为的目标字符
|
61
|
+
|
62
|
+
:return: 替换后的名字
|
63
|
+
"""
|
64
|
+
return name.replace("/", repl)
|
65
|
+
|
66
|
+
|
67
|
+
def reduce_image_url_layers(url: str, /, size: str | int = "") -> str:
|
68
|
+
"""从图片的缩略图链接中提取信息,以减少一次 302 访问
|
69
|
+
"""
|
70
|
+
if not url.startswith(("http://thumb.115.com/", "https://thumb.115.com/")):
|
71
|
+
return url
|
72
|
+
urlp = urlsplit(url)
|
73
|
+
sha1, _, size0 = urlp.path.rsplit("/")[-1].partition("_")
|
74
|
+
if size == "":
|
75
|
+
size = size0 or "0"
|
76
|
+
return f"https://imgjump.115.com/?sha1={sha1}&{urlp.query}&size={size}"
|
77
|
+
|
78
|
+
|
79
|
+
def share_extract_payload(link: str, /) -> SharePayload:
|
80
|
+
"""从链接中提取 share_code 和 receive_code
|
81
|
+
|
82
|
+
.. hint::
|
83
|
+
`link` 支持 3 种形式(圆括号中的字符表示可有可无):
|
84
|
+
|
85
|
+
1. http(s)://115.com/s/{share_code}?password={receive_code}(#) 或 http(s)://share.115.com/{share_code}?password={receive_code}(#)
|
86
|
+
2. (/){share_code}-{receive_code}(/)
|
87
|
+
3. {share_code}
|
88
|
+
"""
|
89
|
+
m = CRE_SHARE_LINK_search1(link)
|
90
|
+
if m is None:
|
91
|
+
m = CRE_SHARE_LINK_search2(link)
|
92
|
+
if m is None:
|
93
|
+
raise ValueError("not a valid 115 share link")
|
94
|
+
return cast(SharePayload, m.groupdict())
|
95
|
+
|
96
|
+
|
97
|
+
def unescape_115_charref(s: str, /) -> str:
|
98
|
+
"""对 115 的字符引用进行解码
|
99
|
+
|
100
|
+
:example:
|
101
|
+
|
102
|
+
.. code:: python
|
103
|
+
|
104
|
+
unescape_115_charref("[\x02128074]0号:优质资源") == "👊0号:优质资源"
|
105
|
+
"""
|
106
|
+
return CRE_115_CHARREF_sub(lambda a: chr(int(a[1])), s)
|
107
|
+
|
p115client/tool/xys.py
CHANGED
@@ -2,45 +2,156 @@
|
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
5
|
-
__all__ = [
|
5
|
+
__all__ = [
|
6
|
+
"wish_info", "wish_make", "wish_answer", "wish_adopt",
|
7
|
+
"wish_del", "wish_iter", "wish_aid_iter",
|
8
|
+
]
|
6
9
|
|
7
|
-
from collections.abc import Iterable
|
10
|
+
from collections.abc import AsyncIterator, Coroutine, Iterable, Iterator
|
11
|
+
from typing import overload, Any, Literal
|
8
12
|
|
13
|
+
from iterutils import run_gen_step, run_gen_step_iter, YieldFrom
|
9
14
|
from p115client import check_response, P115Client
|
15
|
+
from p115client.type import P115StrID
|
10
16
|
|
11
17
|
|
18
|
+
@overload
|
19
|
+
def wish_info(
|
20
|
+
client: str | P115Client,
|
21
|
+
wish_id: str,
|
22
|
+
*,
|
23
|
+
async_: Literal[False] = False,
|
24
|
+
**request_kwargs,
|
25
|
+
) -> dict:
|
26
|
+
...
|
27
|
+
@overload
|
28
|
+
def wish_info(
|
29
|
+
client: str | P115Client,
|
30
|
+
wish_id: str,
|
31
|
+
*,
|
32
|
+
async_: Literal[True],
|
33
|
+
**request_kwargs,
|
34
|
+
) -> Coroutine[Any, Any, dict]:
|
35
|
+
...
|
36
|
+
def wish_info(
|
37
|
+
client: str | P115Client,
|
38
|
+
wish_id: str,
|
39
|
+
*,
|
40
|
+
async_: Literal[False, True] = False,
|
41
|
+
**request_kwargs,
|
42
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
43
|
+
"""许愿树活动:许愿信息
|
44
|
+
|
45
|
+
:param client: 115 客户端或 cookies
|
46
|
+
:param wish_id: 许愿 id
|
47
|
+
:param async_: 是否异步
|
48
|
+
:param request_kwargs: 其它请求参数
|
49
|
+
|
50
|
+
:return: 许愿信息
|
51
|
+
"""
|
52
|
+
if isinstance(client, str):
|
53
|
+
client = P115Client(client)
|
54
|
+
def gen_step():
|
55
|
+
resp = yield client.act_xys_get_desire_info(
|
56
|
+
wish_id,
|
57
|
+
async_=async_,
|
58
|
+
**request_kwargs,
|
59
|
+
)
|
60
|
+
check_response(resp)
|
61
|
+
return resp["data"]
|
62
|
+
return run_gen_step(gen_step, async_=async_)
|
63
|
+
|
64
|
+
|
65
|
+
@overload
|
66
|
+
def wish_make(
|
67
|
+
client: str | P115Client,
|
68
|
+
content: str = "随便许个愿",
|
69
|
+
size: int = 5,
|
70
|
+
*,
|
71
|
+
async_: Literal[False] = False,
|
72
|
+
**request_kwargs,
|
73
|
+
) -> P115StrID:
|
74
|
+
...
|
75
|
+
@overload
|
76
|
+
def wish_make(
|
77
|
+
client: str | P115Client,
|
78
|
+
content: str = "随便许个愿",
|
79
|
+
size: int = 5,
|
80
|
+
*,
|
81
|
+
async_: Literal[True],
|
82
|
+
**request_kwargs,
|
83
|
+
) -> Coroutine[Any, Any, P115StrID]:
|
84
|
+
...
|
12
85
|
def wish_make(
|
13
86
|
client: str | P115Client,
|
14
87
|
content: str = "随便许个愿",
|
15
88
|
size: int = 5,
|
16
|
-
|
89
|
+
*,
|
90
|
+
async_: Literal[False, True] = False,
|
91
|
+
**request_kwargs,
|
92
|
+
) -> P115StrID | Coroutine[Any, Any, P115StrID]:
|
17
93
|
"""许愿树活动:创建许愿(许愿创建后需要等审核)
|
18
94
|
|
19
95
|
:param client: 115 客户端或 cookies
|
20
96
|
:param content: 许愿内容
|
21
97
|
:param size: 答谢空间大小,单位是 GB
|
98
|
+
:param async_: 是否异步
|
99
|
+
:param request_kwargs: 其它请求参数
|
22
100
|
|
23
101
|
:return: 许愿 id
|
24
102
|
"""
|
25
103
|
if isinstance(client, str):
|
26
104
|
client = P115Client(client)
|
27
|
-
|
28
|
-
|
29
|
-
|
105
|
+
def gen_step():
|
106
|
+
resp = yield client.act_xys_wish(
|
107
|
+
{"rewardSpace": size, "content": content},
|
108
|
+
async_=async_,
|
109
|
+
**request_kwargs,
|
110
|
+
)
|
111
|
+
check_response(resp)
|
112
|
+
return P115StrID(resp["data"]["xys_id"], resp["data"])
|
113
|
+
return run_gen_step(gen_step, async_=async_)
|
30
114
|
|
31
115
|
|
116
|
+
@overload
|
32
117
|
def wish_answer(
|
33
118
|
client: str | P115Client,
|
34
119
|
wish_id: str,
|
35
120
|
content: str = "帮你助个愿",
|
36
121
|
file_ids: int | str | Iterable[int | str] = "",
|
37
|
-
|
122
|
+
*,
|
123
|
+
async_: Literal[False] = False,
|
124
|
+
**request_kwargs,
|
125
|
+
) -> P115StrID:
|
126
|
+
...
|
127
|
+
@overload
|
128
|
+
def wish_answer(
|
129
|
+
client: str | P115Client,
|
130
|
+
wish_id: str,
|
131
|
+
content: str = "帮你助个愿",
|
132
|
+
file_ids: int | str | Iterable[int | str] = "",
|
133
|
+
*,
|
134
|
+
async_: Literal[True],
|
135
|
+
**request_kwargs,
|
136
|
+
) -> Coroutine[Any, Any, P115StrID]:
|
137
|
+
...
|
138
|
+
def wish_answer(
|
139
|
+
client: str | P115Client,
|
140
|
+
wish_id: str,
|
141
|
+
content: str = "帮你助个愿",
|
142
|
+
file_ids: int | str | Iterable[int | str] = "",
|
143
|
+
*,
|
144
|
+
async_: Literal[False, True] = False,
|
145
|
+
**request_kwargs,
|
146
|
+
) -> P115StrID | Coroutine[Any, Any, P115StrID]:
|
38
147
|
"""许愿树活动:创建助愿(助愿创建后需要等审核)
|
39
148
|
|
40
149
|
:param client: 115 客户端或 cookies
|
41
150
|
:param wish_id: 许愿 id
|
42
151
|
:param content: 助愿内容
|
43
152
|
:param file_ids: 文件在你的网盘的 id,多个用逗号 "," 隔开
|
153
|
+
:param async_: 是否异步
|
154
|
+
:param request_kwargs: 其它请求参数
|
44
155
|
|
45
156
|
:return: 助愿 id
|
46
157
|
"""
|
@@ -48,78 +159,234 @@ def wish_answer(
|
|
48
159
|
client = P115Client(client)
|
49
160
|
if not isinstance(file_ids, (int, str)):
|
50
161
|
file_ids = ",".join(map(str, file_ids))
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
162
|
+
def gen_step():
|
163
|
+
resp = yield client.act_xys_aid_desire(
|
164
|
+
{"id": wish_id, "content": content, "file_ids": file_ids},
|
165
|
+
async_=async_,
|
166
|
+
**request_kwargs,
|
167
|
+
)
|
168
|
+
check_response(resp)
|
169
|
+
return P115StrID(resp["data"]["aid_id"], resp["data"])
|
170
|
+
return run_gen_step(gen_step, async_=async_)
|
55
171
|
|
56
172
|
|
57
|
-
|
173
|
+
@overload
|
174
|
+
def wish_adopt(
|
58
175
|
client: str | P115Client,
|
59
|
-
|
60
|
-
|
61
|
-
|
176
|
+
wish_id: str,
|
177
|
+
aid_id: int | str,
|
178
|
+
to_cid: int = 0,
|
179
|
+
*,
|
180
|
+
async_: Literal[False] = False,
|
181
|
+
**request_kwargs,
|
182
|
+
) -> dict:
|
183
|
+
...
|
184
|
+
@overload
|
185
|
+
def wish_adopt(
|
186
|
+
client: str | P115Client,
|
187
|
+
wish_id: str,
|
188
|
+
aid_id: int | str,
|
189
|
+
to_cid: int = 0,
|
190
|
+
*,
|
191
|
+
async_: Literal[True],
|
192
|
+
**request_kwargs,
|
193
|
+
) -> Coroutine[Any, Any, dict]:
|
194
|
+
...
|
195
|
+
def wish_adopt(
|
196
|
+
client: str | P115Client,
|
197
|
+
wish_id: str,
|
198
|
+
aid_id: int | str,
|
199
|
+
to_cid: int = 0,
|
200
|
+
*,
|
201
|
+
async_: Literal[False, True] = False,
|
202
|
+
**request_kwargs,
|
203
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
204
|
+
"""许愿树活动:采纳助愿
|
62
205
|
|
63
206
|
:param client: 115 客户端或 cookies
|
64
|
-
:param
|
65
|
-
|
66
|
-
|
67
|
-
|
207
|
+
:param wish_id: 许愿 id
|
208
|
+
:param aid_id: 助愿 id
|
209
|
+
:param to_cid: 助愿的分享文件保存到你的网盘中目录的 id
|
210
|
+
:param async_: 是否异步
|
211
|
+
:param request_kwargs: 其它请求参数
|
68
212
|
|
69
|
-
:return:
|
213
|
+
:return: 接口的返回信息
|
70
214
|
"""
|
71
215
|
if isinstance(client, str):
|
72
216
|
client = P115Client(client)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
ls.extend(adds)
|
79
|
-
return ls
|
217
|
+
return check_response(client.act_xys_adopt(
|
218
|
+
{"did": wish_id, "aid": aid_id, "to_cid": to_cid},
|
219
|
+
async_=async_,
|
220
|
+
**request_kwargs,
|
221
|
+
))
|
80
222
|
|
81
223
|
|
82
|
-
|
224
|
+
@overload
|
225
|
+
def wish_del(
|
83
226
|
client: str | P115Client,
|
84
|
-
wish_id: str,
|
85
|
-
|
86
|
-
|
227
|
+
wish_id: str | Iterable[str],
|
228
|
+
*,
|
229
|
+
async_: Literal[False] = False,
|
230
|
+
**request_kwargs,
|
231
|
+
) -> dict:
|
232
|
+
...
|
233
|
+
@overload
|
234
|
+
def wish_del(
|
235
|
+
client: str | P115Client,
|
236
|
+
wish_id: str | Iterable[str],
|
237
|
+
*,
|
238
|
+
async_: Literal[True],
|
239
|
+
**request_kwargs,
|
240
|
+
) -> Coroutine[Any, Any, dict]:
|
241
|
+
...
|
242
|
+
def wish_del(
|
243
|
+
client: str | P115Client,
|
244
|
+
wish_id: str | Iterable[str],
|
245
|
+
*,
|
246
|
+
async_: Literal[False, True] = False,
|
247
|
+
**request_kwargs,
|
248
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
249
|
+
"""许愿树活动:许愿信息
|
87
250
|
|
88
251
|
:param client: 115 客户端或 cookies
|
89
252
|
:param wish_id: 许愿 id
|
253
|
+
:param async_: 是否异步
|
254
|
+
:param request_kwargs: 其它请求参数
|
90
255
|
|
91
|
-
:return:
|
256
|
+
:return: 接口的返回信息
|
92
257
|
"""
|
93
258
|
if isinstance(client, str):
|
94
259
|
client = P115Client(client)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
260
|
+
if not isinstance(wish_id, str):
|
261
|
+
wish_id = ",".join(wish_id)
|
262
|
+
return check_response(client.act_xys_wish_del(
|
263
|
+
wish_id,
|
264
|
+
async_=async_,
|
265
|
+
**request_kwargs,
|
266
|
+
))
|
102
267
|
|
103
268
|
|
104
|
-
|
269
|
+
@overload
|
270
|
+
def wish_iter(
|
271
|
+
client: str | P115Client,
|
272
|
+
type: int = 0,
|
273
|
+
page_size: int = 1_000,
|
274
|
+
*,
|
275
|
+
async_: Literal[False] = False,
|
276
|
+
**request_kwargs,
|
277
|
+
) -> Iterator[dict]:
|
278
|
+
...
|
279
|
+
@overload
|
280
|
+
def wish_iter(
|
281
|
+
client: str | P115Client,
|
282
|
+
type: int = 0,
|
283
|
+
page_size: int = 1_000,
|
284
|
+
*,
|
285
|
+
async_: Literal[True],
|
286
|
+
**request_kwargs,
|
287
|
+
) -> AsyncIterator[dict]:
|
288
|
+
...
|
289
|
+
def wish_iter(
|
290
|
+
client: str | P115Client,
|
291
|
+
type: int = 0,
|
292
|
+
page_size: int = 1_000,
|
293
|
+
*,
|
294
|
+
async_: Literal[False, True] = False,
|
295
|
+
**request_kwargs,
|
296
|
+
) -> Iterator[dict] | AsyncIterator[dict]:
|
297
|
+
"""许愿树活动:罗列我的许愿列表
|
298
|
+
|
299
|
+
:param client: 115 客户端或 cookies
|
300
|
+
:param type: 类型
|
301
|
+
|
302
|
+
- 0: 全部
|
303
|
+
- 1: 进行中
|
304
|
+
- 2: 已实现
|
305
|
+
|
306
|
+
:param page_size: 分页大小
|
307
|
+
:param async_: 是否异步
|
308
|
+
:param request_kwargs: 其它请求参数
|
309
|
+
|
310
|
+
:return: 迭代器,逐个返回许愿许愿信息
|
311
|
+
"""
|
312
|
+
if isinstance(client, str):
|
313
|
+
client = P115Client(client)
|
314
|
+
if page_size <= 0:
|
315
|
+
page_size = 1_000
|
316
|
+
def gen_step():
|
317
|
+
payload: dict = {"type": type, "limit": page_size, "page": 1}
|
318
|
+
while True:
|
319
|
+
resp = yield client.act_xys_my_desire(
|
320
|
+
payload,
|
321
|
+
async_=async_,
|
322
|
+
**request_kwargs,
|
323
|
+
)
|
324
|
+
check_response(resp)
|
325
|
+
ls = resp["data"]["list"]
|
326
|
+
yield YieldFrom(ls, identity=True)
|
327
|
+
if not ls:
|
328
|
+
break
|
329
|
+
payload["page"] += 1
|
330
|
+
return run_gen_step_iter(gen_step, async_=async_)
|
331
|
+
|
332
|
+
|
333
|
+
@overload
|
334
|
+
def wish_aid_iter(
|
105
335
|
client: str | P115Client,
|
106
336
|
wish_id: str,
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
337
|
+
page_size: int = 1_000,
|
338
|
+
*,
|
339
|
+
async_: Literal[False] = False,
|
340
|
+
**request_kwargs,
|
341
|
+
) -> Iterator[dict]:
|
342
|
+
...
|
343
|
+
@overload
|
344
|
+
def wish_aid_iter(
|
345
|
+
client: str | P115Client,
|
346
|
+
wish_id: str,
|
347
|
+
page_size: int = 1_000,
|
348
|
+
*,
|
349
|
+
async_: Literal[True],
|
350
|
+
**request_kwargs,
|
351
|
+
) -> AsyncIterator[dict]:
|
352
|
+
...
|
353
|
+
def wish_aid_iter(
|
354
|
+
client: str | P115Client,
|
355
|
+
wish_id: str,
|
356
|
+
page_size: int = 1_000,
|
357
|
+
*,
|
358
|
+
async_: Literal[False, True] = False,
|
359
|
+
**request_kwargs,
|
360
|
+
) -> Iterator[dict] | AsyncIterator[dict]:
|
361
|
+
"""许愿树活动:许愿的助愿列表
|
111
362
|
|
112
363
|
:param client: 115 客户端或 cookies
|
113
364
|
:param wish_id: 许愿 id
|
114
|
-
:param
|
115
|
-
:param
|
365
|
+
:param page_size: 分页大小
|
366
|
+
:param async_: 是否异步
|
367
|
+
:param request_kwargs: 其它请求参数
|
116
368
|
|
117
|
-
:return:
|
369
|
+
:return: 迭代器,逐个返回助愿信息
|
118
370
|
"""
|
119
371
|
if isinstance(client, str):
|
120
372
|
client = P115Client(client)
|
121
|
-
|
373
|
+
if page_size <= 0:
|
374
|
+
page_size = 1_000
|
375
|
+
def gen_step():
|
376
|
+
payload: dict = {"id": wish_id, "limit": page_size, "page": 1}
|
377
|
+
while True:
|
378
|
+
resp = yield client.act_xys_desire_aid_list(
|
379
|
+
payload,
|
380
|
+
async_=async_,
|
381
|
+
**request_kwargs,
|
382
|
+
)
|
383
|
+
check_response(resp)
|
384
|
+
ls = resp["data"]["list"]
|
385
|
+
yield YieldFrom(ls, identity=True)
|
386
|
+
if not ls:
|
387
|
+
break
|
388
|
+
payload["page"] += 1
|
389
|
+
return run_gen_step_iter(gen_step, async_=async_)
|
122
390
|
|
123
|
-
# TODO: 再实现一个漂流瓶
|
124
|
-
# TODO: 支持异步
|
125
391
|
|
392
|
+
# TODO: 再实现一个漂流瓶
|
p115client/type.py
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
5
|
-
__all__ = [
|
5
|
+
__all__ = [
|
6
|
+
"MultipartResumeData", "P115Cookies", "P115DictAttrLikeMixin", "P115DictAttrLike",
|
7
|
+
"P115ID", "P115StrID", "P115URL",
|
8
|
+
]
|
6
9
|
|
7
10
|
from collections.abc import Callable
|
8
11
|
from functools import cached_property
|
@@ -199,6 +202,18 @@ class P115DictAttrLike(P115DictAttrLikeMixin):
|
|
199
202
|
return type(name, (base, cls), ns)
|
200
203
|
|
201
204
|
|
205
|
+
class P115ID(P115DictAttrLike, int):
|
206
|
+
"""整数 id 的封装
|
207
|
+
"""
|
208
|
+
def __str__(self, /) -> str:
|
209
|
+
return int.__repr__(self)
|
210
|
+
|
211
|
+
|
212
|
+
class P115StrID(P115DictAttrLike, str):
|
213
|
+
"""字符串 id 的封装
|
214
|
+
"""
|
215
|
+
|
216
|
+
|
202
217
|
class P115URL(P115DictAttrLike, str):
|
203
218
|
"""下载链接的封装
|
204
219
|
"""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: p115client
|
3
|
-
Version: 0.0.5.
|
3
|
+
Version: 0.0.5.10
|
4
4
|
Summary: Python 115 webdisk client.
|
5
5
|
Home-page: https://github.com/ChenyangGao/p115client
|
6
6
|
License: MIT
|
@@ -108,7 +108,7 @@ client = P115Client(Path("~/115-cookies.txt").expanduser(), check_for_relogin=Tr
|
|
108
108
|
|
109
109
|
如果你有一个申请通过的开放接口的应用,则可以创建开放接口的客户端实例
|
110
110
|
|
111
|
-
你可以直接从一个 `P115Client`
|
111
|
+
你可以直接从一个 `P115Client` 实例拿到授权(自动扫码登录并授权),如果不提供 `app_id`,则使用默认值
|
112
112
|
|
113
113
|
```python
|
114
114
|
app_id = <开放接口应用的 AppID>
|
@@ -143,7 +143,7 @@ from p115client import P115Client, P115OpenClient
|
|
143
143
|
from pathlib import Path
|
144
144
|
|
145
145
|
client = P115Client(Path("~/115-cookies.txt").expanduser(), check_for_relogin=True)
|
146
|
-
client_open = client.login_another_open(
|
146
|
+
client_open = client.login_another_open()
|
147
147
|
```
|
148
148
|
|
149
149
|
### 2. 接口调用
|