p115client 0.0.5.11.7.2__py3-none-any.whl → 0.0.5.11.8.1__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 +316 -163
- p115client/exception.py +9 -4
- {p115client-0.0.5.11.7.2.dist-info → p115client-0.0.5.11.8.1.dist-info}/METADATA +1 -1
- {p115client-0.0.5.11.7.2.dist-info → p115client-0.0.5.11.8.1.dist-info}/RECORD +6 -6
- {p115client-0.0.5.11.7.2.dist-info → p115client-0.0.5.11.8.1.dist-info}/LICENSE +0 -0
- {p115client-0.0.5.11.7.2.dist-info → p115client-0.0.5.11.8.1.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,60 @@ 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
|
+
"app_id": app_id,
|
6076
|
+
"name": tip_txt[:-10].removeprefix("\ufeff"),
|
6077
|
+
"icon": resp["data"]["icon"],
|
6078
|
+
}
|
6079
|
+
return run_gen_step(gen_step, may_call=False, async_=async_)
|
6080
|
+
|
5956
6081
|
@overload
|
5957
6082
|
def login_with_open(
|
5958
6083
|
self,
|
5959
6084
|
/,
|
5960
|
-
app_id: int | str,
|
6085
|
+
app_id: int | str = 100195123,
|
5961
6086
|
*,
|
5962
6087
|
show_warning: bool = False,
|
5963
6088
|
async_: Literal[False] = False,
|
@@ -5968,7 +6093,7 @@ class P115Client(P115OpenClient):
|
|
5968
6093
|
def login_with_open(
|
5969
6094
|
self,
|
5970
6095
|
/,
|
5971
|
-
app_id: int | str,
|
6096
|
+
app_id: int | str = 100195123,
|
5972
6097
|
*,
|
5973
6098
|
show_warning: bool = False,
|
5974
6099
|
async_: Literal[True],
|
@@ -5978,7 +6103,7 @@ class P115Client(P115OpenClient):
|
|
5978
6103
|
def login_with_open(
|
5979
6104
|
self,
|
5980
6105
|
/,
|
5981
|
-
app_id: int | str,
|
6106
|
+
app_id: int | str = 100195123,
|
5982
6107
|
*,
|
5983
6108
|
show_warning: bool = False,
|
5984
6109
|
async_: Literal[False, True] = False,
|
@@ -6153,7 +6278,7 @@ class P115Client(P115OpenClient):
|
|
6153
6278
|
def login_another_open(
|
6154
6279
|
self,
|
6155
6280
|
/,
|
6156
|
-
app_id: int | str,
|
6281
|
+
app_id: int | str = 100195123,
|
6157
6282
|
*,
|
6158
6283
|
replace: Literal[True] | Self,
|
6159
6284
|
show_warning: bool = False,
|
@@ -6165,7 +6290,7 @@ class P115Client(P115OpenClient):
|
|
6165
6290
|
def login_another_open(
|
6166
6291
|
self,
|
6167
6292
|
/,
|
6168
|
-
app_id: int | str,
|
6293
|
+
app_id: int | str = 100195123,
|
6169
6294
|
*,
|
6170
6295
|
replace: Literal[True] | Self,
|
6171
6296
|
show_warning: bool = False,
|
@@ -6177,7 +6302,7 @@ class P115Client(P115OpenClient):
|
|
6177
6302
|
def login_another_open(
|
6178
6303
|
self,
|
6179
6304
|
/,
|
6180
|
-
app_id: int | str,
|
6305
|
+
app_id: int | str = 100195123,
|
6181
6306
|
*,
|
6182
6307
|
replace: Literal[False] = False,
|
6183
6308
|
show_warning: bool = False,
|
@@ -6189,7 +6314,7 @@ class P115Client(P115OpenClient):
|
|
6189
6314
|
def login_another_open(
|
6190
6315
|
self,
|
6191
6316
|
/,
|
6192
|
-
app_id: int | str,
|
6317
|
+
app_id: int | str = 100195123,
|
6193
6318
|
*,
|
6194
6319
|
replace: Literal[False] = False,
|
6195
6320
|
show_warning: bool = False,
|
@@ -6200,7 +6325,7 @@ class P115Client(P115OpenClient):
|
|
6200
6325
|
def login_another_open(
|
6201
6326
|
self,
|
6202
6327
|
/,
|
6203
|
-
app_id: int | str,
|
6328
|
+
app_id: int | str = 100195123,
|
6204
6329
|
*,
|
6205
6330
|
replace: bool | Self = False,
|
6206
6331
|
show_warning: bool = False,
|
@@ -6571,8 +6696,16 @@ class P115Client(P115OpenClient):
|
|
6571
6696
|
method=method,
|
6572
6697
|
**request_kwargs,
|
6573
6698
|
)
|
6699
|
+
if (
|
6700
|
+
is_open_api and
|
6701
|
+
need_to_check and
|
6702
|
+
isinstance(resp, dict) and
|
6703
|
+
resp.get("code") in (40140123, 40140124, 40140125, 40140126)
|
6704
|
+
):
|
6705
|
+
check_response(resp)
|
6574
6706
|
except BaseException as e:
|
6575
6707
|
is_auth_error = isinstance(e, (AuthenticationError, LoginError))
|
6708
|
+
not_access_token_error = not isinstance(e, AccessTokenError)
|
6576
6709
|
if (
|
6577
6710
|
cert_headers is not None and
|
6578
6711
|
revert_cert_headers is not None and
|
@@ -6582,26 +6715,25 @@ class P115Client(P115OpenClient):
|
|
6582
6715
|
yield revert_cert_headers(cert_headers)
|
6583
6716
|
if not need_to_check:
|
6584
6717
|
raise
|
6585
|
-
|
6586
|
-
|
6587
|
-
|
6718
|
+
if not_access_token_error:
|
6719
|
+
res = yield cast(Callable, check_for_relogin)(e)
|
6720
|
+
if not res if isinstance(res, bool) else res != 405:
|
6721
|
+
raise
|
6588
6722
|
if fetch_cert_headers is not None:
|
6589
6723
|
cert_headers = yield fetch_cert_headers()
|
6590
6724
|
headers.update(cert_headers)
|
6591
6725
|
elif is_open_api:
|
6592
6726
|
yield lock.acquire()
|
6593
6727
|
try:
|
6594
|
-
|
6595
|
-
|
6596
|
-
|
6597
|
-
|
6598
|
-
|
6599
|
-
|
6600
|
-
|
6601
|
-
|
6602
|
-
|
6603
|
-
)
|
6604
|
-
warn(f"relogin to refresh token: {app_id=}", category=P115Warning)
|
6728
|
+
access_token = self.access_token
|
6729
|
+
if cert.capitalize().removeprefix("Bearer ") == access_token:
|
6730
|
+
if i or is_auth_error or not_access_token_error:
|
6731
|
+
raise
|
6732
|
+
warn(f"relogin to refresh token", category=P115Warning)
|
6733
|
+
yield self.refresh_access_token(async_=async_)
|
6734
|
+
cert = headers["authorization"] = "Bearer " + self.access_token
|
6735
|
+
else:
|
6736
|
+
cert = headers["authorization"] = "Bearer " + access_token
|
6605
6737
|
finally:
|
6606
6738
|
lock.release()
|
6607
6739
|
else:
|
@@ -6625,8 +6757,9 @@ class P115Client(P115OpenClient):
|
|
6625
6757
|
replace=True,
|
6626
6758
|
async_=async_, # type: ignore
|
6627
6759
|
)
|
6760
|
+
cert = headers["cookie"] = self.cookies_str
|
6628
6761
|
else:
|
6629
|
-
headers["cookie"] = cookies_new
|
6762
|
+
cert = headers["cookie"] = cookies_new
|
6630
6763
|
finally:
|
6631
6764
|
lock.release()
|
6632
6765
|
else:
|
@@ -10222,7 +10355,7 @@ class P115Client(P115OpenClient):
|
|
10222
10355
|
- 7: 其它
|
10223
10356
|
|
10224
10357
|
:payload:
|
10225
|
-
- cid: int | str = 0 💡 目录 id
|
10358
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10226
10359
|
- limit: int = 32 💡 分页大小,目前最大值是 1,150,以前是没限制的
|
10227
10360
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10228
10361
|
|
@@ -10232,6 +10365,11 @@ class P115Client(P115OpenClient):
|
|
10232
10365
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10233
10366
|
- cur: 0 | 1 = <default> 💡 是否只搜索当前目录
|
10234
10367
|
- custom_order: 0 | 1 = <default> 💡 启用自定义排序,如果指定了 "asc"、"fc_mix"、"o" 中其一,则此参数会被自动设置为 1
|
10368
|
+
|
10369
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10370
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10371
|
+
- 2: 自定义排序(非目录置顶)
|
10372
|
+
|
10235
10373
|
- date: str = <default> 💡 筛选日期
|
10236
10374
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10237
10375
|
- fields: str = <default>
|
@@ -10256,12 +10394,12 @@ class P115Client(P115OpenClient):
|
|
10256
10394
|
- r_all: 0 | 1 = <default>
|
10257
10395
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10258
10396
|
- scid: int | str = <default>
|
10259
|
-
- show_dir: 0 | 1 = 1
|
10397
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10260
10398
|
- snap: 0 | 1 = <default>
|
10261
10399
|
- source: str = <default>
|
10262
10400
|
- sys_dir: int | str = <default>
|
10263
10401
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10264
|
-
- stdir: 0 | 1 = <default>
|
10402
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10265
10403
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10266
10404
|
- suffix_type: int = <default>
|
10267
10405
|
- type: int = <default> 💡 文件类型
|
@@ -10358,7 +10496,7 @@ class P115Client(P115OpenClient):
|
|
10358
10496
|
在根目录下且 fc_mix=0 且是特殊名字 ("我的接收", "手机相册", "云下载", "我的时光记录"),会在整个文件列表的最前面,这时可从返回信息的 "sys_count" 字段知道数目
|
10359
10497
|
|
10360
10498
|
:payload:
|
10361
|
-
- cid: int | str = 0 💡 目录 id
|
10499
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10362
10500
|
- limit: int = 32 💡 分页大小,最大值不一定,看数据量,7,000 应该总是安全的,10,000 有可能报错,但有时也可以 20,000 而成功
|
10363
10501
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10364
10502
|
|
@@ -10367,7 +10505,12 @@ class P115Client(P115OpenClient):
|
|
10367
10505
|
- code: int | str = <default>
|
10368
10506
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10369
10507
|
- cur: 0 | 1 = <default> 💡 是否只显示当前目录
|
10370
|
-
- custom_order: 0 | 1 | 2 = <default> 💡
|
10508
|
+
- custom_order: 0 | 1 | 2 = <default> 💡 是否使用记忆排序。如果指定了 "asc"、"fc_mix"、"o" 中其一,则此参数会被自动设置为 2
|
10509
|
+
|
10510
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10511
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10512
|
+
- 2: 自定义排序(非目录置顶)
|
10513
|
+
|
10371
10514
|
- date: str = <default> 💡 筛选日期
|
10372
10515
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10373
10516
|
- fields: str = <default>
|
@@ -10393,12 +10536,12 @@ class P115Client(P115OpenClient):
|
|
10393
10536
|
- r_all: 0 | 1 = <default>
|
10394
10537
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10395
10538
|
- scid: int | str = <default>
|
10396
|
-
- show_dir: 0 | 1 = 1 💡
|
10539
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10397
10540
|
- snap: 0 | 1 = <default>
|
10398
10541
|
- source: str = <default>
|
10399
10542
|
- sys_dir: int | str = <default> 💡 系统通用目录
|
10400
10543
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10401
|
-
- stdir: 0 | 1 = <default>
|
10544
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10402
10545
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10403
10546
|
- type: int = <default> 💡 文件类型
|
10404
10547
|
|
@@ -10483,7 +10626,7 @@ class P115Client(P115OpenClient):
|
|
10483
10626
|
2. fc_mix 无论怎么设置,都和 fc_mix=0 的效果相同(即目录总是置顶),设置为 custom_order=2 也没用
|
10484
10627
|
|
10485
10628
|
:payload:
|
10486
|
-
- cid: int | str = 0 💡 目录 id
|
10629
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10487
10630
|
- limit: int = 32 💡 分页大小,最大值不一定,看数据量,7,000 应该总是安全的,10,000 有可能报错,但有时也可以 20,000 而成功
|
10488
10631
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10489
10632
|
|
@@ -10493,6 +10636,11 @@ class P115Client(P115OpenClient):
|
|
10493
10636
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10494
10637
|
- cur: 0 | 1 = <default> 💡 是否只搜索当前目录
|
10495
10638
|
- custom_order: 0 | 1 | 2 = <default> 💡 启用自定义排序,如果指定了 "asc"、"fc_mix"、"o" 中其一,则此参数会被自动设置为 2
|
10639
|
+
|
10640
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10641
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10642
|
+
- 2: 自定义排序(非目录置顶)
|
10643
|
+
|
10496
10644
|
- date: str = <default> 💡 筛选日期
|
10497
10645
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10498
10646
|
- fields: str = <default>
|
@@ -10518,12 +10666,12 @@ class P115Client(P115OpenClient):
|
|
10518
10666
|
- r_all: 0 | 1 = <default>
|
10519
10667
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10520
10668
|
- scid: int | str = <default>
|
10521
|
-
- show_dir: 0 | 1 = 1
|
10669
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10522
10670
|
- snap: 0 | 1 = <default>
|
10523
10671
|
- source: str = <default>
|
10524
10672
|
- sys_dir: int | str = <default>
|
10525
10673
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10526
|
-
- stdir: 0 | 1 = <default>
|
10674
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10527
10675
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10528
10676
|
- type: int = <default> 💡 文件类型
|
10529
10677
|
|
@@ -10608,7 +10756,7 @@ class P115Client(P115OpenClient):
|
|
10608
10756
|
不过在我看来,只要一个目录内的节点数超过 2,400 个,则大概就没必要使用此接口
|
10609
10757
|
|
10610
10758
|
:payload:
|
10611
|
-
- cid: int | str = 0 💡 目录 id
|
10759
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10612
10760
|
- limit: int = 32 💡 分页大小,最大值是 1,200
|
10613
10761
|
- offset: int = 0 💡 分页开始的索引,索引从 0 开始计算
|
10614
10762
|
|
@@ -10618,6 +10766,11 @@ class P115Client(P115OpenClient):
|
|
10618
10766
|
- count_folders: 0 | 1 = 1 💡 统计文件数和目录数
|
10619
10767
|
- cur: 0 | 1 = <default> 💡 是否只搜索当前目录
|
10620
10768
|
- custom_order: 0 | 1 = <default> 💡 启用自定义排序,如果指定了 "asc"、"fc_mix" 中其一,则此参数会被自动设置为 1
|
10769
|
+
|
10770
|
+
- 0: 使用记忆排序(自定义排序失效)
|
10771
|
+
- 1: 使用自定义排序(不使用记忆排序)
|
10772
|
+
- 2: 自定义排序(非目录置顶)
|
10773
|
+
|
10621
10774
|
- date: str = <default> 💡 筛选日期
|
10622
10775
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
10623
10776
|
- fields: str = <default>
|
@@ -10633,12 +10786,12 @@ class P115Client(P115OpenClient):
|
|
10633
10786
|
- r_all: 0 | 1 = <default>
|
10634
10787
|
- record_open_time: 0 | 1 = 1 💡 是否要记录目录的打开时间
|
10635
10788
|
- scid: int | str = <default>
|
10636
|
-
- show_dir: 0 | 1 = 1
|
10789
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
10637
10790
|
- snap: 0 | 1 = <default>
|
10638
10791
|
- source: str = <default>
|
10639
10792
|
- sys_dir: int | str = <default>
|
10640
10793
|
- star: 0 | 1 = <default> 💡 是否星标文件
|
10641
|
-
- stdir: 0 | 1 = <default>
|
10794
|
+
- stdir: 0 | 1 = <default> 💡 筛选文件时,是否显示文件夹:1:展示 0:不展示
|
10642
10795
|
- suffix: str = <default> 💡 后缀名(优先级高于 `type`)
|
10643
10796
|
- type: int = <default> 💡 文件类型
|
10644
10797
|
|
@@ -10715,7 +10868,7 @@ class P115Client(P115OpenClient):
|
|
10715
10868
|
|
10716
10869
|
:payload:
|
10717
10870
|
- file_name: str 💡 文件名,不含后缀
|
10718
|
-
- pid: int | str = 0 💡 目录 id
|
10871
|
+
- pid: int | str = 0 💡 目录 id,对应 parent_id
|
10719
10872
|
- type: 1 | 2 | 3 = 1 💡 1:Word文档(.docx) 2:Excel表格(.xlsx) 3:PPT文稿(.pptx)
|
10720
10873
|
"""
|
10721
10874
|
api = complete_webapi("/files/blank_document", base_url=base_url)
|
@@ -10860,7 +11013,7 @@ class P115Client(P115OpenClient):
|
|
10860
11013
|
GET https://webapi.115.com/files/get_second_type
|
10861
11014
|
|
10862
11015
|
:payload:
|
10863
|
-
- cid: int | str = 0 💡 目录 id
|
11016
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
10864
11017
|
- type: int = 1 💡 文件类型
|
10865
11018
|
|
10866
11019
|
- 1: 文档
|
@@ -11921,7 +12074,7 @@ class P115Client(P115OpenClient):
|
|
11921
12074
|
只能获取直属于 `cid` 所在目录的图片,不会遍历整个目录树
|
11922
12075
|
|
11923
12076
|
:payload:
|
11924
|
-
- cid: int | str 💡 目录 id
|
12077
|
+
- cid: int | str 💡 目录 id,对应 parent_id
|
11925
12078
|
- file_id: int | str 💡 不能是 0,可以不同于 `cid`,必须是任何一个有效的 id(单纯是被检查一下)
|
11926
12079
|
- limit: int = <default> 💡 最多返回数量
|
11927
12080
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
@@ -11984,7 +12137,7 @@ class P115Client(P115OpenClient):
|
|
11984
12137
|
GET https://proapi.115.com/android/files/imglist
|
11985
12138
|
|
11986
12139
|
:payload:
|
11987
|
-
- cid: int | str = 0 💡 目录 id
|
12140
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
11988
12141
|
- limit: int = 32 💡 一页大小,建议控制在 <= 9000,不然会报错
|
11989
12142
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
11990
12143
|
|
@@ -13890,7 +14043,7 @@ class P115Client(P115OpenClient):
|
|
13890
14043
|
- "user_ptime": 创建时间
|
13891
14044
|
- "user_otime": 上一次打开时间
|
13892
14045
|
|
13893
|
-
- file_id: int | str = 0 💡 目录 id
|
14046
|
+
- file_id: int | str = 0 💡 目录 id,对应 parent_id
|
13894
14047
|
- user_asc: 0 | 1 = <default> 💡 是否升序排列
|
13895
14048
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
13896
14049
|
- module: str = <default> 💡 "label_search" 表示用于搜索的排序
|
@@ -13953,7 +14106,7 @@ class P115Client(P115OpenClient):
|
|
13953
14106
|
- "user_ptime": 创建时间
|
13954
14107
|
- "user_otime": 上一次打开时间
|
13955
14108
|
|
13956
|
-
- file_id: int | str = 0 💡 目录 id
|
14109
|
+
- file_id: int | str = 0 💡 目录 id,对应 parent_id
|
13957
14110
|
- user_asc: 0 | 1 = <default> 💡 是否升序排列
|
13958
14111
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
13959
14112
|
- module: str = <default> 💡 "label_search" 表示用于搜索的排序
|
@@ -14338,7 +14491,7 @@ class P115Client(P115OpenClient):
|
|
14338
14491
|
:payload:
|
14339
14492
|
- aid: int | str = 1 💡 area_id。1:正常文件 7:回收站文件 12:瞬间文件 120:彻底删除文件、简历附件
|
14340
14493
|
- asc: 0 | 1 = <default> 💡 是否升序排列
|
14341
|
-
- cid: int | str = 0 💡 目录 id
|
14494
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
14342
14495
|
- count_folders: 0 | 1 = <default> 💡 是否统计目录数,这样就会增加 "folder_count" 和 "file_count" 字段作为统计
|
14343
14496
|
- date: str = <default> 💡 筛选日期,格式为 YYYY-MM-DD(或者 YYYY-MM 或 YYYY),具体可以看文件信息中的 "t" 字段的值
|
14344
14497
|
- fc_mix: 0 | 1 = <default> 💡 是否目录和文件混合,如果为 0 则目录在前(目录置顶)
|
@@ -14450,7 +14603,7 @@ class P115Client(P115OpenClient):
|
|
14450
14603
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
14451
14604
|
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
14452
14605
|
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
14453
|
-
- show_dir: 0 | 1 = 1
|
14606
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
14454
14607
|
- source: str = <default>
|
14455
14608
|
- star: 0 | 1 = <default>
|
14456
14609
|
- suffix: str = <default>
|
@@ -14547,7 +14700,7 @@ class P115Client(P115OpenClient):
|
|
14547
14700
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
14548
14701
|
- pick_code: str = <default> 💡 是否查询提取码,如果该值为 1 则查询提取码为 `search_value` 的文件
|
14549
14702
|
- search_value: str = "." 💡 搜索文本,可以是 sha1
|
14550
|
-
- show_dir: 0 | 1 = 1
|
14703
|
+
- show_dir: 0 | 1 = 1 💡 是否显示目录
|
14551
14704
|
- source: str = <default>
|
14552
14705
|
- star: 0 | 1 = <default>
|
14553
14706
|
- suffix: str = <default>
|
@@ -19391,7 +19544,7 @@ class P115Client(P115OpenClient):
|
|
19391
19544
|
:payload:
|
19392
19545
|
- share_code: str 💡 分享码
|
19393
19546
|
- receive_code: str 💡 接收码(即密码)
|
19394
|
-
- cid: int | str = 0 💡 目录 id
|
19547
|
+
- cid: int | str = 0 💡 目录 id,对应 parent_id
|
19395
19548
|
- limit: int = 32 💡 一页大小,意思就是 page_size
|
19396
19549
|
- offset: int = 0 💡 索引偏移,索引从 0 开始计算
|
19397
19550
|
- search_value: str = "." 💡 搜索文本,仅支持搜索文件名
|
@@ -20156,7 +20309,7 @@ class P115Client(P115OpenClient):
|
|
20156
20309
|
POST https://aps.115.com/repeat/repeat.php
|
20157
20310
|
|
20158
20311
|
:payload:
|
20159
|
-
- folder_id: int | str 💡 目录 id
|
20312
|
+
- folder_id: int | str 💡 目录 id,对应 parent_id
|
20160
20313
|
"""
|
20161
20314
|
api = complete_api("/repeat/repeat.php", "aps", base_url=base_url)
|
20162
20315
|
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
|
"""
|
@@ -1,9 +1,9 @@
|
|
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=ro8Qk1RiKMzMRyg19eRvVTBFF-9lgKZoOYq2FiDff5w,779734
|
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
9
|
p115client/tool/attr.py,sha256=RmNm5uar2PVv1Me7xOWyM0JtZr-JqoglIIpF0WHGues,2979
|
@@ -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.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
24
|
+
p115client-0.0.5.11.8.1.dist-info/METADATA,sha256=e-F1jCsLHlXC-jCgUfDJcvKcjZpn7OwX8H9Hu7yu6nE,8194
|
25
|
+
p115client-0.0.5.11.8.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
26
|
+
p115client-0.0.5.11.8.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|