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/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] = range(100195123, 100196659, 2),
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] = range(100195123, 100196659, 2),
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 辅助刷新)
@@ -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
@@ -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__ = ["wish_make", "wish_answer", "wish_list", "wish_aid_list", "wish_adopt"]
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
- ) -> str:
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
- return check_response(client.act_xys_wish(
28
- {"rewardSpace": size, "content": content}
29
- ))["data"]["xys_id"]
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
- ) -> str:
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
- check_response(client.act_xys_get_desire_info(wish_id))
52
- return check_response(
53
- client.act_xys_aid_desire({"id": wish_id, "content": content, "file_ids": file_ids}
54
- ))["data"]["aid_id"]
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
- def wish_list(
173
+ @overload
174
+ def wish_adopt(
58
175
  client: str | P115Client,
59
- type: int = 0,
60
- ) -> list[dict]:
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 type: 类型
65
- - 0: 全部
66
- - 1: 进行中
67
- - 2: 已实现
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
- payload: dict = {"type": type, "limit": 1000, "page": 1}
74
- ls = adds = check_response(client.act_xys_my_desire(payload))["data"]["list"]
75
- while len(adds) == 1000:
76
- payload["page"] += 1
77
- adds = check_response(client.act_xys_my_desire(payload))["data"]["list"]
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
- def wish_aid_list(
224
+ @overload
225
+ def wish_del(
83
226
  client: str | P115Client,
84
- wish_id: str,
85
- ) -> list[dict]:
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
- payload: dict = {"id": wish_id, "limit": 1000, "page": 1}
96
- ls = adds = check_response(client.act_xys_desire_aid_list(payload))["data"]["list"]
97
- while len(adds) == 1000:
98
- payload["page"] += 1
99
- adds = check_response(client.act_xys_desire_aid_list(payload))["data"]["list"]
100
- ls.extend(adds)
101
- return ls
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
- def wish_adopt(
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
- aid_id: int | str,
108
- to_cid: int = 0,
109
- ) -> dict:
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 aid_id: 助愿 id
115
- :param to_cid: 助愿的分享文件保存到你的网盘中目录的 id
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
- return check_response(client.act_xys_adopt({"did": wish_id, "aid": aid_id, "to_cid": to_cid}))
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__ = ["MultipartResumeData", "P115Cookies", "P115DictAttrLikeMixin", "P115DictAttrLike", "P115URL"]
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.9.3
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(app_id)
146
+ client_open = client.login_another_open()
147
147
  ```
148
148
 
149
149
  ### 2. 接口调用