p115client 0.0.5.8.4__py3-none-any.whl → 0.0.5.8.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 +64 -2
- p115client/tool/download.py +28 -25
- p115client/tool/edit.py +50 -5
- p115client/tool/iterdir.py +101 -6
- {p115client-0.0.5.8.4.dist-info → p115client-0.0.5.8.6.dist-info}/METADATA +1 -1
- {p115client-0.0.5.8.4.dist-info → p115client-0.0.5.8.6.dist-info}/RECORD +8 -8
- {p115client-0.0.5.8.4.dist-info → p115client-0.0.5.8.6.dist-info}/LICENSE +0 -0
- {p115client-0.0.5.8.4.dist-info → p115client-0.0.5.8.6.dist-info}/WHEEL +0 -0
p115client/client.py
CHANGED
@@ -3139,6 +3139,64 @@ class P115OpenClient(ClientRequestMixin):
|
|
3139
3139
|
}
|
3140
3140
|
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
3141
3141
|
|
3142
|
+
@overload
|
3143
|
+
def fs_star_set(
|
3144
|
+
self,
|
3145
|
+
payload: int | str | Iterable[int | str] | dict,
|
3146
|
+
/,
|
3147
|
+
star: bool = True,
|
3148
|
+
base_url: bool | str | Callable[[], str] = False,
|
3149
|
+
*,
|
3150
|
+
async_: Literal[False] = False,
|
3151
|
+
**request_kwargs,
|
3152
|
+
) -> dict:
|
3153
|
+
...
|
3154
|
+
@overload
|
3155
|
+
def fs_star_set(
|
3156
|
+
self,
|
3157
|
+
payload: int | str | Iterable[int | str] | dict,
|
3158
|
+
/,
|
3159
|
+
star: bool = True,
|
3160
|
+
base_url: bool | str | Callable[[], str] = False,
|
3161
|
+
*,
|
3162
|
+
async_: Literal[True],
|
3163
|
+
**request_kwargs,
|
3164
|
+
) -> Coroutine[Any, Any, dict]:
|
3165
|
+
...
|
3166
|
+
def fs_star_set(
|
3167
|
+
self,
|
3168
|
+
payload: int | str | Iterable[int | str] | dict,
|
3169
|
+
/,
|
3170
|
+
star: bool = True,
|
3171
|
+
base_url: bool | str | Callable[[], str] = False,
|
3172
|
+
*,
|
3173
|
+
async_: Literal[False, True] = False,
|
3174
|
+
**request_kwargs,
|
3175
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3176
|
+
"""为文件或目录设置或取消星标,此接口是对 `fs_update_open` 的封装
|
3177
|
+
|
3178
|
+
.. note::
|
3179
|
+
即使其中任何一个 id 目前已经被删除,也可以操作成功
|
3180
|
+
|
3181
|
+
:payload:
|
3182
|
+
- file_id: int | str 💡 只能传入 1 个
|
3183
|
+
- file_id[0]: int | str 💡 如果有多个,则按顺序给出
|
3184
|
+
- file_id[1]: int | str
|
3185
|
+
- ...
|
3186
|
+
- star: 0 | 1 = 1
|
3187
|
+
"""
|
3188
|
+
api = complete_webapi("/files/star", base_url=base_url)
|
3189
|
+
if isinstance(payload, (int, str)):
|
3190
|
+
payload = {"file_id": payload, "star": int(star)}
|
3191
|
+
elif not isinstance(payload, dict):
|
3192
|
+
payload = {f"file_id[{i}]": id for i, id in enumerate(payload)}
|
3193
|
+
if not payload:
|
3194
|
+
return {"state": False, "message": "no op"}
|
3195
|
+
payload["star"] = int(star)
|
3196
|
+
else:
|
3197
|
+
payload = {"star": int(star), **payload}
|
3198
|
+
return self.fs_update(payload, async_=async_, **request_kwargs)
|
3199
|
+
|
3142
3200
|
@overload
|
3143
3201
|
def fs_update(
|
3144
3202
|
self,
|
@@ -3175,13 +3233,16 @@ class P115OpenClient(ClientRequestMixin):
|
|
3175
3233
|
POST https://proapi.115.com/open/ufile/update
|
3176
3234
|
|
3177
3235
|
.. hint::
|
3178
|
-
|
3236
|
+
即使文件已经被删除,也可以操作成功
|
3179
3237
|
|
3180
3238
|
.. note::
|
3181
3239
|
https://www.yuque.com/115yun/open/gyrpw5a0zc4sengm
|
3182
3240
|
|
3183
3241
|
:payload:
|
3184
|
-
- file_id: int | str
|
3242
|
+
- file_id: int | str 💡 只能传入 1 个
|
3243
|
+
- file_id[0]: int | str 💡 如果有多个,则按顺序给出
|
3244
|
+
- file_id[1]: int | str
|
3245
|
+
- ...
|
3185
3246
|
- file_name: str = <default> 💡 文件名
|
3186
3247
|
- star: 0 | 1 = <default> 💡 是否星标:0:取消星标 1:设置星标
|
3187
3248
|
- ...
|
@@ -3970,6 +4031,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3970
4031
|
fs_mkdir_open = fs_mkdir
|
3971
4032
|
fs_move_open = fs_move
|
3972
4033
|
fs_search_open = fs_search
|
4034
|
+
fs_star_set_open = fs_star_set
|
3973
4035
|
fs_update_open = fs_update
|
3974
4036
|
recyclebin_clean_open = recyclebin_clean
|
3975
4037
|
recyclebin_list_open = recyclebin_list
|
p115client/tool/download.py
CHANGED
@@ -25,6 +25,7 @@ from shutil import rmtree
|
|
25
25
|
from threading import Lock
|
26
26
|
from time import time
|
27
27
|
from typing import cast, overload, Any, Final, Literal, TypedDict
|
28
|
+
from types import EllipsisType
|
28
29
|
from urllib.parse import quote, urlsplit
|
29
30
|
from urllib.request import urlopen, Request
|
30
31
|
from uuid import uuid4
|
@@ -257,7 +258,7 @@ def iter_files_with_url(
|
|
257
258
|
use_star: None | bool = False,
|
258
259
|
escape: None | bool | Callable[[str], str] = True,
|
259
260
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
260
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
261
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
261
262
|
app: str = "web",
|
262
263
|
raise_for_changed_count: bool = False,
|
263
264
|
user_agent: str = "",
|
@@ -278,7 +279,7 @@ def iter_files_with_url(
|
|
278
279
|
use_star: None | bool = False,
|
279
280
|
escape: None | bool | Callable[[str], str] = True,
|
280
281
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
281
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
282
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
282
283
|
app: str = "web",
|
283
284
|
raise_for_changed_count: bool = False,
|
284
285
|
user_agent: str = "",
|
@@ -298,7 +299,7 @@ def iter_files_with_url(
|
|
298
299
|
use_star: None | bool = False,
|
299
300
|
escape: None | bool | Callable[[str], str] = True,
|
300
301
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
301
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
302
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
302
303
|
app: str = "web",
|
303
304
|
raise_for_changed_count: bool = False,
|
304
305
|
user_agent: str = "",
|
@@ -423,7 +424,7 @@ def iter_images_with_url(
|
|
423
424
|
use_star: None | bool = False,
|
424
425
|
escape: None | bool | Callable[[str], str] = True,
|
425
426
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
426
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
427
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
427
428
|
app: str = "web",
|
428
429
|
raise_for_changed_count: bool = False,
|
429
430
|
*,
|
@@ -442,7 +443,7 @@ def iter_images_with_url(
|
|
442
443
|
use_star: None | bool = False,
|
443
444
|
escape: None | bool | Callable[[str], str] = True,
|
444
445
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
445
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
446
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
446
447
|
app: str = "web",
|
447
448
|
raise_for_changed_count: bool = False,
|
448
449
|
*,
|
@@ -460,7 +461,7 @@ def iter_images_with_url(
|
|
460
461
|
use_star: None | bool = False,
|
461
462
|
escape: None | bool | Callable[[str], str] = True,
|
462
463
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
463
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
464
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
464
465
|
app: str = "web",
|
465
466
|
raise_for_changed_count: bool = False,
|
466
467
|
*,
|
@@ -578,7 +579,7 @@ def iter_subtitles_with_url(
|
|
578
579
|
use_star: None | bool = False,
|
579
580
|
escape: None | bool | Callable[[str], str] = True,
|
580
581
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
581
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
582
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
582
583
|
app: str = "web",
|
583
584
|
raise_for_changed_count: bool = False,
|
584
585
|
*,
|
@@ -597,7 +598,7 @@ def iter_subtitles_with_url(
|
|
597
598
|
use_star: None | bool = False,
|
598
599
|
escape: None | bool | Callable[[str], str] = True,
|
599
600
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
600
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
601
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
601
602
|
app: str = "web",
|
602
603
|
raise_for_changed_count: bool = False,
|
603
604
|
*,
|
@@ -615,7 +616,7 @@ def iter_subtitles_with_url(
|
|
615
616
|
use_star: None | bool = False,
|
616
617
|
escape: None | bool | Callable[[str], str] = True,
|
617
618
|
normalize_attr: Callable[[dict], dict] = normalize_attr,
|
618
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
619
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
619
620
|
app: str = "web",
|
620
621
|
raise_for_changed_count: bool = False,
|
621
622
|
*,
|
@@ -855,7 +856,7 @@ def make_strm(
|
|
855
856
|
suffix: str = "",
|
856
857
|
type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
|
857
858
|
max_workers: None | int = None,
|
858
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
859
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
859
860
|
path_already: bool = False,
|
860
861
|
app: str = "android",
|
861
862
|
fs_files_cooldown: int | float = 0.5,
|
@@ -881,7 +882,7 @@ def make_strm(
|
|
881
882
|
suffix: str = "",
|
882
883
|
type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
|
883
884
|
max_workers: None | int = None,
|
884
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
885
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
885
886
|
path_already: bool = False,
|
886
887
|
app: str = "android",
|
887
888
|
fs_files_cooldown: int | float = 0.5,
|
@@ -906,7 +907,7 @@ def make_strm(
|
|
906
907
|
suffix: str = "",
|
907
908
|
type: Literal[1, 2, 3, 4, 5, 6, 7, 99] = 4,
|
908
909
|
max_workers: None | int = None,
|
909
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
910
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
910
911
|
path_already: bool = False,
|
911
912
|
app: str = "android",
|
912
913
|
fs_files_cooldown: int | float = 0.5,
|
@@ -1170,40 +1171,36 @@ def iter_download_nodes(
|
|
1170
1171
|
method = client.download_files
|
1171
1172
|
else:
|
1172
1173
|
method = client.download_folders
|
1174
|
+
get_nodes = partial(method, async_=async_, **{"base_url": get_base_url, **request_kwargs})
|
1173
1175
|
if max_workers == 1:
|
1174
1176
|
def gen_step(pickcode):
|
1175
1177
|
if isinstance(pickcode, int):
|
1176
1178
|
resp = yield client.fs_file_skim(pickcode, async_=async_, **request_kwargs)
|
1177
1179
|
check_response(resp)
|
1178
1180
|
pickcode = resp["data"][0]["pick_code"]
|
1179
|
-
request_kwargs.setdefault("base_url", get_base_url)
|
1180
1181
|
for i in count(1):
|
1181
1182
|
payload = {"pickcode": pickcode, "page": i}
|
1182
|
-
resp = yield
|
1183
|
+
resp = yield get_nodes(payload)
|
1183
1184
|
check_response(resp)
|
1184
1185
|
data = resp["data"]
|
1185
1186
|
yield YieldFrom(data["list"], identity=True)
|
1186
1187
|
if not data["has_next_page"]:
|
1187
1188
|
break
|
1188
1189
|
else:
|
1190
|
+
max_page = 0
|
1189
1191
|
get_next_page = count(1).__next__
|
1190
1192
|
if async_:
|
1191
1193
|
q: Any = AsyncQueue()
|
1192
1194
|
else:
|
1193
1195
|
q = SimpleQueue()
|
1194
1196
|
get, put = q.get, q.put_nowait
|
1195
|
-
max_page = 0
|
1196
1197
|
def request(pickcode):
|
1197
1198
|
nonlocal max_page
|
1198
1199
|
while True:
|
1199
1200
|
page = get_next_page()
|
1200
1201
|
if max_page and page > max_page:
|
1201
1202
|
return
|
1202
|
-
resp: dict = yield
|
1203
|
-
{"pickcode": pickcode, "page": page},
|
1204
|
-
async_=async_, # type: ignore
|
1205
|
-
**request_kwargs,
|
1206
|
-
)
|
1203
|
+
resp: dict = yield get_nodes({"pickcode": pickcode, "page": page})
|
1207
1204
|
try:
|
1208
1205
|
check_response(resp)
|
1209
1206
|
except BaseException as e:
|
@@ -1214,7 +1211,9 @@ def iter_download_nodes(
|
|
1214
1211
|
if not data["has_next_page"]:
|
1215
1212
|
max_page = page
|
1216
1213
|
def gen_step(pickcode):
|
1217
|
-
nonlocal max_workers
|
1214
|
+
nonlocal max_workers, max_page, get_next_page
|
1215
|
+
max_page = 0
|
1216
|
+
get_next_page = count(1).__next__
|
1218
1217
|
if async_:
|
1219
1218
|
if max_workers is None or max_workers <= 0:
|
1220
1219
|
max_workers = 20
|
@@ -1239,7 +1238,6 @@ def iter_download_nodes(
|
|
1239
1238
|
)
|
1240
1239
|
check_response(resp)
|
1241
1240
|
pickcode = resp["data"][0]["pick_code"]
|
1242
|
-
request_kwargs.setdefault("base_url", cycle(("http://proapi.115.com", "https://proapi.115.com")).__next__)
|
1243
1241
|
try:
|
1244
1242
|
sentinel = object()
|
1245
1243
|
countdown: Callable
|
@@ -1282,6 +1280,11 @@ def iter_download_nodes(
|
|
1282
1280
|
)) as get_next:
|
1283
1281
|
while True:
|
1284
1282
|
attr = yield get_next
|
1283
|
+
if not files:
|
1284
|
+
yield Yield(
|
1285
|
+
{"fid": str(attr["id"]), "pid": "0", "fn": attr["name"]},
|
1286
|
+
identity=True,
|
1287
|
+
)
|
1285
1288
|
yield YieldFrom(
|
1286
1289
|
run_gen_step_iter(gen_step(attr["pickcode"]), async_=async_),
|
1287
1290
|
identity=True,
|
@@ -1293,7 +1296,7 @@ def iter_download_nodes(
|
|
1293
1296
|
def iter_download_files(
|
1294
1297
|
client: str | P115Client,
|
1295
1298
|
cid: int = 0,
|
1296
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
1299
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
1297
1300
|
escape: None | bool | Callable[[str], str] = True,
|
1298
1301
|
with_ancestors: bool = True,
|
1299
1302
|
max_workers: None | int = None,
|
@@ -1307,7 +1310,7 @@ def iter_download_files(
|
|
1307
1310
|
def iter_download_files(
|
1308
1311
|
client: str | P115Client,
|
1309
1312
|
cid: int = 0,
|
1310
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
1313
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
1311
1314
|
escape: None | bool | Callable[[str], str] = True,
|
1312
1315
|
with_ancestors: bool = True,
|
1313
1316
|
max_workers: None | int = None,
|
@@ -1320,7 +1323,7 @@ def iter_download_files(
|
|
1320
1323
|
def iter_download_files(
|
1321
1324
|
client: str | P115Client,
|
1322
1325
|
cid: int = 0,
|
1323
|
-
id_to_dirnode: None | dict[int, tuple[str, int] | DirNode] = None,
|
1326
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
1324
1327
|
escape: None | bool | Callable[[str], str] = True,
|
1325
1328
|
with_ancestors: bool = True,
|
1326
1329
|
max_workers: None | int = None,
|
p115client/tool/edit.py
CHANGED
@@ -103,6 +103,7 @@ def update_desc(
|
|
103
103
|
desc: str = "",
|
104
104
|
batch_size: int = 10_000,
|
105
105
|
max_workers: None | int = None,
|
106
|
+
app: str = "web",
|
106
107
|
*,
|
107
108
|
async_: Literal[False] = False,
|
108
109
|
**request_kwargs,
|
@@ -116,6 +117,7 @@ def update_desc(
|
|
116
117
|
desc: str = "",
|
117
118
|
batch_size: int = 10_000,
|
118
119
|
max_workers: None | int = None,
|
120
|
+
app: str = "web",
|
119
121
|
*,
|
120
122
|
async_: Literal[True],
|
121
123
|
**request_kwargs,
|
@@ -128,6 +130,7 @@ def update_desc(
|
|
128
130
|
desc: str = "",
|
129
131
|
batch_size: int = 10_000,
|
130
132
|
max_workers: None | int = None,
|
133
|
+
app: str = "web",
|
131
134
|
*,
|
132
135
|
async_: Literal[False, True] = False,
|
133
136
|
**request_kwargs,
|
@@ -139,13 +142,19 @@ def update_desc(
|
|
139
142
|
:param desc: 备注文本
|
140
143
|
:param batch_size: 批次大小,分批次,每次提交的 id 数
|
141
144
|
:param max_workers: 并发工作数,如果为 None 或者 <= 0,则自动确定
|
145
|
+
:param app: 使用此设备的接口
|
142
146
|
:param async_: 是否异步
|
143
147
|
:param request_kwargs: 其它请求参数
|
144
148
|
"""
|
149
|
+
if app in ("", "web", "desktop", "harmony"):
|
150
|
+
method = "fs_desc_set"
|
151
|
+
else:
|
152
|
+
method = "fs_desc_set_app"
|
153
|
+
request_kwargs["app"] = app
|
145
154
|
return update_abstract(
|
146
155
|
client,
|
147
156
|
ids, # type: ignore
|
148
|
-
method=
|
157
|
+
method=method,
|
149
158
|
value=desc,
|
150
159
|
batch_size=batch_size,
|
151
160
|
max_workers=max_workers,
|
@@ -162,6 +171,7 @@ def update_star(
|
|
162
171
|
star: bool = True,
|
163
172
|
batch_size: int = 10_000,
|
164
173
|
max_workers: None | int = None,
|
174
|
+
app: str = "web",
|
165
175
|
*,
|
166
176
|
async_: Literal[False] = False,
|
167
177
|
**request_kwargs,
|
@@ -175,6 +185,7 @@ def update_star(
|
|
175
185
|
star: bool = True,
|
176
186
|
batch_size: int = 10_000,
|
177
187
|
max_workers: None | int = None,
|
188
|
+
app: str = "web",
|
178
189
|
*,
|
179
190
|
async_: Literal[True],
|
180
191
|
**request_kwargs,
|
@@ -187,6 +198,7 @@ def update_star(
|
|
187
198
|
star: bool = True,
|
188
199
|
batch_size: int = 10_000,
|
189
200
|
max_workers: None | int = None,
|
201
|
+
app: str = "web",
|
190
202
|
*,
|
191
203
|
async_: Literal[False, True] = False,
|
192
204
|
**request_kwargs,
|
@@ -201,13 +213,23 @@ def update_star(
|
|
201
213
|
:param star: 是否设置星标
|
202
214
|
:param batch_size: 批次大小,分批次,每次提交的 id 数
|
203
215
|
:param max_workers: 并发工作数,如果为 None 或者 <= 0,则自动确定
|
216
|
+
:param app: 使用此设备的接口
|
204
217
|
:param async_: 是否异步
|
205
218
|
:param request_kwargs: 其它请求参数
|
206
219
|
"""
|
220
|
+
if isinstance(client, str):
|
221
|
+
client = P115Client(client, check_for_relogin=True)
|
222
|
+
if not isinstance(client, P115Client) or app == "open":
|
223
|
+
method = "fs_star_set_open"
|
224
|
+
elif app in ("", "web", "desktop", "harmony"):
|
225
|
+
method = "fs_star_set"
|
226
|
+
else:
|
227
|
+
method = "fs_star_set_app"
|
228
|
+
request_kwargs["app"] = app
|
207
229
|
return update_abstract(
|
208
230
|
client,
|
209
231
|
ids, # type: ignore
|
210
|
-
method=
|
232
|
+
method=method,
|
211
233
|
value=star,
|
212
234
|
batch_size=batch_size,
|
213
235
|
max_workers=max_workers,
|
@@ -224,6 +246,7 @@ def update_label(
|
|
224
246
|
label: int | str = 1,
|
225
247
|
batch_size: int = 10_000,
|
226
248
|
max_workers: None | int = None,
|
249
|
+
app: str = "web",
|
227
250
|
*,
|
228
251
|
async_: Literal[False] = False,
|
229
252
|
**request_kwargs,
|
@@ -237,6 +260,7 @@ def update_label(
|
|
237
260
|
label: int | str = 1,
|
238
261
|
batch_size: int = 10_000,
|
239
262
|
max_workers: None | int = None,
|
263
|
+
app: str = "web",
|
240
264
|
*,
|
241
265
|
async_: Literal[True],
|
242
266
|
**request_kwargs,
|
@@ -249,6 +273,7 @@ def update_label(
|
|
249
273
|
label: int | str = 1,
|
250
274
|
batch_size: int = 10_000,
|
251
275
|
max_workers: None | int = None,
|
276
|
+
app: str = "web",
|
252
277
|
*,
|
253
278
|
async_: Literal[False, True] = False,
|
254
279
|
**request_kwargs,
|
@@ -260,13 +285,19 @@ def update_label(
|
|
260
285
|
:param label: 标签 id,多个用逗号 "," 隔开,如果用一个根本不存在的 id,效果就是清空标签列表
|
261
286
|
:param batch_size: 批次大小,分批次,每次提交的 id 数
|
262
287
|
:param max_workers: 并发工作数,如果为 None 或者 <= 0,则自动确定
|
288
|
+
:param app: 使用此设备的接口
|
263
289
|
:param async_: 是否异步
|
264
290
|
:param request_kwargs: 其它请求参数
|
265
291
|
"""
|
292
|
+
if app in ("", "web", "desktop", "harmony"):
|
293
|
+
method = "fs_label_set"
|
294
|
+
else:
|
295
|
+
method = "fs_label_set_app"
|
296
|
+
request_kwargs["app"] = app
|
266
297
|
return update_abstract(
|
267
298
|
client,
|
268
299
|
ids, # type: ignore
|
269
|
-
method=
|
300
|
+
method=method,
|
270
301
|
value=label,
|
271
302
|
batch_size=batch_size,
|
272
303
|
max_workers=max_workers,
|
@@ -401,6 +432,7 @@ def update_show_play_long(
|
|
401
432
|
show: bool = True,
|
402
433
|
batch_size: int = 10_000,
|
403
434
|
max_workers: None | int = None,
|
435
|
+
app: str = "web",
|
404
436
|
*,
|
405
437
|
async_: Literal[False] = False,
|
406
438
|
**request_kwargs,
|
@@ -414,6 +446,7 @@ def update_show_play_long(
|
|
414
446
|
show: bool = True,
|
415
447
|
batch_size: int = 10_000,
|
416
448
|
max_workers: None | int = None,
|
449
|
+
app: str = "web",
|
417
450
|
*,
|
418
451
|
async_: Literal[True],
|
419
452
|
**request_kwargs,
|
@@ -426,6 +459,7 @@ def update_show_play_long(
|
|
426
459
|
show: bool = True,
|
427
460
|
batch_size: int = 10_000,
|
428
461
|
max_workers: None | int = None,
|
462
|
+
app: str = "web",
|
429
463
|
*,
|
430
464
|
async_: Literal[False, True] = False,
|
431
465
|
**request_kwargs,
|
@@ -437,13 +471,19 @@ def update_show_play_long(
|
|
437
471
|
:param show: 是否显示时长
|
438
472
|
:param batch_size: 批次大小,分批次,每次提交的 id 数
|
439
473
|
:param max_workers: 并发工作数,如果为 None 或者 <= 0,则自动确定
|
474
|
+
:param app: 使用此设备的接口
|
440
475
|
:param async_: 是否异步
|
441
476
|
:param request_kwargs: 其它请求参数
|
442
477
|
"""
|
478
|
+
if app in ("", "web", "desktop", "harmony"):
|
479
|
+
method = "fs_show_play_long_set"
|
480
|
+
else:
|
481
|
+
method = "fs_show_play_long_set_app"
|
482
|
+
request_kwargs["app"] = app
|
443
483
|
return update_abstract(
|
444
484
|
client,
|
445
485
|
ids, # type: ignore
|
446
|
-
method=
|
486
|
+
method=method,
|
447
487
|
value=show,
|
448
488
|
batch_size=batch_size,
|
449
489
|
max_workers=max_workers,
|
@@ -518,6 +558,7 @@ def batch_unstar(
|
|
518
558
|
batch_size: int = 10_000,
|
519
559
|
ensure_file: None | bool = None,
|
520
560
|
max_workers: None | int = None,
|
561
|
+
app: str = "web",
|
521
562
|
*,
|
522
563
|
async_: Literal[False] = False,
|
523
564
|
**request_kwargs,
|
@@ -530,6 +571,7 @@ def batch_unstar(
|
|
530
571
|
batch_size: int = 10_000,
|
531
572
|
ensure_file: None | bool = None,
|
532
573
|
max_workers: None | int = None,
|
574
|
+
app: str = "web",
|
533
575
|
*,
|
534
576
|
async_: Literal[True],
|
535
577
|
**request_kwargs,
|
@@ -541,6 +583,7 @@ def batch_unstar(
|
|
541
583
|
batch_size: int = 10_000,
|
542
584
|
ensure_file: None | bool = None,
|
543
585
|
max_workers: None | int = None,
|
586
|
+
app: str = "web",
|
544
587
|
*,
|
545
588
|
async_: Literal[False, True] = False,
|
546
589
|
**request_kwargs,
|
@@ -556,6 +599,7 @@ def batch_unstar(
|
|
556
599
|
- None: 可以是目录或文件
|
557
600
|
|
558
601
|
:param max_workers: 并发工作数,如果为 None 或者 <= 0,则自动确定
|
602
|
+
:param app: 使用此设备的接口
|
559
603
|
:param async_: 是否异步
|
560
604
|
:param request_kwargs: 其它请求参数
|
561
605
|
"""
|
@@ -572,7 +616,7 @@ def batch_unstar(
|
|
572
616
|
client,
|
573
617
|
payload={"cid": 0, "count_folders": 1, "cur": 0, "fc_mix": 0, "offset": 0, "show_dir": 1, "star": 1},
|
574
618
|
ensure_file=ensure_file,
|
575
|
-
app=
|
619
|
+
app=app,
|
576
620
|
cooldown=0.5,
|
577
621
|
async_=async_,
|
578
622
|
**request_kwargs,
|
@@ -587,6 +631,7 @@ def batch_unstar(
|
|
587
631
|
star=False,
|
588
632
|
batch_size=batch_size,
|
589
633
|
max_workers=max_workers,
|
634
|
+
app=app,
|
590
635
|
async_=async_, # type: ignore
|
591
636
|
**request_kwargs,
|
592
637
|
)
|
p115client/tool/iterdir.py
CHANGED
@@ -8,9 +8,9 @@ __all__ = [
|
|
8
8
|
"get_ancestors_to_cid", "get_id_to_path", "get_id_to_sha1", "get_id_to_pickcode",
|
9
9
|
"iter_nodes_skim", "iter_stared_dirs_raw", "iter_stared_dirs", "ensure_attr_path",
|
10
10
|
"ensure_attr_path_by_category_get", "iterdir_raw", "iterdir", "iterdir_limited",
|
11
|
-
"iter_files_raw", "iter_files", "traverse_files", "
|
12
|
-
"
|
13
|
-
"iter_selected_nodes_by_pickcode", "iter_selected_nodes_using_category_get",
|
11
|
+
"iter_files_raw", "iter_files", "traverse_files", "iter_dirs", "iter_dupfiles",
|
12
|
+
"iter_image_files", "share_extract_payload", "share_iterdir", "share_iter_files",
|
13
|
+
"iter_selected_nodes", "iter_selected_nodes_by_pickcode", "iter_selected_nodes_using_category_get",
|
14
14
|
"iter_selected_nodes_using_edit", "iter_selected_nodes_using_star_event",
|
15
15
|
"iter_selected_dirs_using_star", "iter_files_with_dirname", "iter_files_with_path",
|
16
16
|
"iter_files_with_path_by_export_dir", "iter_parents_3_level", "iter_dir_nodes",
|
@@ -41,9 +41,9 @@ from weakref import WeakValueDictionary
|
|
41
41
|
from asynctools import async_chain, async_filter, async_map, to_list
|
42
42
|
from concurrenttools import run_as_thread, taskgroup_map, threadpool_map
|
43
43
|
from iterutils import (
|
44
|
-
bfs_gen, chunked, async_foreach, ensure_aiter, foreach,
|
45
|
-
iter_unique, run_gen_step, run_gen_step_iter, through,
|
46
|
-
with_iter_next, Yield, YieldFrom,
|
44
|
+
as_gen_step, bfs_gen, chunked, async_foreach, ensure_aiter, foreach,
|
45
|
+
flatten, iter_unique, run_gen_step, run_gen_step_iter, through,
|
46
|
+
async_through, with_iter_next, Yield, YieldFrom,
|
47
47
|
)
|
48
48
|
from iter_collect import iter_keyed_dups, SupportsLT
|
49
49
|
from orjson import loads
|
@@ -2789,6 +2789,101 @@ def traverse_files(
|
|
2789
2789
|
return run_gen_step_iter(gen_step, async_=async_)
|
2790
2790
|
|
2791
2791
|
|
2792
|
+
@overload
|
2793
|
+
def iter_dirs(
|
2794
|
+
client: str | P115Client,
|
2795
|
+
cid: int | str = 0,
|
2796
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
2797
|
+
with_pickcode: bool = False,
|
2798
|
+
max_workers: None | int = None,
|
2799
|
+
*,
|
2800
|
+
async_: Literal[False] = False,
|
2801
|
+
**request_kwargs,
|
2802
|
+
) -> Iterator[dict]:
|
2803
|
+
...
|
2804
|
+
@overload
|
2805
|
+
def iter_dirs(
|
2806
|
+
client: str | P115Client,
|
2807
|
+
cid: int | str = 0,
|
2808
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
2809
|
+
with_pickcode: bool = False,
|
2810
|
+
max_workers: None | int = None,
|
2811
|
+
*,
|
2812
|
+
async_: Literal[True],
|
2813
|
+
**request_kwargs,
|
2814
|
+
) -> AsyncIterator[dict]:
|
2815
|
+
...
|
2816
|
+
def iter_dirs(
|
2817
|
+
client: str | P115Client,
|
2818
|
+
cid: int | str = 0,
|
2819
|
+
id_to_dirnode: None | EllipsisType | dict[int, tuple[str, int] | DirNode] = None,
|
2820
|
+
with_pickcode: bool = False,
|
2821
|
+
max_workers: None | int = None,
|
2822
|
+
*,
|
2823
|
+
async_: Literal[False, True] = False,
|
2824
|
+
**request_kwargs,
|
2825
|
+
) -> Iterator[dict] | AsyncIterator[dict]:
|
2826
|
+
"""遍历目录树,获取目录信息
|
2827
|
+
|
2828
|
+
:param client: 115 客户端或 cookies
|
2829
|
+
:param cid: 目录 id(如果是 int) 或者 pickcode(如果是 str)
|
2830
|
+
:param id_to_dirnode: 字典,保存 id 到对应文件的 `DirNode(name, parent_id)` 命名元组的字典
|
2831
|
+
:param with_pickcode: 是否需要包含提取码
|
2832
|
+
:param max_workers: 最大并发数
|
2833
|
+
:param async_: 是否异步
|
2834
|
+
:param request_kwargs: 其它请求参数
|
2835
|
+
|
2836
|
+
:return: 迭代器,返回此目录内的(仅目录)文件信息
|
2837
|
+
"""
|
2838
|
+
from .download import iter_download_nodes
|
2839
|
+
if isinstance(client, str):
|
2840
|
+
client = P115Client(client, check_for_relogin=True)
|
2841
|
+
if id_to_dirnode is None:
|
2842
|
+
id_to_dirnode = ID_TO_DIRNODE_CACHE[client.user_id]
|
2843
|
+
it = iter_download_nodes(
|
2844
|
+
client,
|
2845
|
+
cid,
|
2846
|
+
files=False,
|
2847
|
+
max_workers=max_workers,
|
2848
|
+
async_=async_, # type: ignore
|
2849
|
+
**request_kwargs,
|
2850
|
+
)
|
2851
|
+
do_map: Callable = async_map if async_ else map
|
2852
|
+
def project(info: dict, /) -> dict:
|
2853
|
+
attr = {"id": int(info["fid"]), "parent_id": int(info["pid"]), "name": info["fn"]}
|
2854
|
+
if id_to_dirnode is not ...:
|
2855
|
+
id_to_dirnode[attr["id"]] = DirNode(attr["name"], attr["parent_id"])
|
2856
|
+
return attr
|
2857
|
+
it = do_map(project, it)
|
2858
|
+
if with_pickcode:
|
2859
|
+
file_skim = client.fs_file_skim
|
2860
|
+
@as_gen_step(async_=async_)
|
2861
|
+
def batch_load_pickcode(batch: Sequence[dict], /):
|
2862
|
+
resp = yield file_skim(
|
2863
|
+
(a["id"] for a in batch),
|
2864
|
+
method="POST",
|
2865
|
+
async_=async_,
|
2866
|
+
**request_kwargs,
|
2867
|
+
)
|
2868
|
+
check_response(resp)
|
2869
|
+
maps = {int(a["file_id"]): a["pick_code"] for a in resp["data"]}
|
2870
|
+
for attr in batch:
|
2871
|
+
attr["pickcode"] = maps[attr["id"]]
|
2872
|
+
return batch
|
2873
|
+
def gen_step(iterable):
|
2874
|
+
batch_map = taskgroup_map if async_ else threadpool_map
|
2875
|
+
with with_iter_next(batch_map(
|
2876
|
+
batch_load_pickcode,
|
2877
|
+
chunked(iterable, 3000),
|
2878
|
+
max_workers=max_workers,
|
2879
|
+
)) as get_next:
|
2880
|
+
while True:
|
2881
|
+
batch = yield get_next
|
2882
|
+
yield YieldFrom(batch, identity=True)
|
2883
|
+
it = run_gen_step_iter(gen_step(it), async_=async_)
|
2884
|
+
return it
|
2885
|
+
|
2886
|
+
|
2792
2887
|
@overload
|
2793
2888
|
def iter_dupfiles[K](
|
2794
2889
|
client: str | P115Client,
|
@@ -1,23 +1,23 @@
|
|
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=
|
4
|
+
p115client/client.py,sha256=PvlnygUvcLrLrZF9fYWt3NIg2ayMWee6Iw4f-v78S8Y,717352
|
5
5
|
p115client/const.py,sha256=maIZfJAiUuEnXIKc8TMAyW_UboDUJPwYpPS8LjPFp_U,4321
|
6
6
|
p115client/exception.py,sha256=Ugjr__aSlYRDYwoOz7273ngV-gFX2z-ohsJmCba8nnQ,2657
|
7
7
|
p115client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
p115client/tool/__init__.py,sha256=2YrKoAcFYOuqu2nUBoPVhxMOseAvcLE_LcnbZV11UKw,324
|
9
|
-
p115client/tool/download.py,sha256=
|
10
|
-
p115client/tool/edit.py,sha256=
|
9
|
+
p115client/tool/download.py,sha256=DneVsbryn4d47RkS62ghF5Xz8vkDq6U0n2hj1W5g4iY,61176
|
10
|
+
p115client/tool/edit.py,sha256=3hQ5J3hHQx4yNsGcWSechBYAvZRSQUxfXLXuqXiDKmk,17789
|
11
11
|
p115client/tool/export_dir.py,sha256=iMnKtnESi8HKvW9WhIvOdEoMXSBpAnhFlGeyKXHpQbE,24545
|
12
12
|
p115client/tool/fs_files.py,sha256=hkezLKrtTAGPDkPxwq6jMrm8s2-unHZQBR7cDvh41qs,16027
|
13
|
-
p115client/tool/iterdir.py,sha256=
|
13
|
+
p115client/tool/iterdir.py,sha256=T6bsD8A896nHgVxKYu2dkIo-5Az2svL4iLm2uHQWyHg,187517
|
14
14
|
p115client/tool/life.py,sha256=SJ1dAvRYCWTUz1gPrCWv-_G1Rq5yPfxDgY7KT-2UP4A,17528
|
15
15
|
p115client/tool/pool.py,sha256=vM5ItMxELtT7_bvbmdhwWj81rQ0zyaj3uPMny4KDw_E,9757
|
16
16
|
p115client/tool/request.py,sha256=SWsezW9EYZGS3R-TbZxMG-8bN3YWJ0-GzgvKlvRBSCM,7042
|
17
17
|
p115client/tool/upload.py,sha256=qK1OQYxP-Faq2eMDhc5sBXJiSr8m8EZ_gb0O_iA2TrI,15915
|
18
18
|
p115client/tool/xys.py,sha256=n89n9OLBXx6t20L61wJgfrP6V4jW3sHgyaQNBLdUwUQ,3578
|
19
19
|
p115client/type.py,sha256=e4g9URQBE23XN2dGomldj8wC6NlDWBBSVC5Bmd8giBc,5993
|
20
|
-
p115client-0.0.5.8.
|
21
|
-
p115client-0.0.5.8.
|
22
|
-
p115client-0.0.5.8.
|
23
|
-
p115client-0.0.5.8.
|
20
|
+
p115client-0.0.5.8.6.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
21
|
+
p115client-0.0.5.8.6.dist-info/METADATA,sha256=iYXxUpy5PpP618SQZ4utGQSwXWPw2wZ3WVGqJM_wZBc,8233
|
22
|
+
p115client-0.0.5.8.6.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
23
|
+
p115client-0.0.5.8.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|