p115client 0.0.5.10.4__py3-none-any.whl → 0.0.5.10.6__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
@@ -1364,6 +1364,7 @@ class ClientRequestMixin:
1364
1364
  POST https://qrcodeapi.115.com/open/deviceCodeToToken
1365
1365
 
1366
1366
  .. admonition:: Reference
1367
+
1367
1368
  https://www.yuque.com/115yun/open/shtpzfhewv5nag11#QCCVQ
1368
1369
 
1369
1370
  :payload:
@@ -1415,6 +1416,7 @@ class ClientRequestMixin:
1415
1416
  POST https://qrcodeapi.115.com/open/refreshToken
1416
1417
 
1417
1418
  .. admonition:: Reference
1419
+
1418
1420
  https://www.yuque.com/115yun/open/shtpzfhewv5nag11#ve54x
1419
1421
 
1420
1422
  :payload:
@@ -1567,6 +1569,7 @@ class ClientRequestMixin:
1567
1569
  GET https://qrcodeapi.115.com/get/status/
1568
1570
 
1569
1571
  .. admonition:: Reference
1572
+
1570
1573
  https://www.yuque.com/115yun/open/shtpzfhewv5nag11#lAsp2
1571
1574
 
1572
1575
  :payload:
@@ -1653,6 +1656,7 @@ class ClientRequestMixin:
1653
1656
  POST https://qrcodeapi.115.com/open/authDeviceCode
1654
1657
 
1655
1658
  .. admonition:: Reference
1659
+
1656
1660
  https://www.yuque.com/115yun/open/shtpzfhewv5nag11#WzRhM
1657
1661
 
1658
1662
  .. note::
@@ -2464,6 +2468,7 @@ class P115OpenClient(ClientRequestMixin):
2464
2468
  """115 的客户端对象
2465
2469
 
2466
2470
  .. admonition:: Reference
2471
+
2467
2472
  https://www.yuque.com/115yun/open
2468
2473
 
2469
2474
  :param app_id_or_refresh_token: 申请到的 AppID 或 refresh_token
@@ -2747,6 +2752,7 @@ class P115OpenClient(ClientRequestMixin):
2747
2752
  相当于 `P115Client.download_url_app(app="chrome")`
2748
2753
 
2749
2754
  .. admonition:: Reference
2755
+
2750
2756
  https://www.yuque.com/115yun/open/um8whr91bxb5997o
2751
2757
 
2752
2758
  :payload:
@@ -2810,6 +2816,7 @@ class P115OpenClient(ClientRequestMixin):
2810
2816
  POST https://proapi.115.com/open/ufile/copy
2811
2817
 
2812
2818
  .. admonition:: Reference
2819
+
2813
2820
  https://www.yuque.com/115yun/open/lvas49ar94n47bbk
2814
2821
 
2815
2822
  :payload:
@@ -2866,6 +2873,7 @@ class P115OpenClient(ClientRequestMixin):
2866
2873
  POST https://proapi.115.com/open/ufile/delete
2867
2874
 
2868
2875
  .. admonition:: Reference
2876
+
2869
2877
  https://www.yuque.com/115yun/open/kt04fu8vcchd2fnb
2870
2878
 
2871
2879
  :payload:
@@ -2909,7 +2917,7 @@ class P115OpenClient(ClientRequestMixin):
2909
2917
  async_: Literal[False, True] = False,
2910
2918
  **request_kwargs,
2911
2919
  ) -> dict | Coroutine[Any, Any, dict]:
2912
- """更新文件或目录
2920
+ """获取目录中的文件列表和基本信息
2913
2921
 
2914
2922
  GET https://proapi.115.com/open/ufile/files
2915
2923
 
@@ -2917,6 +2925,7 @@ class P115OpenClient(ClientRequestMixin):
2917
2925
  相当于 `P115Client.fs_files_app`
2918
2926
 
2919
2927
  .. admonition:: Reference
2928
+
2920
2929
  https://www.yuque.com/115yun/open/kz9ft9a7s57ep868
2921
2930
 
2922
2931
  :payload:
@@ -3036,6 +3045,7 @@ class P115OpenClient(ClientRequestMixin):
3036
3045
  相当于 `P115Client.fs_category_get_app`
3037
3046
 
3038
3047
  .. admonition:: Reference
3048
+
3039
3049
  https://www.yuque.com/115yun/open/rl8zrhe2nag21dfw
3040
3050
 
3041
3051
  :payload:
@@ -3085,6 +3095,7 @@ class P115OpenClient(ClientRequestMixin):
3085
3095
  POST https://proapi.115.com/open/folder/add
3086
3096
 
3087
3097
  .. admonition:: Reference
3098
+
3088
3099
  https://www.yuque.com/115yun/open/qur839kyx9cgxpxi
3089
3100
 
3090
3101
  :payload:
@@ -3137,6 +3148,7 @@ class P115OpenClient(ClientRequestMixin):
3137
3148
  POST https://proapi.115.com/open/ufile/move
3138
3149
 
3139
3150
  .. admonition:: Reference
3151
+
3140
3152
  https://www.yuque.com/115yun/open/vc6fhi2mrkenmav2
3141
3153
 
3142
3154
  :payload:
@@ -3195,6 +3207,7 @@ class P115OpenClient(ClientRequestMixin):
3195
3207
  相当于 `P115Client.fs_search_app2`
3196
3208
 
3197
3209
  .. admonition:: Reference
3210
+
3198
3211
  https://www.yuque.com/115yun/open/ft2yelxzopusus38
3199
3212
 
3200
3213
  :payload:
@@ -3350,6 +3363,7 @@ class P115OpenClient(ClientRequestMixin):
3350
3363
  即使文件已经被删除,也可以操作成功
3351
3364
 
3352
3365
  .. admonition:: Reference
3366
+
3353
3367
  https://www.yuque.com/115yun/open/gyrpw5a0zc4sengm
3354
3368
 
3355
3369
  :payload:
@@ -3448,6 +3462,7 @@ class P115OpenClient(ClientRequestMixin):
3448
3462
  GET https://proapi.115.com/open/rb/list
3449
3463
 
3450
3464
  .. admonition:: Reference
3465
+
3451
3466
  https://www.yuque.com/115yun/open/bg7l4328t98fwgex
3452
3467
 
3453
3468
  :payload:
@@ -3497,6 +3512,7 @@ class P115OpenClient(ClientRequestMixin):
3497
3512
  POST https://proapi.115.com/open/rb/revert
3498
3513
 
3499
3514
  .. admonition:: Reference
3515
+
3500
3516
  https://www.yuque.com/115yun/open/gq293z80a3kmxbaq
3501
3517
 
3502
3518
  :payload:
@@ -3542,6 +3558,7 @@ class P115OpenClient(ClientRequestMixin):
3542
3558
  GET https://proapi.115.com/open/upload/get_token
3543
3559
 
3544
3560
  .. admonition:: Reference
3561
+
3545
3562
  https://www.yuque.com/115yun/open/kzacvzl0g7aiyyn4
3546
3563
  """
3547
3564
  api = complete_proapi("/open/upload/get_token", base_url)
@@ -3583,6 +3600,7 @@ class P115OpenClient(ClientRequestMixin):
3583
3600
  POST https://proapi.115.com/open/upload/init
3584
3601
 
3585
3602
  .. admonition:: Reference
3603
+
3586
3604
  https://www.yuque.com/115yun/open/ul4mrauo5i2uza0q
3587
3605
 
3588
3606
  :payload:
@@ -3641,6 +3659,7 @@ class P115OpenClient(ClientRequestMixin):
3641
3659
  POST https://proapi.115.com/open/upload/resume
3642
3660
 
3643
3661
  .. admonition:: Reference
3662
+
3644
3663
  https://www.yuque.com/115yun/open/tzvi9sbcg59msddz
3645
3664
 
3646
3665
  :payload:
@@ -4131,6 +4150,7 @@ class P115OpenClient(ClientRequestMixin):
4131
4150
  GET https://proapi.115.com/open/user/info
4132
4151
 
4133
4152
  .. admonition:: Reference
4153
+
4134
4154
  https://www.yuque.com/115yun/open/ot1litggzxa1czww
4135
4155
  """
4136
4156
  api = complete_proapi("/open/user/info", base_url)
@@ -9057,9 +9077,9 @@ class P115Client(P115OpenClient):
9057
9077
  4. show_dir=0 且 cur=0(或不指定 cur)
9058
9078
 
9059
9079
  .. hint::
9060
- 如果仅指定 natsort=1&show_dir=1,以及一个可选的 cid,则当文件数不大于 1150 时可仅统计某个目录内的文件或目录总数,而不返回具体的文件信息,超过那个数值时,则会返回完整的文件列表
9080
+ 如果不指定或者指定的 cid 不存在,则会视为 cid=0 进行处理
9061
9081
 
9062
- 但如果不指定或者指定的 cid 不存在,则会视为 cid=0 进行处理
9082
+ 当指定 natsort=1 时,如果里面的数量较少时,可仅统计某个目录内的文件或目录总数,而不返回具体的文件信息
9063
9083
 
9064
9084
  .. hint::
9065
9085
  当一个 cookies 被另一个更新的登录所失效,并不意味着这个 cookies 就直接不可用了。
p115client/tool/attr.py CHANGED
@@ -66,6 +66,7 @@ def get_attr(
66
66
  pickcode=info["pick_code"],
67
67
  sha1=info["sha1"],
68
68
  size=int(info["file_size"]),
69
+ is_dir=not info["sha1"],
69
70
  )
70
71
  else:
71
72
  resp = yield client.fs_file(id, async_=async_, **request_kwargs)
@@ -59,30 +59,6 @@ from .life import iter_life_behavior_once, life_show
59
59
  from .util import posix_escape_name, share_extract_payload, unescape_115_charref
60
60
 
61
61
 
62
- WEBAPI_BASE_URLS = (
63
- "http://webapi.115.com",
64
- "https://webapi.115.com",
65
- "http://webapi.115.com",
66
- "http://115cdn.com/webapi",
67
- "http://webapi.115.com",
68
- "http://115vod.com/webapi",
69
- )
70
- PROAPI_BASE_URLS = (
71
- "http://proapi.115.com",
72
- "https://proapi.115.com",
73
- "http://proapi.115.com",
74
- "https://proapi.115.com",
75
- )
76
- APS_BASE_URLS = (
77
- "http://115cdn.com/aps",
78
- "http://aps.115.com",
79
- "http://115vod.com/aps",
80
- )
81
-
82
- _n_get_ancestors = 0
83
- _n_get_count = 0
84
-
85
-
86
62
  class DirNode(NamedTuple):
87
63
  name: str
88
64
  parent_id: int
@@ -152,7 +128,7 @@ def get_path_to_cid(
152
128
  root_id: None | int = None,
153
129
  escape: None | bool | Callable[[str], str] = True,
154
130
  refresh: bool = False,
155
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
131
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
156
132
  app: str = "web",
157
133
  *,
158
134
  async_: Literal[False] = False,
@@ -166,7 +142,7 @@ def get_path_to_cid(
166
142
  root_id: None | int = None,
167
143
  escape: None | bool | Callable[[str], str] = True,
168
144
  refresh: bool = False,
169
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
145
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
170
146
  app: str = "web",
171
147
  *,
172
148
  async_: Literal[True],
@@ -179,7 +155,7 @@ def get_path_to_cid(
179
155
  root_id: None | int = None,
180
156
  escape: None | bool | Callable[[str], str] = True,
181
157
  refresh: bool = False,
182
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
158
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
183
159
  app: str = "web",
184
160
  *,
185
161
  async_: Literal[False, True] = False,
@@ -215,14 +191,31 @@ def get_path_to_cid(
215
191
  escape = cast(None | Callable[[str], str], escape)
216
192
  if id_to_dirnode is None:
217
193
  id_to_dirnode = ID_TO_DIRNODE_CACHE[client.user_id]
194
+ elif id_to_dirnode is ...:
195
+ id_to_dirnode = {}
218
196
  def gen_step():
219
197
  nonlocal cid
220
198
  parts: list[str] = []
221
199
  if cid and (refresh or cid not in id_to_dirnode):
222
- if app in ("", "web", "desktop", "harmony"):
223
- resp = yield client.fs_files({"cid": cid, "limit": 1}, async_=async_, **request_kwargs)
200
+ if not isinstance(client, P115Client) or app == "open":
201
+ resp = yield client.fs_files_open(
202
+ {"cid": cid, "cur": 1, "nf": 1, "hide_data": 1},
203
+ async_=async_,
204
+ **request_kwargs,
205
+ )
206
+ elif app in ("", "web", "desktop", "harmony"):
207
+ resp = yield client.fs_files_aps(
208
+ {"cid": cid, "limit": 1, "nf": 1, "star": 1},
209
+ async_=async_,
210
+ **request_kwargs,
211
+ )
224
212
  else:
225
- resp = yield client.fs_files_app({"cid": cid, "hide_data": 1}, async_=async_, **request_kwargs)
213
+ resp = yield client.fs_files_app(
214
+ {"cid": cid, "cur": 1, "nf": 1, "hide_data": 1},
215
+ app=app,
216
+ async_=async_,
217
+ **request_kwargs,
218
+ )
226
219
  check_response(resp)
227
220
  if cid and int(resp["path"][-1]["cid"]) != cid:
228
221
  raise FileNotFoundError(ENOENT, cid)
@@ -252,6 +245,8 @@ def get_file_count(
252
245
  client: str | P115Client,
253
246
  cid: int = 0,
254
247
  id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
248
+ app: str = "web",
249
+ use_fs_files: bool = True,
255
250
  *,
256
251
  async_: Literal[False] = False,
257
252
  **request_kwargs,
@@ -262,6 +257,8 @@ def get_file_count(
262
257
  client: str | P115Client,
263
258
  cid: int = 0,
264
259
  id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
260
+ app: str = "web",
261
+ use_fs_files: bool = True,
265
262
  *,
266
263
  async_: Literal[True],
267
264
  **request_kwargs,
@@ -271,6 +268,8 @@ def get_file_count(
271
268
  client: str | P115Client,
272
269
  cid: int = 0,
273
270
  id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
271
+ app: str = "web",
272
+ use_fs_files: bool = True,
274
273
  *,
275
274
  async_: Literal[False, True] = False,
276
275
  **request_kwargs,
@@ -283,6 +282,8 @@ def get_file_count(
283
282
  :param client: 115 客户端或 cookies
284
283
  :param cid: 目录 id
285
284
  :param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
285
+ :param app: 使用某个 app (设备)的接口
286
+ :param use_fs_files: 使用 `client.fs_files`,否则使用 `client.fs_category_get`
286
287
  :param async_: 是否异步
287
288
  :param request_kwargs: 其它请求参数
288
289
 
@@ -292,75 +293,78 @@ def get_file_count(
292
293
  client = P115Client(client, check_for_relogin=True)
293
294
  if id_to_dirnode is None:
294
295
  id_to_dirnode = ID_TO_DIRNODE_CACHE[client.user_id]
295
- n_webapi = len(WEBAPI_BASE_URLS)
296
- n_proapi = len(PROAPI_BASE_URLS)
297
- n_apsapi = len(APS_BASE_URLS)
298
- n_api = n_webapi * 2 + n_proapi * 2 + n_apsapi
299
- def get_resp():
300
- global _n_get_count
301
- n = _n_get_count % n_api
302
- if n < n_webapi:
303
- _n_get_count += 1
296
+ def get_resp_of_fs_files(id: int, /):
297
+ if not isinstance(client, P115Client) or app == "open":
298
+ return client.fs_files_open(
299
+ {"cid": id, "hide_data": 1, "show_dir": 0},
300
+ async_=async_,
301
+ **request_kwargs,
302
+ )
303
+ elif app in ("", "web", "desktop", "harmony"):
304
304
  return client.fs_files(
305
- {"cid": cid, "limit": 1, "show_dir": 0},
306
- base_url=WEBAPI_BASE_URLS[n],
305
+ {"cid": id, "limit": 1, "show_dir": 0},
307
306
  async_=async_,
308
307
  **request_kwargs,
309
308
  )
310
- n -= n_webapi
311
- if n < n_proapi:
312
- _n_get_count += 1
309
+ elif app == "aps":
310
+ return client.fs_files_aps(
311
+ {"cid": id, "limit": 1, "show_dir": 0},
312
+ async_=async_,
313
+ **request_kwargs,
314
+ )
315
+ else:
313
316
  return client.fs_files_app(
314
- {"cid": cid, "hide_data": 1, "show_dir": 0},
315
- base_url=PROAPI_BASE_URLS[n],
317
+ {"cid": id, "hide_data": 1, "show_dir": 0},
318
+ app=app,
316
319
  async_=async_,
317
320
  **request_kwargs,
318
321
  )
319
- n -= n_proapi
320
- if n < n_apsapi:
321
- _n_get_count += 1
322
- return client.fs_files_aps(
323
- {"cid": cid, "limit": 1, "show_dir": 0},
324
- base_url=APS_BASE_URLS[n],
322
+ def get_resp_of_category_get(id: int, /):
323
+ if not isinstance(client, P115Client) or app == "open":
324
+ return client.fs_info_open(
325
+ id,
325
326
  async_=async_,
326
327
  **request_kwargs,
327
328
  )
328
- n -= n_apsapi
329
- if n < n_webapi:
330
- _n_get_count += 1
329
+ elif app in ("", "web", "desktop", "harmony", "aps"):
331
330
  return client.fs_category_get(
332
- cid,
333
- base_url=WEBAPI_BASE_URLS[n],
331
+ id,
332
+ async_=async_,
333
+ **request_kwargs,
334
+ )
335
+ else:
336
+ return client.fs_category_get_app(
337
+ id,
338
+ app=app,
334
339
  async_=async_,
335
340
  **request_kwargs,
336
341
  )
337
- n -= n_webapi
338
- _n_get_count += 1
339
- return client.fs_category_get_app(
340
- cid,
341
- base_url=PROAPI_BASE_URLS[n],
342
- async_=async_,
343
- **request_kwargs,
344
- )
345
342
  def gen_step():
346
- if cid == 0:
343
+ if not cid:
347
344
  resp = yield client.fs_space_summury(async_=async_, **request_kwargs)
348
345
  check_response(resp)
349
346
  return sum(v["count"] for k, v in resp["type_summury"].items() if k.isupper())
350
- resp = yield get_resp()
351
- if not resp:
352
- raise FileNotFoundError(ENOENT, cid)
353
- check_response(resp)
354
- resp["cid"] = cid
355
- if "path" in resp:
347
+ if use_fs_files:
348
+ resp = yield get_resp_of_fs_files(cid)
349
+ check_response(resp)
356
350
  if cid != int(resp["path"][-1]["cid"]):
351
+ resp["cid"] = cid
357
352
  raise NotADirectoryError(ENOTDIR, resp)
358
353
  if id_to_dirnode is not ...:
359
354
  for info in resp["path"][1:]:
360
355
  id_to_dirnode[int(info["cid"])] = DirNode(info["name"], int(info["pid"]))
361
356
  return int(resp["count"])
362
357
  else:
358
+ resp = yield get_resp_of_category_get(cid)
359
+ if not resp:
360
+ raise FileNotFoundError(ENOENT, cid)
361
+ if "paths" not in resp:
362
+ check_response(resp)
363
+ resp = resp["data"]
364
+ if not resp:
365
+ raise FileNotFoundError(ENOENT, cid)
363
366
  if int(resp["file_category"]):
367
+ resp["cid"] = cid
364
368
  raise NotADirectoryError(ENOTDIR, resp)
365
369
  if id_to_dirnode is not ...:
366
370
  pid = 0
@@ -374,8 +378,9 @@ def get_file_count(
374
378
  @overload
375
379
  def get_ancestors(
376
380
  client: str | P115Client,
377
- attr: dict,
381
+ attr: int | dict,
378
382
  id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
383
+ app: str = "web",
379
384
  *,
380
385
  async_: Literal[False] = False,
381
386
  **request_kwargs,
@@ -384,8 +389,9 @@ def get_ancestors(
384
389
  @overload
385
390
  def get_ancestors(
386
391
  client: str | P115Client,
387
- attr: dict,
392
+ attr: int | dict,
388
393
  id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
394
+ app: str = "web",
389
395
  *,
390
396
  async_: Literal[True],
391
397
  **request_kwargs,
@@ -393,8 +399,9 @@ def get_ancestors(
393
399
  ...
394
400
  def get_ancestors(
395
401
  client: str | P115Client,
396
- attr: dict,
402
+ attr: int | dict,
397
403
  id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
404
+ app: str = "web",
398
405
  *,
399
406
  async_: Literal[False, True] = False,
400
407
  **request_kwargs,
@@ -405,8 +412,9 @@ def get_ancestors(
405
412
  我通过一些经验,搭配了多个接口的占比和参数分布,可能不够合理,以后会根据实际情况调整
406
413
 
407
414
  :param client: 115 客户端或 cookies
408
- :param attr: 待查询节点的信息(必须有 id parent_id
415
+ :param attr: 待查询节点 `id` 或信息(必须有 `id`,可选有 `parent_id`)
409
416
  :param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
417
+ :param app: 使用某个 app (设备)的接口
410
418
  :param async_: 是否异步
411
419
  :param request_kwargs: 其它请求参数
412
420
 
@@ -424,89 +432,168 @@ def get_ancestors(
424
432
  client = P115Client(client, check_for_relogin=True)
425
433
  if id_to_dirnode is None:
426
434
  id_to_dirnode = ID_TO_DIRNODE_CACHE[client.user_id]
427
- n_webapi = len(WEBAPI_BASE_URLS)
428
- n_proapi = len(PROAPI_BASE_URLS)
429
- n_apsapi = len(APS_BASE_URLS)
430
- n_api = n_webapi * 2 + n_proapi * 2 + n_apsapi
431
- def get_resp():
432
- global _n_get_ancestors
433
- n = _n_get_ancestors % n_api
434
- if n < n_webapi:
435
- _n_get_ancestors += 1
435
+ def get_resp_of_fs_files(id: int, /):
436
+ if not isinstance(client, P115Client) or app == "open":
437
+ return client.fs_files_open(
438
+ {"cid": id, "cur": 1, "nf": 1, "hide_data": 1},
439
+ async_=async_,
440
+ **request_kwargs,
441
+ )
442
+ elif app in ("", "web", "desktop", "harmony"):
436
443
  return client.fs_files(
437
- {"cid": attr["parent_id"], "limit": 1},
438
- base_url=WEBAPI_BASE_URLS[n],
444
+ {"cid": id, "limit": 1, "nf": 1, "star": 1},
439
445
  async_=async_,
440
446
  **request_kwargs,
441
447
  )
442
- n -= n_webapi
443
- if n < n_proapi:
444
- _n_get_ancestors += 1
448
+ elif app == "aps":
449
+ return client.fs_files_aps(
450
+ {"cid": id, "limit": 1, "nf": 1, "star": 1},
451
+ async_=async_,
452
+ **request_kwargs,
453
+ )
454
+ else:
445
455
  return client.fs_files_app(
446
- {"cid": attr["parent_id"], "hide_data": 1},
447
- base_url=PROAPI_BASE_URLS[n],
456
+ {"cid": id, "cur": 1, "nf": 1, "hide_data": 1},
457
+ app=app,
448
458
  async_=async_,
449
459
  **request_kwargs,
450
460
  )
451
- n -= n_proapi
452
- if n < n_apsapi:
453
- _n_get_ancestors += 1
454
- return client.fs_files_aps(
455
- {"cid": attr["parent_id"], "limit": 1},
456
- base_url=APS_BASE_URLS[n],
461
+ def get_resp_of_category_get(id: int, /):
462
+ if not isinstance(client, P115Client) or app == "open":
463
+ return client.fs_info_open(
464
+ id,
457
465
  async_=async_,
458
466
  **request_kwargs,
459
467
  )
460
- if attr.get("is_dir", False) or attr.get("is_directory", False):
461
- _n_get_ancestors = 0
462
- return get_resp()
463
- n -= n_apsapi
464
- if n < n_webapi:
465
- _n_get_ancestors += 1
468
+ elif app in ("", "web", "desktop", "harmony", "aps"):
466
469
  return client.fs_category_get(
467
- attr["id"],
468
- base_url=WEBAPI_BASE_URLS[n],
470
+ id,
471
+ async_=async_,
472
+ **request_kwargs,
473
+ )
474
+ else:
475
+ return client.fs_category_get_app(
476
+ id,
477
+ app=app,
469
478
  async_=async_,
470
479
  **request_kwargs,
471
480
  )
472
- n -= n_webapi
473
- _n_get_ancestors += 1
474
- return client.fs_category_get_app(
475
- attr["id"],
476
- base_url=PROAPI_BASE_URLS[n],
477
- async_=async_,
478
- **request_kwargs,
479
- )
480
481
  def gen_step():
481
- if not attr["parent_id"]:
482
- return [{"id": 0, "parent_id": 0, "name": ""}]
483
- resp = yield get_resp()
484
- if not resp:
485
- raise FileNotFoundError(ENOENT, attr)
486
- check_response(resp)
487
- resp["attr"] = attr
488
482
  ancestors: list[dict] = [{"id": 0, "parent_id": 0, "name": ""}]
489
483
  add_ancestor = ancestors.append
490
484
  pid = 0
491
- if "path" in resp:
492
- if attr["parent_id"] != int(resp["path"][-1]["cid"]):
493
- raise FileNotFoundError(ENOENT, resp)
494
- for info in resp["path"][1:]:
495
- add_ancestor({
496
- "parent_id": pid,
497
- "id": (pid := int(info["cid"])),
498
- "name": info["name"],
499
- })
485
+ is_completed = False
486
+ if isinstance(attr, dict):
487
+ fid = cast(int, attr["id"])
488
+ if not fid:
489
+ return ancestors
490
+ is_dir: None | bool = attr.get("is_dir") or attr.get("is_directory")
491
+ if is_dir is None:
492
+ if "parent_id" in attr:
493
+ cid = cast(int, attr["parent_id"])
494
+ resp = yield get_resp_of_fs_files(cid)
495
+ if cid != int(resp["path"][-1]["cid"]):
496
+ resp["attr"] = attr
497
+ raise FileNotFoundError(ENOENT, resp)
498
+ for info in resp["path"][1:]:
499
+ add_ancestor({
500
+ "parent_id": pid,
501
+ "id": (pid := int(info["cid"])),
502
+ "name": info["name"],
503
+ })
504
+ if id_to_dirnode is not ...:
505
+ for ans in ancestors[1:]:
506
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
507
+ if "name" in attr:
508
+ name = attr["name"]
509
+ is_dir = bool(attr.get("is_dir"))
510
+ else:
511
+ resp = yield client.fs_file_skim(attr["id"], async_=async_, **request_kwargs)
512
+ check_response(resp)
513
+ name = unescape_115_charref(resp["data"]["file_name"])
514
+ is_dir = not resp["data"]["sha1"]
515
+ ans = {"id": fid, "parent_id": pid, "name": name}
516
+ add_ancestor(ans)
517
+ if is_dir and id_to_dirnode is not ...:
518
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
519
+ is_completed = True
520
+ elif is_dir:
521
+ resp = yield get_resp_of_fs_files(fid)
522
+ if fid != int(resp["path"][-1]["cid"]):
523
+ resp["attr"] = attr
524
+ raise FileNotFoundError(ENOENT, resp)
525
+ for info in resp["path"][1:]:
526
+ add_ancestor({
527
+ "parent_id": pid,
528
+ "id": (pid := int(info["cid"])),
529
+ "name": info["name"],
530
+ })
531
+ if id_to_dirnode is not ...:
532
+ for ans in ancestors[1:]:
533
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
534
+ is_completed = True
535
+ else:
536
+ resp = yield get_resp_of_category_get(fid)
537
+ if not resp:
538
+ raise FileNotFoundError(ENOENT, attr)
539
+ if "paths" not in resp:
540
+ check_response(resp)
541
+ resp = resp["data"]
542
+ if not resp:
543
+ raise FileNotFoundError(ENOENT, attr)
544
+ for info in resp["paths"]:
545
+ add_ancestor({
546
+ "parent_id": pid,
547
+ "id": (pid := int(info["file_id"])),
548
+ "name": info["file_name"],
549
+ })
550
+ if id_to_dirnode is not ...:
551
+ for ans in ancestors[1:]:
552
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
553
+ ans = {"id": fid, "parent_id": pid, "name": resp["file_name"]}
554
+ add_ancestor(ans)
555
+ if not resp.get("sha1") and id_to_dirnode is not ...:
556
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
557
+ is_completed = True
500
558
  else:
501
- for info in resp["paths"]:
502
- add_ancestor({
503
- "parent_id": pid,
504
- "id": (pid := int(info["file_id"])),
505
- "name": info["file_name"],
506
- })
507
- if id_to_dirnode is not ...:
508
- for ans in ancestors[1:]:
509
- id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
559
+ fid = attr
560
+ if not is_completed:
561
+ if not fid:
562
+ return ancestors
563
+ resp = yield get_resp_of_fs_files(fid)
564
+ check_response(resp)
565
+ if fid == int(resp["path"][-1]["cid"]):
566
+ for info in resp["path"][1:]:
567
+ add_ancestor({
568
+ "parent_id": pid,
569
+ "id": (pid := int(info["cid"])),
570
+ "name": info["name"],
571
+ })
572
+ if id_to_dirnode is not ...:
573
+ for ans in ancestors[1:]:
574
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
575
+ else:
576
+ resp = yield get_resp_of_category_get(fid)
577
+ if not resp:
578
+ raise FileNotFoundError(ENOENT, fid)
579
+ if "paths" not in resp:
580
+ check_response(resp)
581
+ resp = resp["data"]
582
+ if not resp:
583
+ raise FileNotFoundError(ENOENT, fid)
584
+ for info in resp["paths"]:
585
+ add_ancestor({
586
+ "parent_id": pid,
587
+ "id": (pid := int(info["file_id"])),
588
+ "name": info["file_name"],
589
+ })
590
+ if id_to_dirnode is not ...:
591
+ for ans in ancestors[1:]:
592
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
593
+ ans = {"id": fid, "parent_id": pid, "name": resp["file_name"]}
594
+ add_ancestor(ans)
595
+ if not resp.get("sha1") and id_to_dirnode is not ...:
596
+ id_to_dirnode[ans["id"]] = DirNode(ans["name"], ans["parent_id"])
510
597
  return ancestors
511
598
  return run_gen_step(gen_step, async_=async_)
512
599
 
@@ -516,7 +603,7 @@ def get_ancestors_to_cid(
516
603
  client: str | P115Client,
517
604
  cid: int = 0,
518
605
  refresh: bool = False,
519
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
606
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
520
607
  app: str = "web",
521
608
  *,
522
609
  async_: Literal[False] = False,
@@ -528,7 +615,7 @@ def get_ancestors_to_cid(
528
615
  client: str | P115Client,
529
616
  cid: int = 0,
530
617
  refresh: bool = False,
531
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
618
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
532
619
  app: str = "web",
533
620
  *,
534
621
  async_: Literal[True],
@@ -539,7 +626,7 @@ def get_ancestors_to_cid(
539
626
  client: str | P115Client,
540
627
  cid: int = 0,
541
628
  refresh: bool = False,
542
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
629
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
543
630
  app: str = "web",
544
631
  *,
545
632
  async_: Literal[False, True] = False,
@@ -569,14 +656,31 @@ def get_ancestors_to_cid(
569
656
  client = P115Client(client, check_for_relogin=True)
570
657
  if id_to_dirnode is None:
571
658
  id_to_dirnode = ID_TO_DIRNODE_CACHE[client.user_id]
659
+ elif id_to_dirnode is ...:
660
+ id_to_dirnode = {}
572
661
  def gen_step():
573
662
  nonlocal cid
574
663
  parts: list[dict] = []
575
664
  if cid and (refresh or cid not in id_to_dirnode):
576
- if app in ("", "web", "desktop", "harmony"):
577
- resp = yield client.fs_files({"cid": cid, "limit": 1}, async_=async_, **request_kwargs)
665
+ if not isinstance(client, P115Client) or app == "open":
666
+ resp = yield client.fs_files_open(
667
+ {"cid": cid, "cur": 1, "nf": 1, "hide_data": 1},
668
+ async_=async_,
669
+ **request_kwargs,
670
+ )
671
+ elif app in ("", "web", "desktop", "harmony"):
672
+ resp = yield client.fs_files_aps(
673
+ {"cid": cid, "limit": 1, "nf": 1, "star": 1},
674
+ async_=async_,
675
+ **request_kwargs,
676
+ )
578
677
  else:
579
- resp = yield client.fs_files_app({"cid": cid, "hide_data": 1}, async_=async_, **request_kwargs)
678
+ resp = yield client.fs_files_app(
679
+ {"cid": cid, "cur": 1, "nf": 1, "hide_data": 1},
680
+ app=app,
681
+ async_=async_,
682
+ **request_kwargs,
683
+ )
580
684
  check_response(resp)
581
685
  if cid and int(resp["path"][-1]["cid"]) != cid:
582
686
  raise FileNotFoundError(ENOENT, cid)
@@ -605,7 +709,7 @@ def get_id_to_path(
605
709
  ensure_file: None | bool = None,
606
710
  is_posixpath: bool = False,
607
711
  refresh: bool = False,
608
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
712
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
609
713
  app: str = "web",
610
714
  dont_use_getid: bool = False,
611
715
  *,
@@ -621,7 +725,7 @@ def get_id_to_path(
621
725
  ensure_file: None | bool = None,
622
726
  is_posixpath: bool = False,
623
727
  refresh: bool = False,
624
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
728
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
625
729
  app: str = "web",
626
730
  dont_use_getid: bool = False,
627
731
  *,
@@ -636,7 +740,7 @@ def get_id_to_path(
636
740
  ensure_file: None | bool = None,
637
741
  is_posixpath: bool = False,
638
742
  refresh: bool = False,
639
- id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
743
+ id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
640
744
  app: str = "web",
641
745
  dont_use_getid: bool = False,
642
746
  *,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: p115client
3
- Version: 0.0.5.10.4
3
+ Version: 0.0.5.10.6
4
4
  Summary: Python 115 webdisk client.
5
5
  Home-page: https://github.com/ChenyangGao/p115client
6
6
  License: MIT
@@ -1,18 +1,18 @@
1
1
  LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
2
  p115client/__init__.py,sha256=1mx7njuAlqcuEWONTjSiiGnXyyNyqOcJyNX1FMHqQ-4,214
3
3
  p115client/_upload.py,sha256=DOckFLU_P7Fl0BNu_0-2od6pPsCnzroYY6zZE5_EMnM,30735
4
- p115client/client.py,sha256=98Zf8CzxeSPcU-U7LUd9KMY2WON7F90kGSokbVcqqXU,727434
4
+ p115client/client.py,sha256=rNLeQTbQp861Vs6L-OfEXh6ykM-NvfycwaCZJiOx91E,727374
5
5
  p115client/const.py,sha256=AMyL3QZ172f_RaEkfh27DQxwbkXvPhqfeBWHWTrvSLY,7754
6
6
  p115client/exception.py,sha256=kQMI7lwkFIC_tRuj1HT8zqi5HGzz6fTxgK7B1aKrNTI,3447
7
7
  p115client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  p115client/tool/__init__.py,sha256=NjT9rroMhLwKI7UlpSCksSsnB3GexXzxvhfunNWzjY0,386
9
- p115client/tool/attr.py,sha256=u_5JM2LlWFT4IHF2zlz-DY4llgmw4mwouEKMae8BZdQ,2841
9
+ p115client/tool/attr.py,sha256=9xN99lgFxE-48nqiIOSuuo3R0D9lcvuJvcRbJzPKKiw,2883
10
10
  p115client/tool/download.py,sha256=3zoxkLPf4Jya-wYowZJmZR65sR3GWNWNmnevKrrgvQY,60509
11
11
  p115client/tool/edit.py,sha256=eRlR1UZMpfGnoetpqSAAx5bPBOEiSlx7HPkpOSs5agk,17739
12
12
  p115client/tool/export_dir.py,sha256=iMnKtnESi8HKvW9WhIvOdEoMXSBpAnhFlGeyKXHpQbE,24545
13
13
  p115client/tool/fs_files.py,sha256=jY57L4nhB9t-2kT_1j3mdiwOdPZKsimN3eN5mUJAqMI,15745
14
14
  p115client/tool/history.py,sha256=2S26BH7uBNfVHlbYFNy-aNOLMcM-HrlR7TLHAZacUJI,7458
15
- p115client/tool/iterdir.py,sha256=Qgs1fHwfgCXb-9T_1WQfyhnfXe8LZYwZY7oMTnCz3tQ,192038
15
+ p115client/tool/iterdir.py,sha256=bg59xHMxSuPEAqlmEhF6IBvbSW8piKbfrb6QYtAixa0,197797
16
16
  p115client/tool/life.py,sha256=X6Bp0GYKwnZeWlttE2DIVw5iOCXM5QzIkM6Zuj24c5Y,17323
17
17
  p115client/tool/pool.py,sha256=K-ALC-JEwik3DYCr5Eckok15oQnHRe6yznKIuJ9jyyM,13953
18
18
  p115client/tool/request.py,sha256=rjXuQwRganE5Z-4rfgnyPFjE4jzdQSLdIs9s0cIDshU,7043
@@ -20,7 +20,7 @@ p115client/tool/upload.py,sha256=qK1OQYxP-Faq2eMDhc5sBXJiSr8m8EZ_gb0O_iA2TrI,159
20
20
  p115client/tool/util.py,sha256=0o9TrXdoPcljgxDDRdxRon41bq1OjuUYCWsR0XLfmPo,3357
21
21
  p115client/tool/xys.py,sha256=WMTisCyN4eYyv4A14yYOpjud2mBhQvBcUHOp6pJUQeA,10140
22
22
  p115client/type.py,sha256=7kOp98uLaYqcTTCgCrb3DRcl8ukMpn7ibsnVvtw2nG8,6250
23
- p115client-0.0.5.10.4.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
24
- p115client-0.0.5.10.4.dist-info/METADATA,sha256=-zPTpPGe0IpuPfetzVHdvKDXQ9PGxPIu--dw7MFJxns,8276
25
- p115client-0.0.5.10.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
26
- p115client-0.0.5.10.4.dist-info/RECORD,,
23
+ p115client-0.0.5.10.6.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
24
+ p115client-0.0.5.10.6.dist-info/METADATA,sha256=Uahbt1F8XXlWu3VG5PvJps8OsInLt78coGPwhSI1RgI,8276
25
+ p115client-0.0.5.10.6.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
26
+ p115client-0.0.5.10.6.dist-info/RECORD,,