p115client 0.0.5.11.7.1__py3-none-any.whl → 0.0.5.11.8__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 +315 -163
- p115client/exception.py +9 -4
- p115client/tool/attr.py +4 -4
- {p115client-0.0.5.11.7.1.dist-info → p115client-0.0.5.11.8.dist-info}/METADATA +1 -1
- {p115client-0.0.5.11.7.1.dist-info → p115client-0.0.5.11.8.dist-info}/RECORD +7 -7
- {p115client-0.0.5.11.7.1.dist-info → p115client-0.0.5.11.8.dist-info}/LICENSE +0 -0
- {p115client-0.0.5.11.7.1.dist-info → p115client-0.0.5.11.8.dist-info}/WHEEL +0 -0
p115client/client.py
CHANGED
@@ -65,9 +65,9 @@ from yarl import URL
|
|
65
65
|
|
66
66
|
from .const import CLASS_TO_TYPE, CLIENT_API_MAP, SSOENT_TO_APP, SUFFIX_TO_TYPE, errno
|
67
67
|
from .exception import (
|
68
|
-
AuthenticationError, BusyOSError, DataError, LoginError,
|
69
|
-
NotSupportedError, P115OSError, OperationalError,
|
70
|
-
P115FileNotFoundError, P115IsADirectoryError,
|
68
|
+
AccessTokenError, AuthenticationError, BusyOSError, DataError, LoginError,
|
69
|
+
OpenAppAuthLimitExceeded, NotSupportedError, P115OSError, OperationalError,
|
70
|
+
P115Warning, P115FileExistsError, P115FileNotFoundError, P115IsADirectoryError,
|
71
71
|
)
|
72
72
|
from .type import RequestKeywords, MultipartResumeData, P115Cookies, P115URL
|
73
73
|
from ._upload import buffer_length, make_dataiter, oss_upload, oss_multipart_upload
|
@@ -220,6 +220,16 @@ def complete_lixian_api(
|
|
220
220
|
return complete_api(path, base, base_url=base_url)
|
221
221
|
|
222
222
|
|
223
|
+
def try_parse_int(s: int | str, /):
|
224
|
+
if not isinstance(s, str):
|
225
|
+
return s
|
226
|
+
if s == "0":
|
227
|
+
return 0
|
228
|
+
if s.startswith("0") or s.strip(digits):
|
229
|
+
return s
|
230
|
+
return int(s)
|
231
|
+
|
232
|
+
|
223
233
|
def json_loads(content: Buffer, /):
|
224
234
|
try:
|
225
235
|
if isinstance(content, (bytes, bytearray, memoryview)):
|
@@ -232,7 +242,7 @@ def json_loads(content: Buffer, /):
|
|
232
242
|
raise DataError(errno.ENODATA, content) from e
|
233
243
|
|
234
244
|
|
235
|
-
def default_parse(
|
245
|
+
def default_parse(_, content: Buffer, /):
|
236
246
|
if not isinstance(content, (bytes, bytearray, memoryview)):
|
237
247
|
content = memoryview(content)
|
238
248
|
if content and content[0] + content[-1] not in (b"{}", b"[]", b'""'):
|
@@ -532,16 +542,16 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
|
|
532
542
|
raise OpenAppAuthLimitExceeded(errno.EDQUOT, resp)
|
533
543
|
# {"state": 0, "errno": 40140123, "error": "access_token 格式错误(防篡改)"}
|
534
544
|
case 40140123:
|
535
|
-
raise
|
545
|
+
raise AccessTokenError(errno.EINVAL, resp)
|
536
546
|
# {"state": 0, "errno": 40140124, "error": "access_token 签名校验失败(防篡改)"}
|
537
547
|
case 40140124:
|
538
|
-
raise
|
548
|
+
raise AccessTokenError(errno.EINVAL, resp)
|
539
549
|
# {"state": 0, "errno": 40140125, "error": "access_token 无效(已过期或者已解除授权)"}
|
540
550
|
case 40140125:
|
541
|
-
raise
|
551
|
+
raise AccessTokenError(errno.EINVAL, resp)
|
542
552
|
# {"state": 0, "errno": 40140126, "error": "access_token 校验失败(防篡改)"}
|
543
553
|
case 40140126:
|
544
|
-
raise
|
554
|
+
raise AccessTokenError(errno.EINVAL, resp)
|
545
555
|
# {"state": 0, "errno": 40140127, "error": "response_type 错误"}
|
546
556
|
case 40140127:
|
547
557
|
raise OperationalError(errno.EINVAL, resp)
|
@@ -685,40 +695,36 @@ def normalize_attr_web[D: dict[str, Any]](
|
|
685
695
|
attr["has_desc"] = bool(val)
|
686
696
|
for key, name in (
|
687
697
|
("aid", "area_id"),
|
698
|
+
("audio_play_long", "audio_play_long"),
|
699
|
+
("c", "violated"),
|
700
|
+
("c", "is_collect"),
|
701
|
+
("cc", "cover"),
|
702
|
+
("class", "class"),
|
703
|
+
("current_time", "current_time"),
|
704
|
+
#("d", "has_desc"),
|
705
|
+
("dp", "dir_path"),
|
706
|
+
("fl", "labels"),
|
688
707
|
("hdf", "hidden"),
|
689
708
|
("hdf", "is_private"),
|
690
|
-
("issct", "is_shortcut"),
|
691
|
-
("ispl", "show_play_long"),
|
692
709
|
("is_top", "is_top"),
|
710
|
+
("ispl", "show_play_long"),
|
711
|
+
("issct", "is_shortcut"),
|
693
712
|
("iv", "is_video"),
|
713
|
+
("last_time", "last_time"),
|
694
714
|
("m", "star"),
|
695
715
|
("m", "is_mark"),
|
696
|
-
("c", "violated"),
|
697
|
-
("c", "is_collect"),
|
698
|
-
("sh", "is_share"),
|
699
|
-
("score", "score"),
|
700
|
-
#("d", "has_desc"),
|
701
|
-
#("p", "has_pass"),
|
702
|
-
):
|
703
|
-
if key in info:
|
704
|
-
attr[name] = int(info[key] or 0)
|
705
|
-
for key, name in (
|
706
|
-
("fl", "labels"),
|
707
|
-
("dp", "dir_path"),
|
708
|
-
("style", "style"),
|
709
716
|
("ns", "name_show"),
|
710
|
-
("
|
711
|
-
("sta", "status"),
|
712
|
-
("class", "class"),
|
713
|
-
("u", "thumb"),
|
717
|
+
#("p", "has_pass"),
|
714
718
|
("play_long", "play_long"),
|
715
|
-
("audio_play_long", "audio_play_long"),
|
716
|
-
("current_time", "current_time"),
|
717
|
-
("last_time", "last_time"),
|
718
719
|
("played_end", "played_end"),
|
720
|
+
("score", "score"),
|
721
|
+
("sh", "is_share"),
|
722
|
+
("sta", "status"),
|
723
|
+
("style", "style"),
|
724
|
+
("u", "thumb"),
|
719
725
|
):
|
720
726
|
if key in info:
|
721
|
-
attr[name] = info[key]
|
727
|
+
attr[name] = try_parse_int(info[key])
|
722
728
|
if vdi := info.get("vdi"):
|
723
729
|
attr["defination"] = vdi
|
724
730
|
match vdi:
|
@@ -821,47 +827,43 @@ def normalize_attr_app[D: dict[str, Any]](
|
|
821
827
|
if "uet" in info: # utime
|
822
828
|
attr["utime"] = int(info["uet"])
|
823
829
|
for key, name in (
|
824
|
-
("aid", "area_id"),
|
825
|
-
("
|
826
|
-
("
|
827
|
-
("
|
828
|
-
("
|
829
|
-
("
|
830
|
-
("
|
831
|
-
("
|
832
|
-
("
|
833
|
-
("
|
834
|
-
("
|
835
|
-
("
|
836
|
-
("
|
837
|
-
("
|
838
|
-
("ic", "
|
839
|
-
("
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
("
|
845
|
-
("
|
846
|
-
("
|
847
|
-
("
|
848
|
-
("
|
849
|
-
("
|
850
|
-
("
|
851
|
-
("
|
852
|
-
("
|
853
|
-
("
|
854
|
-
("
|
855
|
-
("
|
856
|
-
("
|
857
|
-
("
|
858
|
-
("current_time", "current_time"),
|
859
|
-
("last_time", "last_time"),
|
860
|
-
("played_end", "played_end"),
|
861
|
-
("uo", "source_url"),
|
830
|
+
("aid", "area_id"), # 域 id,表示文件的状态:1:正常 7:删除(回收站) 120:彻底删除
|
831
|
+
("audio_play_long", "audio_play_long"), # 音频长度
|
832
|
+
("current_time", "current_time"), # 视频当前播放位置(从头开始到此为第 `current_time` 秒)
|
833
|
+
("d_img", "d_img"), # 目录封面
|
834
|
+
("def", "defination"), # 视频清晰度:1:标清 2:高清 3:超清 4:1080P 5:4k 100:原画
|
835
|
+
("def2", "defination2"), # 视频清晰度:1:标清 2:高清 3:超清 4:1080P 5:4k 100:原画
|
836
|
+
("fatr", "audio_play_long"), # 音频长度
|
837
|
+
("fco", "cover"), # 文件夹封面
|
838
|
+
("fco", "folder_cover"), # 文件夹封面
|
839
|
+
("fdesc", "desc"), # 文件备注
|
840
|
+
("fl", "labels"), # 文件标签,得到 1 个字典列表
|
841
|
+
("flabel", "fflabel"), # 文件标签(一般为空)
|
842
|
+
("fta", "status"), # 文件状态:0/2:未上传完成,1:已上传完成
|
843
|
+
("ftype", "file_type"), # 文件类型代码
|
844
|
+
("ic", "violated"), # 是否违规
|
845
|
+
("ic", "is_collect"), # 是否违规
|
846
|
+
("is_top", "is_top"), # 是否置顶
|
847
|
+
("ism", "star"), # 是否星标
|
848
|
+
("ism", "is_mark"), # 是否星标
|
849
|
+
("isp", "hidden"), # 是否加密隐藏(隐藏模式中显示)
|
850
|
+
("isp", "is_private"), # 是否加密隐藏(隐藏模式中显示)
|
851
|
+
("ispl", "show_play_long"), # 是否统计文件夹下视频时长
|
852
|
+
("iss", "is_share"), # 是否共享
|
853
|
+
("issct", "is_shortcut"), # 是否在快捷入口
|
854
|
+
("isv", "is_video"), # 是否为视频
|
855
|
+
("last_time", "last_time"), # 视频上次播放时间戳(秒)
|
856
|
+
("muc", "cover"), # 封面
|
857
|
+
("muc", "music_cover"), # 音乐封面
|
858
|
+
("multitrack", "multitrack"), # 音轨数量
|
859
|
+
("play_long", "play_long"), # 音视频时长
|
860
|
+
("played_end", "played_end"), # 是否播放完成
|
861
|
+
("unzip_status", "unzip_status"), # 解压状态:0(或无值):未解压或已完成 1:解压中
|
862
|
+
("uo", "source_url"), # 原图地址
|
863
|
+
("v_img", "video_img_url"), # 图片封面
|
862
864
|
):
|
863
865
|
if key in info:
|
864
|
-
attr[name] = info[key]
|
866
|
+
attr[name] = try_parse_int(info[key])
|
865
867
|
if is_directory:
|
866
868
|
attr["type"] = 0
|
867
869
|
elif (thumb := info.get("thumb")) and thumb.startswith("?"):
|
@@ -983,44 +985,60 @@ def normalize_attr_app2[D: dict[str, Any]](
|
|
983
985
|
if "fl" in info:
|
984
986
|
attr["labels"] = info["fl"]
|
985
987
|
for key, name in (
|
986
|
-
("
|
987
|
-
("has_desc", "has_desc"),
|
988
|
-
("has_pass", "has_pass"),
|
988
|
+
("is_collect", "violated"),
|
989
989
|
("is_mark", "star"),
|
990
|
-
("is_mark", "is_mark"),
|
991
|
-
("is_top", "is_top"),
|
992
990
|
("is_private", "hidden"),
|
993
|
-
("is_private", "is_private"),
|
994
|
-
("show_play_long", "show_play_long"),
|
995
|
-
("is_share", "is_share"),
|
996
|
-
("is_video", "is_video"),
|
997
|
-
("is_collect", "violated"),
|
998
|
-
("is_collect", "is_collect"),
|
999
|
-
("can_delete", "can_delete"),
|
1000
|
-
("file_category", "file_category"),
|
1001
991
|
):
|
1002
992
|
if key in info:
|
1003
993
|
attr[name] = int(info[key] or 0)
|
1004
994
|
for name in (
|
1005
|
-
"
|
1006
|
-
"
|
1007
|
-
"
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
"
|
1013
|
-
"
|
995
|
+
"area_id",
|
996
|
+
"can_delete",
|
997
|
+
"cate_mark",
|
998
|
+
"category_file_count",
|
999
|
+
"category_order",
|
1000
|
+
"current_time",
|
1001
|
+
"d_img",
|
1002
|
+
"definition",
|
1003
|
+
"definition2",
|
1004
|
+
"file_answer",
|
1005
|
+
"file_category",
|
1006
|
+
"file_eda",
|
1007
|
+
"file_question",
|
1008
|
+
"file_sort",
|
1009
|
+
"file_status",
|
1010
|
+
"has_desc",
|
1011
|
+
"has_pass",
|
1012
|
+
"is_collect",
|
1013
|
+
"is_mark",
|
1014
|
+
"is_private",
|
1015
|
+
"is_share",
|
1016
|
+
"is_top",
|
1017
|
+
"is_video",
|
1018
|
+
"last_time",
|
1019
|
+
"password",
|
1020
|
+
"pick_expire",
|
1021
|
+
"pick_time",
|
1022
|
+
"play_long",
|
1023
|
+
"play_url",
|
1024
|
+
"played_end",
|
1025
|
+
"show_play_long",
|
1026
|
+
"video_img_url",
|
1014
1027
|
):
|
1015
1028
|
if name in info:
|
1016
|
-
attr[name] = info[name]
|
1029
|
+
attr[name] = try_parse_int(info[name])
|
1017
1030
|
if is_directory:
|
1018
1031
|
attr["type"] = 0
|
1019
1032
|
elif "thumb_url" in info:
|
1020
1033
|
attr["type"] = 2
|
1021
1034
|
elif "music_cover" in info or "play_url" in info:
|
1022
1035
|
attr["type"] = 3
|
1023
|
-
elif
|
1036
|
+
elif (
|
1037
|
+
info.get("is_video") or
|
1038
|
+
"definition" in info or
|
1039
|
+
"definition2" in info or
|
1040
|
+
"video_img_url" in info
|
1041
|
+
):
|
1024
1042
|
attr["type"] = 4
|
1025
1043
|
elif type_ := SUFFIX_TO_TYPE.get(splitext(attr["name"])[1].lower()):
|
1026
1044
|
attr["type"] = type_
|
@@ -2051,6 +2069,34 @@ class ClientRequestMixin:
|
|
2051
2069
|
.. note::
|
2052
2070
|
code_challenge 默认用的字符串为 64 个 0,hash 算法为 md5
|
2053
2071
|
|
2072
|
+
.. tip::
|
2073
|
+
如果仅仅想要检查 AppID 是否有效,可以用如下的代码:
|
2074
|
+
|
2075
|
+
.. code:: python
|
2076
|
+
|
2077
|
+
from p115client import P115Client
|
2078
|
+
|
2079
|
+
app_id = 100195123
|
2080
|
+
response = P115Client.login_qrcode_token_open(app_id)
|
2081
|
+
if response["code"]:
|
2082
|
+
print("无效 AppID:", app_id, "因为:", response["error"])
|
2083
|
+
else:
|
2084
|
+
print("有效 AppID:", app_id)
|
2085
|
+
|
2086
|
+
.. tip::
|
2087
|
+
如果想要罗列出所有可用的 AppID,可以用如下的代码:
|
2088
|
+
|
2089
|
+
.. code:: python
|
2090
|
+
|
2091
|
+
from itertools import count
|
2092
|
+
from p115client import P115Client
|
2093
|
+
|
2094
|
+
get_qrcode_token = P115Client.login_qrcode_token_open
|
2095
|
+
for app_id in count(100195123, 2):
|
2096
|
+
response = get_qrcode_token(app_id)
|
2097
|
+
if not response["code"]:
|
2098
|
+
print(app_id)
|
2099
|
+
|
2054
2100
|
:payload:
|
2055
2101
|
- client_id: int | str 💡 AppID
|
2056
2102
|
- code_challenge: str = <default> 💡 PKCE 相关参数,计算方式如下
|
@@ -2329,7 +2375,7 @@ class ClientRequestMixin:
|
|
2329
2375
|
def login_with_app_id(
|
2330
2376
|
cls,
|
2331
2377
|
/,
|
2332
|
-
app_id: int | str,
|
2378
|
+
app_id: int | str = 100195123,
|
2333
2379
|
console_qrcode: bool = True,
|
2334
2380
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
2335
2381
|
*,
|
@@ -2342,7 +2388,7 @@ class ClientRequestMixin:
|
|
2342
2388
|
def login_with_app_id(
|
2343
2389
|
cls,
|
2344
2390
|
/,
|
2345
|
-
app_id: int | str,
|
2391
|
+
app_id: int | str = 100195123,
|
2346
2392
|
console_qrcode: bool = True,
|
2347
2393
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
2348
2394
|
*,
|
@@ -2354,7 +2400,7 @@ class ClientRequestMixin:
|
|
2354
2400
|
def login_with_app_id(
|
2355
2401
|
cls,
|
2356
2402
|
/,
|
2357
|
-
app_id: int | str,
|
2403
|
+
app_id: int | str = 100195123,
|
2358
2404
|
console_qrcode: bool = True,
|
2359
2405
|
base_url: str | Callable[[], str] = "https://qrcodeapi.115.com",
|
2360
2406
|
*,
|
@@ -3054,7 +3100,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3054
3100
|
/,
|
3055
3101
|
async_: Literal[False] = False,
|
3056
3102
|
**request_kwargs,
|
3057
|
-
) ->
|
3103
|
+
) -> dict:
|
3058
3104
|
...
|
3059
3105
|
@overload
|
3060
3106
|
def refresh_access_token(
|
@@ -3062,27 +3108,36 @@ class P115OpenClient(ClientRequestMixin):
|
|
3062
3108
|
/,
|
3063
3109
|
async_: Literal[True],
|
3064
3110
|
**request_kwargs,
|
3065
|
-
) -> Coroutine[Any, Any,
|
3111
|
+
) -> Coroutine[Any, Any, dict]:
|
3066
3112
|
...
|
3067
3113
|
def refresh_access_token(
|
3068
3114
|
self,
|
3069
3115
|
/,
|
3070
3116
|
async_: Literal[False, True] = False,
|
3071
3117
|
**request_kwargs,
|
3072
|
-
) ->
|
3118
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3073
3119
|
"""更新 access_token 和 refresh_token (⚠️ 目前是 7200 秒内就要求刷新一次)
|
3074
3120
|
"""
|
3075
3121
|
def gen_step():
|
3076
|
-
|
3077
|
-
self.
|
3078
|
-
|
3079
|
-
|
3080
|
-
|
3122
|
+
if refresh_token := getattr(self, "refresh_token", ""):
|
3123
|
+
resp = yield self.login_refresh_token_open(
|
3124
|
+
refresh_token,
|
3125
|
+
async_=async_,
|
3126
|
+
**request_kwargs,
|
3127
|
+
)
|
3128
|
+
elif hasattr(self, "login_with_open") and (app_id := getattr(self, "app_id", 0)):
|
3129
|
+
resp = yield self.login_with_open(
|
3130
|
+
app_id,
|
3131
|
+
async_=async_,
|
3132
|
+
**request_kwargs,
|
3133
|
+
)
|
3134
|
+
else:
|
3135
|
+
raise RuntimeError("no `refresh_token` or `app_id` provided")
|
3081
3136
|
check_response(resp)
|
3082
3137
|
data = resp["data"]
|
3083
3138
|
self.refresh_token = data["refresh_token"]
|
3084
|
-
|
3085
|
-
return
|
3139
|
+
self.access_token = data["access_token"]
|
3140
|
+
return data
|
3086
3141
|
return run_gen_step(gen_step, may_call=False, async_=async_)
|
3087
3142
|
|
3088
3143
|
@overload
|
@@ -3388,7 +3443,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3388
3443
|
https://www.yuque.com/115yun/open/kz9ft9a7s57ep868
|
3389
3444
|
|
3390
3445
|
:payload:
|
3391
|
-
- cid: int | str = 0 💡 目录 id
|
3446
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
3392
3447
|
- limit: int = 32 💡 分页大小,最大值不一定,看数据量,7,000 应该总是安全的,10,000 有可能报错,但有时也可以 20,000 而成功
|
3393
3448
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
3394
3449
|
|
@@ -3397,7 +3452,12 @@ class P115OpenClient(ClientRequestMixin):
|
|
3397
3452
|
- code: int | str = <default>
|
3398
3453
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
3399
3454
|
- cur: 0 | 1 = <default> 💡 是否只显示当前目录
|
3400
|
-
- custom_order: 0 | 1 | 2 = <default> 💡
|
3455
|
+
- custom_order: 0 | 1 | 2 = <default> 💡 是否使用记忆排序。如果指定了 "asc"、"fc_mix"、"o" 中其一,则此参数会被自动设置为 2
|
3456
|
+
|
3457
|
+
- 0: 使用记忆排序(自定义排序失效)
|
3458
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
3459
|
+
- 2: 自定义排序(非目录置顶)
|
3460
|
+
|
3401
3461
|
- date: str = <default> 💡 筛选日期
|
3402
3462
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
3403
3463
|
- fields: str = <default>
|
@@ -3423,12 +3483,12 @@ class P115OpenClient(ClientRequestMixin):
|
|
3423
3483
|
- r_all: 0 | 1 = <default>
|
3424
3484
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
3425
3485
|
- scid: int | str = <default>
|
3426
|
-
- show_dir: 0 | 1 = 1 💡
|
3486
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
3427
3487
|
- snap: 0 | 1 = <default>
|
3428
3488
|
- source: str = <default>
|
3429
3489
|
- sys_dir: int | str = <default> 💡 系统通用目录
|
3430
3490
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
3431
|
-
- stdir: 0 | 1 = <default>
|
3491
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
3432
3492
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
3433
3493
|
- type: int = <default> 💡 文件类型
|
3434
3494
|
|
@@ -3500,8 +3560,11 @@ class P115OpenClient(ClientRequestMixin):
|
|
3500
3560
|
|
3501
3561
|
GET https://proapi.115.com/open/folder/get_info
|
3502
3562
|
|
3563
|
+
.. note::
|
3564
|
+
支持 GET 和 POST 方法。`file_id` 和 `path` 需必传一个
|
3565
|
+
|
3503
3566
|
.. hint::
|
3504
|
-
|
3567
|
+
部分相当于 `P115Client.fs_category_get_app`
|
3505
3568
|
|
3506
3569
|
.. admonition:: Reference
|
3507
3570
|
|
@@ -3509,11 +3572,24 @@ class P115OpenClient(ClientRequestMixin):
|
|
3509
3572
|
|
3510
3573
|
:payload:
|
3511
3574
|
- file_id: int | str 💡 文件或目录的 id
|
3575
|
+
- path: str = <default> 💡 文件或目录的路径。分隔符支持 / 和 > 两种符号,最前面需分隔符开头,以分隔符分隔目录层级
|
3512
3576
|
"""
|
3513
3577
|
api = complete_proapi("/open/folder/get_info", base_url)
|
3514
|
-
if isinstance(payload,
|
3578
|
+
if isinstance(payload, int):
|
3515
3579
|
payload = {"file_id": payload}
|
3516
|
-
|
3580
|
+
elif isinstance(payload, str):
|
3581
|
+
if payload.startswith("0") or payload.strip(digits):
|
3582
|
+
if not payload.startswith(("/", "<")):
|
3583
|
+
payload = "/" + payload
|
3584
|
+
payload = {"path": payload}
|
3585
|
+
else:
|
3586
|
+
payload = {"file_id": payload}
|
3587
|
+
method = request_kwargs.get("method")
|
3588
|
+
if method and method.upper() == "POST":
|
3589
|
+
request_kwargs["data"] = payload
|
3590
|
+
else:
|
3591
|
+
request_kwargs["params"] = payload
|
3592
|
+
return self.request(url=api, async_=async_, **request_kwargs)
|
3517
3593
|
|
3518
3594
|
@overload
|
3519
3595
|
def fs_mkdir(
|
@@ -3694,7 +3770,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3694
3770
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
3695
3771
|
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
3696
3772
|
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
3697
|
-
- show_dir: 0 | 1 = 1
|
3773
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
3698
3774
|
- source: str = <default>
|
3699
3775
|
- star: 0 | 1 = <default>
|
3700
3776
|
- suffix: str = <default>
|
@@ -5287,7 +5363,7 @@ class P115Client(P115OpenClient):
|
|
5287
5363
|
"""115 的客户端对象
|
5288
5364
|
|
5289
5365
|
.. note::
|
5290
|
-
目前允许 1 个用户同时登录多个开放平台应用(用 AppID
|
5366
|
+
目前允许 1 个用户同时登录多个开放平台应用(用 AppID 区别),也允许多次登录同 1 个应用
|
5291
5367
|
|
5292
5368
|
目前不允许短时间内再次用 `refresh_token` 刷新 `access_token`,但你可以用登录的方式再次授权登录以获取 `access_token`,即可不受频率限制
|
5293
5369
|
|
@@ -5953,11 +6029,59 @@ class P115Client(P115OpenClient):
|
|
5953
6029
|
return uid
|
5954
6030
|
return run_gen_step(gen_step, may_call=False, async_=async_)
|
5955
6031
|
|
6032
|
+
@overload
|
6033
|
+
def login_info_open(
|
6034
|
+
self,
|
6035
|
+
/,
|
6036
|
+
app_id: int | str = 100195123,
|
6037
|
+
*,
|
6038
|
+
async_: Literal[False] = False,
|
6039
|
+
**request_kwargs,
|
6040
|
+
) -> dict:
|
6041
|
+
...
|
6042
|
+
@overload
|
6043
|
+
def login_info_open(
|
6044
|
+
self,
|
6045
|
+
/,
|
6046
|
+
app_id: int | str = 100195123,
|
6047
|
+
*,
|
6048
|
+
async_: Literal[True],
|
6049
|
+
**request_kwargs,
|
6050
|
+
) -> Coroutine[Any, Any, dict]:
|
6051
|
+
...
|
6052
|
+
def login_info_open(
|
6053
|
+
self,
|
6054
|
+
/,
|
6055
|
+
app_id: int | str = 100195123,
|
6056
|
+
*,
|
6057
|
+
async_: Literal[False, True] = False,
|
6058
|
+
**request_kwargs,
|
6059
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
6060
|
+
"""获取某个开放接口应用的信息(目前可获得名称和头像)
|
6061
|
+
|
6062
|
+
:param app_id: AppID
|
6063
|
+
:param async_: 是否异步
|
6064
|
+
:param request_kwargs: 其它请求参数
|
6065
|
+
|
6066
|
+
:return: 接口返回值
|
6067
|
+
"""
|
6068
|
+
def gen_step():
|
6069
|
+
resp = yield self.login_qrcode_token_open(app_id, async_=async_, **request_kwargs)
|
6070
|
+
login_uid = check_response(resp)["data"]["uid"]
|
6071
|
+
resp = yield self.login_qrcode_scan(login_uid, async_=async_, **request_kwargs)
|
6072
|
+
check_response(resp)
|
6073
|
+
tip_txt = resp["data"]["tip_txt"]
|
6074
|
+
return {
|
6075
|
+
"name": tip_txt[:tip_txt.rfind("已经过")],
|
6076
|
+
"icon": resp["data"]["icon"],
|
6077
|
+
}
|
6078
|
+
return run_gen_step(gen_step, may_call=False, async_=async_)
|
6079
|
+
|
5956
6080
|
@overload
|
5957
6081
|
def login_with_open(
|
5958
6082
|
self,
|
5959
6083
|
/,
|
5960
|
-
app_id: int | str,
|
6084
|
+
app_id: int | str = 100195123,
|
5961
6085
|
*,
|
5962
6086
|
show_warning: bool = False,
|
5963
6087
|
async_: Literal[False] = False,
|
@@ -5968,7 +6092,7 @@ class P115Client(P115OpenClient):
|
|
5968
6092
|
def login_with_open(
|
5969
6093
|
self,
|
5970
6094
|
/,
|
5971
|
-
app_id: int | str,
|
6095
|
+
app_id: int | str = 100195123,
|
5972
6096
|
*,
|
5973
6097
|
show_warning: bool = False,
|
5974
6098
|
async_: Literal[True],
|
@@ -5978,7 +6102,7 @@ class P115Client(P115OpenClient):
|
|
5978
6102
|
def login_with_open(
|
5979
6103
|
self,
|
5980
6104
|
/,
|
5981
|
-
app_id: int | str,
|
6105
|
+
app_id: int | str = 100195123,
|
5982
6106
|
*,
|
5983
6107
|
show_warning: bool = False,
|
5984
6108
|
async_: Literal[False, True] = False,
|
@@ -6153,7 +6277,7 @@ class P115Client(P115OpenClient):
|
|
6153
6277
|
def login_another_open(
|
6154
6278
|
self,
|
6155
6279
|
/,
|
6156
|
-
app_id: int | str,
|
6280
|
+
app_id: int | str = 100195123,
|
6157
6281
|
*,
|
6158
6282
|
replace: Literal[True] | Self,
|
6159
6283
|
show_warning: bool = False,
|
@@ -6165,7 +6289,7 @@ class P115Client(P115OpenClient):
|
|
6165
6289
|
def login_another_open(
|
6166
6290
|
self,
|
6167
6291
|
/,
|
6168
|
-
app_id: int | str,
|
6292
|
+
app_id: int | str = 100195123,
|
6169
6293
|
*,
|
6170
6294
|
replace: Literal[True] | Self,
|
6171
6295
|
show_warning: bool = False,
|
@@ -6177,7 +6301,7 @@ class P115Client(P115OpenClient):
|
|
6177
6301
|
def login_another_open(
|
6178
6302
|
self,
|
6179
6303
|
/,
|
6180
|
-
app_id: int | str,
|
6304
|
+
app_id: int | str = 100195123,
|
6181
6305
|
*,
|
6182
6306
|
replace: Literal[False] = False,
|
6183
6307
|
show_warning: bool = False,
|
@@ -6189,7 +6313,7 @@ class P115Client(P115OpenClient):
|
|
6189
6313
|
def login_another_open(
|
6190
6314
|
self,
|
6191
6315
|
/,
|
6192
|
-
app_id: int | str,
|
6316
|
+
app_id: int | str = 100195123,
|
6193
6317
|
*,
|
6194
6318
|
replace: Literal[False] = False,
|
6195
6319
|
show_warning: bool = False,
|
@@ -6200,7 +6324,7 @@ class P115Client(P115OpenClient):
|
|
6200
6324
|
def login_another_open(
|
6201
6325
|
self,
|
6202
6326
|
/,
|
6203
|
-
app_id: int | str,
|
6327
|
+
app_id: int | str = 100195123,
|
6204
6328
|
*,
|
6205
6329
|
replace: bool | Self = False,
|
6206
6330
|
show_warning: bool = False,
|
@@ -6571,8 +6695,16 @@ class P115Client(P115OpenClient):
|
|
6571
6695
|
method=method,
|
6572
6696
|
**request_kwargs,
|
6573
6697
|
)
|
6698
|
+
if (
|
6699
|
+
is_open_api and
|
6700
|
+
need_to_check and
|
6701
|
+
isinstance(resp, dict) and
|
6702
|
+
resp.get("code") in (40140123, 40140124, 40140125, 40140126)
|
6703
|
+
):
|
6704
|
+
check_response(resp)
|
6574
6705
|
except BaseException as e:
|
6575
6706
|
is_auth_error = isinstance(e, (AuthenticationError, LoginError))
|
6707
|
+
not_access_token_error = not isinstance(e, AccessTokenError)
|
6576
6708
|
if (
|
6577
6709
|
cert_headers is not None and
|
6578
6710
|
revert_cert_headers is not None and
|
@@ -6582,26 +6714,25 @@ class P115Client(P115OpenClient):
|
|
6582
6714
|
yield revert_cert_headers(cert_headers)
|
6583
6715
|
if not need_to_check:
|
6584
6716
|
raise
|
6585
|
-
|
6586
|
-
|
6587
|
-
|
6717
|
+
if not_access_token_error:
|
6718
|
+
res = yield cast(Callable, check_for_relogin)(e)
|
6719
|
+
if not res if isinstance(res, bool) else res != 405:
|
6720
|
+
raise
|
6588
6721
|
if fetch_cert_headers is not None:
|
6589
6722
|
cert_headers = yield fetch_cert_headers()
|
6590
6723
|
headers.update(cert_headers)
|
6591
6724
|
elif is_open_api:
|
6592
6725
|
yield lock.acquire()
|
6593
6726
|
try:
|
6594
|
-
|
6595
|
-
|
6596
|
-
|
6597
|
-
|
6598
|
-
|
6599
|
-
|
6600
|
-
|
6601
|
-
|
6602
|
-
|
6603
|
-
)
|
6604
|
-
warn(f"relogin to refresh token: {app_id=}", category=P115Warning)
|
6727
|
+
access_token = self.access_token
|
6728
|
+
if cert.capitalize().removeprefix("Bearer ") == access_token:
|
6729
|
+
if i or is_auth_error or not_access_token_error:
|
6730
|
+
raise
|
6731
|
+
warn(f"relogin to refresh token", category=P115Warning)
|
6732
|
+
yield self.refresh_access_token(async_=async_)
|
6733
|
+
cert = headers["authorization"] = "Bearer " + self.access_token
|
6734
|
+
else:
|
6735
|
+
cert = headers["authorization"] = "Bearer " + access_token
|
6605
6736
|
finally:
|
6606
6737
|
lock.release()
|
6607
6738
|
else:
|
@@ -6625,8 +6756,9 @@ class P115Client(P115OpenClient):
|
|
6625
6756
|
replace=True,
|
6626
6757
|
async_=async_, # type: ignore
|
6627
6758
|
)
|
6759
|
+
cert = headers["cookie"] = self.cookies_str
|
6628
6760
|
else:
|
6629
|
-
headers["cookie"] = cookies_new
|
6761
|
+
cert = headers["cookie"] = cookies_new
|
6630
6762
|
finally:
|
6631
6763
|
lock.release()
|
6632
6764
|
else:
|
@@ -10222,7 +10354,7 @@ class P115Client(P115OpenClient):
|
|
10222
10354
|
- 7: 其它
|
10223
10355
|
|
10224
10356
|
:payload:
|
10225
|
-
- cid: int | str = 0 💡 目录 id
|
10357
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10226
10358
|
- limit: int = 32 💡 分页大小,目前最大值是 1,150,以前是没限制的
|
10227
10359
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10228
10360
|
|
@@ -10232,6 +10364,11 @@ class P115Client(P115OpenClient):
|
|
10232
10364
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10233
10365
|
- cur: 0 | 1 = <default> 💡 是否只搜索当前目录
|
10234
10366
|
- custom_order: 0 | 1 = <default> 💡 启用自定义排序,如果指定了 "asc"、"fc_mix"、"o" 中其一,则此参数会被自动设置为 1
|
10367
|
+
|
10368
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10369
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10370
|
+
- 2: 自定义排序(非目录置顶)
|
10371
|
+
|
10235
10372
|
- date: str = <default> 💡 筛选日期
|
10236
10373
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10237
10374
|
- fields: str = <default>
|
@@ -10256,12 +10393,12 @@ class P115Client(P115OpenClient):
|
|
10256
10393
|
- r_all: 0 | 1 = <default>
|
10257
10394
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10258
10395
|
- scid: int | str = <default>
|
10259
|
-
- show_dir: 0 | 1 = 1
|
10396
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10260
10397
|
- snap: 0 | 1 = <default>
|
10261
10398
|
- source: str = <default>
|
10262
10399
|
- sys_dir: int | str = <default>
|
10263
10400
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10264
|
-
- stdir: 0 | 1 = <default>
|
10401
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10265
10402
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10266
10403
|
- suffix_type: int = <default>
|
10267
10404
|
- type: int = <default> 💡 文件类型
|
@@ -10358,7 +10495,7 @@ class P115Client(P115OpenClient):
|
|
10358
10495
|
在根目录下且 fc_mix=0 且是特殊名字 ("我的接收", "手机相册", "云下载", "我的时光记录"),会在整个文件列表的最前面,这时可从返回信息的 "sys_count" 字段知道数目
|
10359
10496
|
|
10360
10497
|
:payload:
|
10361
|
-
- cid: int | str = 0 💡 目录 id
|
10498
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10362
10499
|
- limit: int = 32 💡 分页大小,最大值不一定,看数据量,7,000 应该总是安全的,10,000 有可能报错,但有时也可以 20,000 而成功
|
10363
10500
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10364
10501
|
|
@@ -10367,7 +10504,12 @@ class P115Client(P115OpenClient):
|
|
10367
10504
|
- code: int | str = <default>
|
10368
10505
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10369
10506
|
- cur: 0 | 1 = <default> 💡 是否只显示当前目录
|
10370
|
-
- custom_order: 0 | 1 | 2 = <default> 💡
|
10507
|
+
- custom_order: 0 | 1 | 2 = <default> 💡 是否使用记忆排序。如果指定了 "asc"、"fc_mix"、"o" 中其一,则此参数会被自动设置为 2
|
10508
|
+
|
10509
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10510
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10511
|
+
- 2: 自定义排序(非目录置顶)
|
10512
|
+
|
10371
10513
|
- date: str = <default> 💡 筛选日期
|
10372
10514
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10373
10515
|
- fields: str = <default>
|
@@ -10393,12 +10535,12 @@ class P115Client(P115OpenClient):
|
|
10393
10535
|
- r_all: 0 | 1 = <default>
|
10394
10536
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10395
10537
|
- scid: int | str = <default>
|
10396
|
-
- show_dir: 0 | 1 = 1 💡
|
10538
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10397
10539
|
- snap: 0 | 1 = <default>
|
10398
10540
|
- source: str = <default>
|
10399
10541
|
- sys_dir: int | str = <default> 💡 系统通用目录
|
10400
10542
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10401
|
-
- stdir: 0 | 1 = <default>
|
10543
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10402
10544
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10403
10545
|
- type: int = <default> 💡 文件类型
|
10404
10546
|
|
@@ -10483,7 +10625,7 @@ class P115Client(P115OpenClient):
|
|
10483
10625
|
2. fc_mix 无论怎么设置,都和 fc_mix=0 的效果相同(即目录总是置顶),设置为 custom_order=2 也没用
|
10484
10626
|
|
10485
10627
|
:payload:
|
10486
|
-
- cid: int | str = 0 💡 目录 id
|
10628
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10487
10629
|
- limit: int = 32 💡 分页大小,最大值不一定,看数据量,7,000 应该总是安全的,10,000 有可能报错,但有时也可以 20,000 而成功
|
10488
10630
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10489
10631
|
|
@@ -10493,6 +10635,11 @@ class P115Client(P115OpenClient):
|
|
10493
10635
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10494
10636
|
- cur: 0 | 1 = <default> 💡 是否只搜索当前目录
|
10495
10637
|
- custom_order: 0 | 1 | 2 = <default> 💡 启用自定义排序,如果指定了 "asc"、"fc_mix"、"o" 中其一,则此参数会被自动设置为 2
|
10638
|
+
|
10639
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10640
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10641
|
+
- 2: 自定义排序(非目录置顶)
|
10642
|
+
|
10496
10643
|
- date: str = <default> 💡 筛选日期
|
10497
10644
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10498
10645
|
- fields: str = <default>
|
@@ -10518,12 +10665,12 @@ class P115Client(P115OpenClient):
|
|
10518
10665
|
- r_all: 0 | 1 = <default>
|
10519
10666
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10520
10667
|
- scid: int | str = <default>
|
10521
|
-
- show_dir: 0 | 1 = 1
|
10668
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10522
10669
|
- snap: 0 | 1 = <default>
|
10523
10670
|
- source: str = <default>
|
10524
10671
|
- sys_dir: int | str = <default>
|
10525
10672
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10526
|
-
- stdir: 0 | 1 = <default>
|
10673
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10527
10674
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10528
10675
|
- type: int = <default> 💡 文件类型
|
10529
10676
|
|
@@ -10608,7 +10755,7 @@ class P115Client(P115OpenClient):
|
|
10608
10755
|
不过在我看来,只要一个目录内的节点数超过 2,400 个,则大概就没必要使用此接口
|
10609
10756
|
|
10610
10757
|
:payload:
|
10611
|
-
- cid: int | str = 0 💡 目录 id
|
10758
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10612
10759
|
- limit: int = 32 💡 分页大小,最大值是 1,200
|
10613
10760
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10614
10761
|
|
@@ -10618,6 +10765,11 @@ class P115Client(P115OpenClient):
|
|
10618
10765
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10619
10766
|
- cur: 0 | 1 = <default> 💡 是否只搜索当前目录
|
10620
10767
|
- custom_order: 0 | 1 = <default> 💡 启用自定义排序,如果指定了 "asc"、"fc_mix" 中其一,则此参数会被自动设置为 1
|
10768
|
+
|
10769
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10770
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10771
|
+
- 2: 自定义排序(非目录置顶)
|
10772
|
+
|
10621
10773
|
- date: str = <default> 💡 筛选日期
|
10622
10774
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10623
10775
|
- fields: str = <default>
|
@@ -10633,12 +10785,12 @@ class P115Client(P115OpenClient):
|
|
10633
10785
|
- r_all: 0 | 1 = <default>
|
10634
10786
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10635
10787
|
- scid: int | str = <default>
|
10636
|
-
- show_dir: 0 | 1 = 1
|
10788
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10637
10789
|
- snap: 0 | 1 = <default>
|
10638
10790
|
- source: str = <default>
|
10639
10791
|
- sys_dir: int | str = <default>
|
10640
10792
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10641
|
-
- stdir: 0 | 1 = <default>
|
10793
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10642
10794
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10643
10795
|
- type: int = <default> 💡 文件类型
|
10644
10796
|
|
@@ -10715,7 +10867,7 @@ class P115Client(P115OpenClient):
|
|
10715
10867
|
|
10716
10868
|
:payload:
|
10717
10869
|
- file_name: str 💡 文件名,不含后缀
|
10718
|
-
- pid: int | str = 0 💡 目录 id
|
10870
|
+
- pid: int | str = 0 💡 目录 id,对应 parent_id
|
10719
10871
|
- type: 1 | 2 | 3 = 1 💡 1:Word文档(.docx) 2:Excel表格(.xlsx) 3:PPT文稿(.pptx)
|
10720
10872
|
"""
|
10721
10873
|
api = complete_webapi("/files/blank_document", base_url=base_url)
|
@@ -10860,7 +11012,7 @@ class P115Client(P115OpenClient):
|
|
10860
11012
|
GET https://webapi.115.com/files/get_second_type
|
10861
11013
|
|
10862
11014
|
:payload:
|
10863
|
-
- cid: int | str = 0 💡 目录 id
|
11015
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10864
11016
|
- type: int = 1 💡 文件类型
|
10865
11017
|
|
10866
11018
|
- 1: 文档
|
@@ -11921,7 +12073,7 @@ class P115Client(P115OpenClient):
|
|
11921
12073
|
只能获取直属于 `cid` 所在目录的图片,不会遍历整个目录树
|
11922
12074
|
|
11923
12075
|
:payload:
|
11924
|
-
- cid: int | str 💡 目录 id
|
12076
|
+
- cid: int | str 💡 目录 id,对应 parent_id
|
11925
12077
|
- file_id: int | str 💡 不能是 0,可以不同于 `cid`,必须是任何一个有效的 id(单纯是被检查一下)
|
11926
12078
|
- limit: int = <default> 💡 最多返回数量
|
11927
12079
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
@@ -11984,7 +12136,7 @@ class P115Client(P115OpenClient):
|
|
11984
12136
|
GET https://proapi.115.com/android/files/imglist
|
11985
12137
|
|
11986
12138
|
:payload:
|
11987
|
-
- cid: int | str = 0 💡 目录 id
|
12139
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
11988
12140
|
- limit: int = 32 💡 一页大小,建议控制在 <= 9000,不然会报错
|
11989
12141
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
11990
12142
|
|
@@ -13890,7 +14042,7 @@ class P115Client(P115OpenClient):
|
|
13890
14042
|
- "user_ptime": 创建时间
|
13891
14043
|
- "user_otime": 上一次打开时间
|
13892
14044
|
|
13893
|
-
- file_id: int | str = 0 💡 目录 id
|
14045
|
+
- file_id: int | str = 0 💡 目录 id,对应 parent_id
|
13894
14046
|
- user_asc: 0 | 1 = <default> 💡 是否升序排列
|
13895
14047
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
13896
14048
|
- module: str = <default> 💡 "label_search" 表示用于搜索的排序
|
@@ -13953,7 +14105,7 @@ class P115Client(P115OpenClient):
|
|
13953
14105
|
- "user_ptime": 创建时间
|
13954
14106
|
- "user_otime": 上一次打开时间
|
13955
14107
|
|
13956
|
-
- file_id: int | str = 0 💡 目录 id
|
14108
|
+
- file_id: int | str = 0 💡 目录 id,对应 parent_id
|
13957
14109
|
- user_asc: 0 | 1 = <default> 💡 是否升序排列
|
13958
14110
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
13959
14111
|
- module: str = <default> 💡 "label_search" 表示用于搜索的排序
|
@@ -14338,7 +14490,7 @@ class P115Client(P115OpenClient):
|
|
14338
14490
|
:payload:
|
14339
14491
|
- aid: int | str = 1 💡 area_id。1:正常文件 7:回收站文件 12:瞬间文件 120:彻底删除文件、简历附件
|
14340
14492
|
- asc: 0 | 1 = <default> 💡 是否升序排列
|
14341
|
-
- cid: int | str = 0 💡 目录 id
|
14493
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
14342
14494
|
- count_folders: 0 | 1 = <default> 💡 是否统计目录数,这样就会增加 "folder_count" 和 "file_count" 字段作为统计
|
14343
14495
|
- date: str = <default> 💡 筛选日期,格式为 YYYY-MM-DD(或者 YYYY-MM 或 YYYY),具体可以看文件信息中的 "t" 字段的值
|
14344
14496
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
@@ -14450,7 +14602,7 @@ class P115Client(P115OpenClient):
|
|
14450
14602
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
14451
14603
|
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
14452
14604
|
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
14453
|
-
- show_dir: 0 | 1 = 1
|
14605
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
14454
14606
|
- source: str = <default>
|
14455
14607
|
- star: 0 | 1 = <default>
|
14456
14608
|
- suffix: str = <default>
|
@@ -14547,7 +14699,7 @@ class P115Client(P115OpenClient):
|
|
14547
14699
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
14548
14700
|
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
14549
14701
|
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
14550
|
-
- show_dir: 0 | 1 = 1
|
14702
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
14551
14703
|
- source: str = <default>
|
14552
14704
|
- star: 0 | 1 = <default>
|
14553
14705
|
- suffix: str = <default>
|
@@ -19391,7 +19543,7 @@ class P115Client(P115OpenClient):
|
|
19391
19543
|
:payload:
|
19392
19544
|
- share_code: str 💡 分享码
|
19393
19545
|
- receive_code: str 💡 接收码(即密码)
|
19394
|
-
- cid: int | str = 0 💡 目录 id
|
19546
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
19395
19547
|
- limit: int = 32 💡 一页大小,意思就是 page_size
|
19396
19548
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
19397
19549
|
- search_value: str = "." 💡 搜索文本,仅支持搜索文件名
|
@@ -20156,7 +20308,7 @@ class P115Client(P115OpenClient):
|
|
20156
20308
|
POST https://aps.115.com/repeat/repeat.php
|
20157
20309
|
|
20158
20310
|
:payload:
|
20159
|
-
- folder_id: int | str 💡 目录 id
|
20311
|
+
- folder_id: int | str 💡 目录 id,对应 parent_id
|
20160
20312
|
"""
|
20161
20313
|
api = complete_api("/repeat/repeat.php", "aps", base_url=base_url)
|
20162
20314
|
if isinstance(payload, (int, str)):
|
p115client/exception.py
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
4
|
__all__ = [
|
5
|
-
"P115Warning", "P115OSError", "
|
6
|
-
"
|
7
|
-
"
|
8
|
-
"P115FileNotFoundError", "P115IsADirectoryError",
|
5
|
+
"P115Warning", "P115OSError", "AccessTokenError", "AuthenticationError",
|
6
|
+
"BusyOSError", "DataError", "LoginError", "MultipartUploadAbort",
|
7
|
+
"OpenAppAuthLimitExceeded", "NotSupportedError", "OperationalError",
|
8
|
+
"P115FileExistsError", "P115FileNotFoundError", "P115IsADirectoryError",
|
9
9
|
"P115NotADirectoryError", "P115PermissionError", "P115TimeoutError",
|
10
10
|
]
|
11
11
|
|
@@ -51,6 +51,11 @@ class P115OSError(OSError):
|
|
51
51
|
return args[0]
|
52
52
|
|
53
53
|
|
54
|
+
class AccessTokenError(P115OSError, ValueError):
|
55
|
+
"""access_token 错误或者无效
|
56
|
+
"""
|
57
|
+
|
58
|
+
|
54
59
|
class AuthenticationError(P115OSError):
|
55
60
|
"""当登录状态无效时抛出
|
56
61
|
"""
|
p115client/tool/attr.py
CHANGED
@@ -5,8 +5,8 @@ __author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
5
5
|
__all__ = ["get_attr", "type_of_attr"]
|
6
6
|
__doc__ = "这个模块提供了一些和文件或目录信息有关的函数"
|
7
7
|
|
8
|
-
from collections.abc import Mapping
|
9
|
-
from typing import overload, Literal
|
8
|
+
from collections.abc import Coroutine, Mapping
|
9
|
+
from typing import overload, Any, Literal
|
10
10
|
|
11
11
|
from iterutils import run_gen_step
|
12
12
|
from p115client import check_response, normalize_attr_web, P115Client
|
@@ -32,7 +32,7 @@ def get_attr(
|
|
32
32
|
*,
|
33
33
|
async_: Literal[True],
|
34
34
|
**request_kwargs,
|
35
|
-
) -> dict:
|
35
|
+
) -> Coroutine[Any, Any, dict]:
|
36
36
|
...
|
37
37
|
def get_attr(
|
38
38
|
client: str | P115Client,
|
@@ -41,7 +41,7 @@ def get_attr(
|
|
41
41
|
*,
|
42
42
|
async_: Literal[False, True] = False,
|
43
43
|
**request_kwargs,
|
44
|
-
) -> dict:
|
44
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
45
45
|
"""获取文件或目录的信息
|
46
46
|
|
47
47
|
:param client: 115 客户端或 cookies
|
@@ -1,12 +1,12 @@
|
|
1
1
|
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
2
2
|
p115client/__init__.py,sha256=1mx7njuAlqcuEWONTjSiiGnXyyNyqOcJyNX1FMHqQ-4,214
|
3
3
|
p115client/_upload.py,sha256=RTYpM_EDFuI3O7yf08f13NdeG0iD03o_V4H6Je6Nsr8,30754
|
4
|
-
p115client/client.py,sha256=
|
4
|
+
p115client/client.py,sha256=YxVXjcnVZM5iCPFfpJGEdCP57mpKFUxXAhfsg6ZMobY,779699
|
5
5
|
p115client/const.py,sha256=KqDGr9KsOnSkNVM3RIdQGptCMHbidMmZ_ffyFPiniww,7654
|
6
|
-
p115client/exception.py,sha256=
|
6
|
+
p115client/exception.py,sha256=4SZ8ubOLMRxtcqc0u1kNzXqH1a6wwXJFwGnRDURoEgQ,3708
|
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=
|
9
|
+
p115client/tool/attr.py,sha256=RmNm5uar2PVv1Me7xOWyM0JtZr-JqoglIIpF0WHGues,2979
|
10
10
|
p115client/tool/download.py,sha256=CZJE5f1SHi26eCNTPcF5VjSoht8WTUYravEG219i4gk,61534
|
11
11
|
p115client/tool/edit.py,sha256=kRz-Ee7KuNNlHhcVi4uHdh9DSfF1ZxUREIhK9x4hNIE,17771
|
12
12
|
p115client/tool/export_dir.py,sha256=1r2qDuYIirtDkCBQfYXh6lbm06IStRpiom-ZjtIYdbo,24502
|
@@ -20,7 +20,7 @@ p115client/tool/upload.py,sha256=i6laoeG7GdNO7hvCDVBy8Yv2Is800wL7O5na6a3v70g,159
|
|
20
20
|
p115client/tool/util.py,sha256=0o9TrXdoPcljgxDDRdxRon41bq1OjuUYCWsR0XLfmPo,3357
|
21
21
|
p115client/tool/xys.py,sha256=vU28Px2yeQzIxxGkopJIpvV6TdOnWJ5xB6NPXpTgM0Y,10306
|
22
22
|
p115client/type.py,sha256=7kOp98uLaYqcTTCgCrb3DRcl8ukMpn7ibsnVvtw2nG8,6250
|
23
|
-
p115client-0.0.5.11.
|
24
|
-
p115client-0.0.5.11.
|
25
|
-
p115client-0.0.5.11.
|
26
|
-
p115client-0.0.5.11.
|
23
|
+
p115client-0.0.5.11.8.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
24
|
+
p115client-0.0.5.11.8.dist-info/METADATA,sha256=Ng7fJ9yIRTxGaXzAqM8rHjbRmgVlt-hdDoJ8C9dlJYM,8192
|
25
|
+
p115client-0.0.5.11.8.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
26
|
+
p115client-0.0.5.11.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|