p115client 0.0.5.8.1__py3-none-any.whl → 0.0.5.8.3__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 +311 -183
- {p115client-0.0.5.8.1.dist-info → p115client-0.0.5.8.3.dist-info}/METADATA +1 -1
- {p115client-0.0.5.8.1.dist-info → p115client-0.0.5.8.3.dist-info}/RECORD +5 -5
- {p115client-0.0.5.8.1.dist-info → p115client-0.0.5.8.3.dist-info}/LICENSE +0 -0
- {p115client-0.0.5.8.1.dist-info → p115client-0.0.5.8.3.dist-info}/WHEEL +0 -0
p115client/client.py
CHANGED
@@ -9,15 +9,14 @@ __all__ = [
|
|
9
9
|
"normalize_attr_app", "normalize_attr_app2", "P115OpenClient", "P115Client",
|
10
10
|
]
|
11
11
|
|
12
|
-
import
|
13
|
-
|
14
|
-
from asyncio import create_task, get_running_loop, run_coroutine_threadsafe, to_thread, Lock as AsyncLock
|
12
|
+
from asyncio import Lock as AsyncLock
|
15
13
|
from base64 import b64encode
|
16
14
|
from collections.abc import (
|
17
15
|
AsyncGenerator, AsyncIterable, Awaitable, Buffer, Callable, Coroutine, Generator,
|
18
16
|
ItemsView, Iterable, Iterator, Mapping, MutableMapping, Sequence,
|
19
17
|
)
|
20
18
|
from datetime import date, datetime, timedelta
|
19
|
+
from errno import EBUSY, EEXIST, EFBIG, EINVAL, EIO, EISDIR, ENODATA, ENOENT, ENOSPC, ENOSYS, ENOTSUP
|
21
20
|
from functools import partial
|
22
21
|
from hashlib import md5, sha1
|
23
22
|
from http.cookiejar import Cookie, CookieJar
|
@@ -230,7 +229,7 @@ def json_loads(content: Buffer, /):
|
|
230
229
|
except Exception as e:
|
231
230
|
if isinstance(content, memoryview):
|
232
231
|
content = content.tobytes()
|
233
|
-
raise DataError(
|
232
|
+
raise DataError(ENODATA, content) from e
|
234
233
|
|
235
234
|
|
236
235
|
def default_parse(resp, content: Buffer, /):
|
@@ -283,35 +282,6 @@ def items(m: Mapping, /) -> ItemsView:
|
|
283
282
|
return ItemsView(m)
|
284
283
|
|
285
284
|
|
286
|
-
def file_close(file, /, async_: bool = False):
|
287
|
-
cls = type(file)
|
288
|
-
if async_:
|
289
|
-
aclose = getattr(file, "aclose", None)
|
290
|
-
if callable(aclose):
|
291
|
-
return aclose()
|
292
|
-
aeixt = getattr(cls, "__aexit__", None)
|
293
|
-
if callable(aeixt):
|
294
|
-
return aeixt(file, *exc_info())
|
295
|
-
close = getattr(file, "close", None)
|
296
|
-
if callable(close):
|
297
|
-
if async_:
|
298
|
-
return ensure_async(close, threaded=True)()
|
299
|
-
else:
|
300
|
-
return close()
|
301
|
-
exit = getattr(cls, "__exit__", None)
|
302
|
-
if callable(exit):
|
303
|
-
if async_:
|
304
|
-
return ensure_async(exit, threaded=True)(file, *exc_info())
|
305
|
-
else:
|
306
|
-
return exit(file, *exc_info())
|
307
|
-
deleter = getattr(cls, "__del__", None)
|
308
|
-
if callable(deleter):
|
309
|
-
if async_:
|
310
|
-
return ensure_async(deleter, threaded=True)(file)
|
311
|
-
else:
|
312
|
-
return deleter(file)
|
313
|
-
|
314
|
-
|
315
285
|
def cookies_equal(cookies1: None | str, cookies2: None | str, /) -> bool:
|
316
286
|
if not (cookies1 and cookies2):
|
317
287
|
return False
|
@@ -380,7 +350,7 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
|
|
380
350
|
"""
|
381
351
|
def check(resp, /) -> dict:
|
382
352
|
if not isinstance(resp, dict):
|
383
|
-
raise P115OSError(
|
353
|
+
raise P115OSError(EIO, resp)
|
384
354
|
if resp.get("state", True):
|
385
355
|
return resp
|
386
356
|
if code := get_first(resp, "errno", "errNo", "errcode", "errCode", "code"):
|
@@ -390,108 +360,109 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
|
|
390
360
|
match code:
|
391
361
|
# {"state": false, "errno": 99, "error": "请重新登录"}
|
392
362
|
case 99:
|
393
|
-
raise LoginError(
|
363
|
+
raise LoginError(EIO, resp)
|
394
364
|
# {"state": false, "errno": 911, "error": "请验证账号"}
|
395
365
|
case 911:
|
396
|
-
raise AuthenticationError(
|
366
|
+
raise AuthenticationError(EIO, resp)
|
397
367
|
# {"state": false, "errno": 20001, "error": "目录名称不能为空"}
|
398
368
|
case 20001:
|
399
|
-
raise OperationalError(
|
369
|
+
raise OperationalError(EINVAL, resp)
|
400
370
|
# {"state": false, "errno": 20004, "error": "该目录名称已存在。"}
|
401
371
|
case 20004:
|
402
|
-
raise FileExistsError(
|
372
|
+
raise FileExistsError(EEXIST, resp)
|
403
373
|
# {"state": false, "errno": 20009, "error": "父目录不存在。"}
|
404
374
|
case 20009:
|
405
|
-
raise FileNotFoundError(
|
375
|
+
raise FileNotFoundError(ENOENT, resp)
|
406
376
|
# {"state": false, "errno": 20018, "error": "文件不存在或已删除。"}
|
407
377
|
# {"state": false, "errno": 50015, "error": "文件不存在或已删除。"}
|
408
|
-
|
409
|
-
|
378
|
+
# {"state": false, "errno": 430004, "error": "文件(夹)不存在或已删除。"}
|
379
|
+
case 20018 | 50015 | 430004:
|
380
|
+
raise FileNotFoundError(ENOENT, resp)
|
410
381
|
# {"state": false, "errno": 20020, "error": "后缀名不正确,请重新输入"}
|
411
382
|
case 20020:
|
412
|
-
raise OperationalError(
|
383
|
+
raise OperationalError(ENOTSUP, resp)
|
413
384
|
# {"state": false, "errno": 20021, "error": "后缀名不正确,请重新输入"}
|
414
385
|
case 20021:
|
415
|
-
raise OperationalError(
|
386
|
+
raise OperationalError(ENOTSUP, resp)
|
416
387
|
# {"state": false, "errno": 31001, "error": "所预览的文件不存在。"}
|
417
388
|
case 31001:
|
418
|
-
raise FileNotFoundError(
|
389
|
+
raise FileNotFoundError(ENOENT, resp)
|
419
390
|
# {"state": false, "errno": 31004, "error": "文档未上传完整,请上传完成后再进行查看。"}
|
420
391
|
case 31004:
|
421
|
-
raise FileNotFoundError(
|
392
|
+
raise FileNotFoundError(ENOENT, resp)
|
422
393
|
# {"state": false, "errno": 50003, "error": "很抱歉,该文件提取码不存在。"}
|
423
394
|
case 50003:
|
424
|
-
raise FileNotFoundError(
|
395
|
+
raise FileNotFoundError(ENOENT, resp)
|
425
396
|
# {"state": false, "errno": 90008, "error": "文件(夹)不存在或已经删除。"}
|
426
397
|
case 90008:
|
427
|
-
raise FileNotFoundError(
|
398
|
+
raise FileNotFoundError(ENOENT, resp)
|
428
399
|
# {"state": false, "errno": 91002, "error": "不能将文件复制到自身或其子目录下。"}
|
429
400
|
case 91002:
|
430
|
-
raise NotSupportedError(
|
401
|
+
raise NotSupportedError(ENOTSUP, resp)
|
431
402
|
# {"state": false, "errno": 91004, "error": "操作的文件(夹)数量超过5万个"}
|
432
403
|
case 91004:
|
433
|
-
raise NotSupportedError(
|
404
|
+
raise NotSupportedError(ENOTSUP, resp)
|
434
405
|
# {"state": false, "errno": 91005, "error": "空间不足,复制失败。"}
|
435
406
|
case 91005:
|
436
|
-
raise OperationalError(
|
407
|
+
raise OperationalError(ENOSPC, resp)
|
437
408
|
# {"state": false, "errno": 231011, "error": "文件已删除,请勿重复操作"}
|
438
409
|
case 231011:
|
439
|
-
raise FileNotFoundError(
|
410
|
+
raise FileNotFoundError(ENOENT, resp)
|
440
411
|
# {"state": false, "errno": 300104, "error": "文件超过200MB,暂不支持播放"}
|
441
412
|
case 300104:
|
442
|
-
raise P115OSError(
|
413
|
+
raise P115OSError(EFBIG, resp)
|
443
414
|
# {"state": false, "errno": 590075, "error": "操作太频繁,请稍候再试"}
|
444
415
|
case 590075:
|
445
|
-
raise BusyOSError(
|
416
|
+
raise BusyOSError(EBUSY, resp)
|
446
417
|
# {"state": false, "errno": 800001, "error": "目录不存在。"}
|
447
418
|
case 800001:
|
448
|
-
raise FileNotFoundError(
|
419
|
+
raise FileNotFoundError(ENOENT, resp)
|
449
420
|
# {"state": false, "errno": 980006, "error": "404 Not Found"}
|
450
421
|
case 980006:
|
451
|
-
raise NotSupportedError(
|
422
|
+
raise NotSupportedError(ENOSYS, resp)
|
452
423
|
# {"state": false, "errno": 990001, "error": "登陆超时,请重新登陆。"}
|
453
424
|
case 990001:
|
454
425
|
# NOTE: 可能就是被下线了
|
455
|
-
raise AuthenticationError(
|
426
|
+
raise AuthenticationError(EIO, resp)
|
456
427
|
# {"state": false, "errno": 990002, "error": "参数错误。"}
|
457
428
|
case 990002:
|
458
|
-
raise P115OSError(
|
429
|
+
raise P115OSError(EINVAL, resp)
|
459
430
|
# {"state": false, "errno": 990003, "error": "操作失败。"}
|
460
431
|
case 990003:
|
461
|
-
raise OperationalError(
|
432
|
+
raise OperationalError(EIO, resp)
|
462
433
|
# {"state": false, "errno": 990005, "error": "你的账号有类似任务正在处理,请稍后再试!"}
|
463
434
|
case 990005:
|
464
|
-
raise BusyOSError(
|
435
|
+
raise BusyOSError(EBUSY, resp)
|
465
436
|
# {"state": false, "errno": 990009, "error": "删除[...]操作尚未执行完成,请稍后再试!"}
|
466
437
|
# {"state": false, "errno": 990009, "error": "还原[...]操作尚未执行完成,请稍后再试!"}
|
467
438
|
# {"state": false, "errno": 990009, "error": "复制[...]操作尚未执行完成,请稍后再试!"}
|
468
439
|
# {"state": false, "errno": 990009, "error": "移动[...]操作尚未执行完成,请稍后再试!"}
|
469
440
|
case 990009:
|
470
|
-
raise BusyOSError(
|
441
|
+
raise BusyOSError(EBUSY, resp)
|
471
442
|
# {"state": false, "errno": 990023, "error": "操作的文件(夹)数量超过5万个"}
|
472
443
|
case 990023:
|
473
|
-
raise OperationalError(
|
444
|
+
raise OperationalError(ENOTSUP, resp)
|
474
445
|
# {"state": 0, "errno": 40100000, "error": "参数错误!"}
|
475
446
|
case 40100000:
|
476
|
-
raise OperationalError(
|
447
|
+
raise OperationalError(EINVAL, resp)
|
477
448
|
# {"state": 0, "errno": 40101004, "error": "IP登录异常,请稍候再登录!"}
|
478
449
|
case 40101004:
|
479
|
-
raise LoginError(
|
450
|
+
raise LoginError(EIO, resp)
|
480
451
|
# {"state": 0, "errno": 40101017, "error": "用户验证失败!"}
|
481
452
|
case 40101017:
|
482
|
-
raise AuthenticationError(
|
453
|
+
raise AuthenticationError(EIO, resp)
|
483
454
|
# {"state": 0, "errno": 40101032, "error": "请重新登录"}
|
484
455
|
case 40101032:
|
485
|
-
raise LoginError(
|
456
|
+
raise LoginError(EIO, resp)
|
486
457
|
elif "msg_code" in resp:
|
487
458
|
match resp["msg_code"]:
|
488
459
|
case 50028:
|
489
|
-
raise P115OSError(
|
460
|
+
raise P115OSError(EFBIG, resp)
|
490
461
|
case 70004:
|
491
|
-
raise IsADirectoryError(
|
462
|
+
raise IsADirectoryError(EISDIR, resp)
|
492
463
|
case 70005 | 70008:
|
493
|
-
raise FileNotFoundError(
|
494
|
-
raise P115OSError(
|
464
|
+
raise FileNotFoundError(ENOENT, resp)
|
465
|
+
raise P115OSError(EIO, resp)
|
495
466
|
if isinstance(resp, dict):
|
496
467
|
return check(resp)
|
497
468
|
elif isawaitable(resp):
|
@@ -499,7 +470,7 @@ def check_response(resp: dict | Awaitable[dict], /) -> dict | Coroutine[Any, Any
|
|
499
470
|
return check(await resp)
|
500
471
|
return check_await()
|
501
472
|
else:
|
502
|
-
raise P115OSError(
|
473
|
+
raise P115OSError(EIO, resp)
|
503
474
|
|
504
475
|
|
505
476
|
def normalize_attr_web(
|
@@ -1773,11 +1744,11 @@ class ClientRequestMixin:
|
|
1773
1744
|
print("[status=2] qrcode: signed in")
|
1774
1745
|
break
|
1775
1746
|
case -1:
|
1776
|
-
raise LoginError(
|
1747
|
+
raise LoginError(EIO, "[status=-1] qrcode: expired")
|
1777
1748
|
case -2:
|
1778
|
-
raise LoginError(
|
1749
|
+
raise LoginError(EIO, "[status=-2] qrcode: canceled")
|
1779
1750
|
case _:
|
1780
|
-
raise LoginError(
|
1751
|
+
raise LoginError(EIO, f"qrcode: aborted with {resp!r}")
|
1781
1752
|
if app:
|
1782
1753
|
return cls.login_qrcode_scan_result(
|
1783
1754
|
login_uid,
|
@@ -1871,11 +1842,11 @@ class ClientRequestMixin:
|
|
1871
1842
|
print("[status=2] qrcode: signed in")
|
1872
1843
|
break
|
1873
1844
|
case -1:
|
1874
|
-
raise LoginError(
|
1845
|
+
raise LoginError(EIO, "[status=-1] qrcode: expired")
|
1875
1846
|
case -2:
|
1876
|
-
raise LoginError(
|
1847
|
+
raise LoginError(EIO, "[status=-2] qrcode: canceled")
|
1877
1848
|
case _:
|
1878
|
-
raise LoginError(
|
1849
|
+
raise LoginError(EIO, f"qrcode: aborted with {resp!r}")
|
1879
1850
|
return cls.login_qrcode_access_token_open(
|
1880
1851
|
login_uid,
|
1881
1852
|
async_=async_,
|
@@ -2599,7 +2570,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2599
2570
|
url = info["url"]
|
2600
2571
|
if strict and not url:
|
2601
2572
|
raise IsADirectoryError(
|
2602
|
-
|
2573
|
+
EISDIR,
|
2603
2574
|
f"{fid} is a directory, with response {resp}",
|
2604
2575
|
)
|
2605
2576
|
return P115URL(
|
@@ -2613,7 +2584,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
2613
2584
|
headers=resp["headers"],
|
2614
2585
|
)
|
2615
2586
|
raise FileNotFoundError(
|
2616
|
-
|
2587
|
+
ENOENT,
|
2617
2588
|
f"no such pickcode: {pickcode!r}, with response {resp}",
|
2618
2589
|
)
|
2619
2590
|
if async_:
|
@@ -3506,44 +3477,6 @@ class P115OpenClient(ClientRequestMixin):
|
|
3506
3477
|
api = complete_proapi("/open/upload/resume", base_url)
|
3507
3478
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
3508
3479
|
|
3509
|
-
@overload
|
3510
|
-
def user_info(
|
3511
|
-
self,
|
3512
|
-
/,
|
3513
|
-
base_url: bool | str | Callable[[], str] = False,
|
3514
|
-
*,
|
3515
|
-
async_: Literal[False] = False,
|
3516
|
-
**request_kwargs,
|
3517
|
-
) -> dict:
|
3518
|
-
...
|
3519
|
-
@overload
|
3520
|
-
def user_info(
|
3521
|
-
self,
|
3522
|
-
/,
|
3523
|
-
base_url: bool | str | Callable[[], str] = False,
|
3524
|
-
*,
|
3525
|
-
async_: Literal[True],
|
3526
|
-
**request_kwargs,
|
3527
|
-
) -> Coroutine[Any, Any, dict]:
|
3528
|
-
...
|
3529
|
-
def user_info(
|
3530
|
-
self,
|
3531
|
-
/,
|
3532
|
-
base_url: bool | str | Callable[[], str] = False,
|
3533
|
-
*,
|
3534
|
-
async_: Literal[False, True] = False,
|
3535
|
-
**request_kwargs,
|
3536
|
-
) -> dict | Coroutine[Any, Any, dict]:
|
3537
|
-
"""获取用户信息
|
3538
|
-
|
3539
|
-
GET https://proapi.115.com/open/user/info
|
3540
|
-
|
3541
|
-
.. note::
|
3542
|
-
https://www.yuque.com/115yun/open/ot1litggzxa1czww
|
3543
|
-
"""
|
3544
|
-
api = complete_proapi("/open/user/info", base_url)
|
3545
|
-
return self.request(url=api, async_=async_, **request_kwargs)
|
3546
|
-
|
3547
3480
|
@overload
|
3548
3481
|
def upload_file_init(
|
3549
3482
|
self,
|
@@ -3779,6 +3712,8 @@ class P115OpenClient(ClientRequestMixin):
|
|
3779
3712
|
async_=async_, # type: ignore
|
3780
3713
|
**request_kwargs,
|
3781
3714
|
)
|
3715
|
+
if filesize == 0:
|
3716
|
+
filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
3782
3717
|
need_calc_filesha1 = not filesha1 and multipart_resume_data is None
|
3783
3718
|
read_range_bytes_or_hash: None | Callable = None
|
3784
3719
|
try:
|
@@ -3787,7 +3722,9 @@ class P115OpenClient(ClientRequestMixin):
|
|
3787
3722
|
pass
|
3788
3723
|
if isinstance(file, Buffer):
|
3789
3724
|
filesize = buffer_length(file)
|
3790
|
-
if
|
3725
|
+
if filesize == 0:
|
3726
|
+
filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
3727
|
+
elif need_calc_filesha1:
|
3791
3728
|
filesha1 = sha1(file).hexdigest()
|
3792
3729
|
if multipart_resume_data is None and filesize >= 1 << 20:
|
3793
3730
|
view = memoryview(file)
|
@@ -3840,7 +3777,9 @@ class P115OpenClient(ClientRequestMixin):
|
|
3840
3777
|
filesize = (yield seek(0, 2)) - curpos
|
3841
3778
|
finally:
|
3842
3779
|
yield seek(curpos)
|
3843
|
-
if
|
3780
|
+
if filesize == 0:
|
3781
|
+
filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
3782
|
+
elif multipart_resume_data is None and filesize >= 1 << 20:
|
3844
3783
|
read: Callable[[int], Buffer] | Callable[[int], Awaitable[Buffer]]
|
3845
3784
|
if seekable:
|
3846
3785
|
if async_:
|
@@ -3897,16 +3836,24 @@ class P115OpenClient(ClientRequestMixin):
|
|
3897
3836
|
url = cast(str, multipart_resume_data.get("url", ""))
|
3898
3837
|
if not url:
|
3899
3838
|
url = self.upload_endpoint_url(bucket, object)
|
3900
|
-
|
3901
|
-
|
3902
|
-
|
3839
|
+
callback_var = loads(multipart_resume_data["callback"]["callback_var"])
|
3840
|
+
yield self.upload_resume_open(
|
3841
|
+
{
|
3842
|
+
"fileid": object,
|
3843
|
+
"file_size": multipart_resume_data["filesize"],
|
3844
|
+
"target": callback_var["x:target"],
|
3845
|
+
"pick_code": callback_var["x:pick_code"],
|
3846
|
+
},
|
3847
|
+
async_=async_,
|
3848
|
+
**request_kwargs,
|
3849
|
+
)
|
3903
3850
|
return oss_multipart_upload(
|
3904
3851
|
self.request,
|
3905
3852
|
file, # type: ignore
|
3906
3853
|
url=url,
|
3907
3854
|
bucket=bucket,
|
3908
3855
|
object=object,
|
3909
|
-
token=
|
3856
|
+
token=self.upload_token,
|
3910
3857
|
callback=multipart_resume_data["callback"],
|
3911
3858
|
upload_id=multipart_resume_data["upload_id"],
|
3912
3859
|
partsize=multipart_resume_data["partsize"],
|
@@ -3941,7 +3888,7 @@ class P115OpenClient(ClientRequestMixin):
|
|
3941
3888
|
case 1:
|
3942
3889
|
bucket, object, callback = data["bucket"], data["object"], data["callback"]
|
3943
3890
|
case _:
|
3944
|
-
raise P115OSError(
|
3891
|
+
raise P115OSError(EINVAL, resp)
|
3945
3892
|
url = self.upload_endpoint_url(bucket, object)
|
3946
3893
|
token = self.upload_token
|
3947
3894
|
if partsize <= 0:
|
@@ -3976,6 +3923,44 @@ class P115OpenClient(ClientRequestMixin):
|
|
3976
3923
|
)
|
3977
3924
|
return run_gen_step(gen_step, async_=async_)
|
3978
3925
|
|
3926
|
+
@overload
|
3927
|
+
def user_info(
|
3928
|
+
self,
|
3929
|
+
/,
|
3930
|
+
base_url: bool | str | Callable[[], str] = False,
|
3931
|
+
*,
|
3932
|
+
async_: Literal[False] = False,
|
3933
|
+
**request_kwargs,
|
3934
|
+
) -> dict:
|
3935
|
+
...
|
3936
|
+
@overload
|
3937
|
+
def user_info(
|
3938
|
+
self,
|
3939
|
+
/,
|
3940
|
+
base_url: bool | str | Callable[[], str] = False,
|
3941
|
+
*,
|
3942
|
+
async_: Literal[True],
|
3943
|
+
**request_kwargs,
|
3944
|
+
) -> Coroutine[Any, Any, dict]:
|
3945
|
+
...
|
3946
|
+
def user_info(
|
3947
|
+
self,
|
3948
|
+
/,
|
3949
|
+
base_url: bool | str | Callable[[], str] = False,
|
3950
|
+
*,
|
3951
|
+
async_: Literal[False, True] = False,
|
3952
|
+
**request_kwargs,
|
3953
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
3954
|
+
"""获取用户信息
|
3955
|
+
|
3956
|
+
GET https://proapi.115.com/open/user/info
|
3957
|
+
|
3958
|
+
.. note::
|
3959
|
+
https://www.yuque.com/115yun/open/ot1litggzxa1czww
|
3960
|
+
"""
|
3961
|
+
api = complete_proapi("/open/user/info", base_url)
|
3962
|
+
return self.request(url=api, async_=async_, **request_kwargs)
|
3963
|
+
|
3979
3964
|
download_url_open = download_url
|
3980
3965
|
download_url_info_open = download_url_info
|
3981
3966
|
fs_copy_open = fs_copy
|
@@ -6314,7 +6299,7 @@ class P115Client(P115OpenClient):
|
|
6314
6299
|
url = info["url"]
|
6315
6300
|
if strict and not url:
|
6316
6301
|
raise IsADirectoryError(
|
6317
|
-
|
6302
|
+
EISDIR,
|
6318
6303
|
f"{fid} is a directory, with response {resp}",
|
6319
6304
|
)
|
6320
6305
|
return P115URL(
|
@@ -6328,7 +6313,7 @@ class P115Client(P115OpenClient):
|
|
6328
6313
|
headers=resp["headers"],
|
6329
6314
|
)
|
6330
6315
|
raise FileNotFoundError(
|
6331
|
-
|
6316
|
+
ENOENT,
|
6332
6317
|
f"no such pickcode: {pickcode!r}, with response {resp}",
|
6333
6318
|
)
|
6334
6319
|
if async_:
|
@@ -9245,6 +9230,53 @@ class P115Client(P115OpenClient):
|
|
9245
9230
|
payload["custom_order"] = 1
|
9246
9231
|
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
9247
9232
|
|
9233
|
+
@overload
|
9234
|
+
def fs_files_blank_document(
|
9235
|
+
self,
|
9236
|
+
payload: str | dict,
|
9237
|
+
/,
|
9238
|
+
base_url: bool | str | Callable[[], str] = False,
|
9239
|
+
*,
|
9240
|
+
async_: Literal[False] = False,
|
9241
|
+
**request_kwargs,
|
9242
|
+
) -> dict:
|
9243
|
+
...
|
9244
|
+
@overload
|
9245
|
+
def fs_files_blank_document(
|
9246
|
+
self,
|
9247
|
+
payload: str | dict,
|
9248
|
+
/,
|
9249
|
+
base_url: bool | str | Callable[[], str] = False,
|
9250
|
+
*,
|
9251
|
+
async_: Literal[True],
|
9252
|
+
**request_kwargs,
|
9253
|
+
) -> Coroutine[Any, Any, dict]:
|
9254
|
+
...
|
9255
|
+
def fs_files_blank_document(
|
9256
|
+
self,
|
9257
|
+
payload: str | dict,
|
9258
|
+
/,
|
9259
|
+
base_url: bool | str | Callable[[], str] = False,
|
9260
|
+
*,
|
9261
|
+
async_: Literal[False, True] = False,
|
9262
|
+
**request_kwargs,
|
9263
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
9264
|
+
"""新建空白 office 文件
|
9265
|
+
|
9266
|
+
POST https://webapi.115.com/files/blank_document
|
9267
|
+
|
9268
|
+
:payload:
|
9269
|
+
- file_name: str 💡 文件名,不含后缀
|
9270
|
+
- pid: int | str = 0 💡 目录 id
|
9271
|
+
- type: 1 | 2 | 3 = 1 💡 1:Word文档(.docx) 2:Excel表格(.xlsx) 3:PPT文稿(.pptx)
|
9272
|
+
"""
|
9273
|
+
api = complete_webapi("/files/blank_document", base_url=base_url)
|
9274
|
+
if isinstance(payload, str):
|
9275
|
+
payload = {"pid": 0, "type": 1, "file_name": payload}
|
9276
|
+
else:
|
9277
|
+
payload = {"pid": 0, "type": 1, **payload}
|
9278
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
9279
|
+
|
9248
9280
|
@overload
|
9249
9281
|
def fs_files_history(
|
9250
9282
|
self,
|
@@ -9329,7 +9361,7 @@ class P115Client(P115OpenClient):
|
|
9329
9361
|
POST https://webapi.115.com/files/history
|
9330
9362
|
|
9331
9363
|
:payload:
|
9332
|
-
- pick_code: str
|
9364
|
+
- pick_code: str 💡 文件的提取码
|
9333
9365
|
- op: str = "update" 💡 操作类型,具体有哪些还需要再研究
|
9334
9366
|
- category: int = <default>
|
9335
9367
|
- definition: int = <default> 💡 视频清晰度
|
@@ -17193,13 +17225,13 @@ class P115Client(P115OpenClient):
|
|
17193
17225
|
file_id = payload["file_id"]
|
17194
17226
|
if not info:
|
17195
17227
|
raise FileNotFoundError(
|
17196
|
-
|
17228
|
+
ENOENT,
|
17197
17229
|
f"no such id: {file_id!r}, with response {resp}",
|
17198
17230
|
)
|
17199
17231
|
url = info["url"]
|
17200
17232
|
if strict and not url:
|
17201
17233
|
raise IsADirectoryError(
|
17202
|
-
|
17234
|
+
EISDIR,
|
17203
17235
|
f"{file_id} is a directory, with response {resp}",
|
17204
17236
|
)
|
17205
17237
|
return P115URL(
|
@@ -17863,8 +17895,8 @@ class P115Client(P115OpenClient):
|
|
17863
17895
|
|
17864
17896
|
@overload
|
17865
17897
|
def share_skip_login_download_url(
|
17866
|
-
self,
|
17867
|
-
payload: int | str | dict,
|
17898
|
+
self: int | str | dict | P115Client,
|
17899
|
+
payload: None | int | str | dict = None,
|
17868
17900
|
/,
|
17869
17901
|
url: str = "",
|
17870
17902
|
strict: bool = True,
|
@@ -17877,8 +17909,8 @@ class P115Client(P115OpenClient):
|
|
17877
17909
|
...
|
17878
17910
|
@overload
|
17879
17911
|
def share_skip_login_download_url(
|
17880
|
-
self,
|
17881
|
-
payload: int | str | dict,
|
17912
|
+
self: int | str | dict | P115Client,
|
17913
|
+
payload: None | int | str | dict = None,
|
17882
17914
|
/,
|
17883
17915
|
url: str = "",
|
17884
17916
|
strict: bool = True,
|
@@ -17890,8 +17922,8 @@ class P115Client(P115OpenClient):
|
|
17890
17922
|
) -> Coroutine[Any, Any, P115URL]:
|
17891
17923
|
...
|
17892
17924
|
def share_skip_login_download_url(
|
17893
|
-
self,
|
17894
|
-
payload: int | str | dict,
|
17925
|
+
self: int | str | dict | P115Client,
|
17926
|
+
payload: None | int | str | dict = None,
|
17895
17927
|
/,
|
17896
17928
|
url: str = "",
|
17897
17929
|
strict: bool = True,
|
@@ -17903,6 +17935,9 @@ class P115Client(P115OpenClient):
|
|
17903
17935
|
) -> P115URL | Coroutine[Any, Any, P115URL]:
|
17904
17936
|
"""获取分享链接中某个文件的下载链接
|
17905
17937
|
|
17938
|
+
.. important::
|
17939
|
+
这个函数可以作为 staticmethod 使用,只要 `self` 不是 P115Client 类型,此时不需要登录
|
17940
|
+
|
17906
17941
|
:param payload: 请求参数,如果为 int 或 str,则视为 `file_id`
|
17907
17942
|
|
17908
17943
|
- file_id: int | str 💡 文件 id
|
@@ -17918,6 +17953,12 @@ class P115Client(P115OpenClient):
|
|
17918
17953
|
|
17919
17954
|
:return: 下载链接
|
17920
17955
|
"""
|
17956
|
+
if isinstance(self, P115Client):
|
17957
|
+
assert payload is not None
|
17958
|
+
inst: P115Client | type[P115Client] = self
|
17959
|
+
else:
|
17960
|
+
payload = self
|
17961
|
+
inst = __class__ # type: ignore
|
17921
17962
|
if isinstance(payload, (int, str)):
|
17922
17963
|
payload = {"file_id": payload}
|
17923
17964
|
else:
|
@@ -17928,21 +17969,21 @@ class P115Client(P115OpenClient):
|
|
17928
17969
|
payload["share_code"] = share_payload["share_code"]
|
17929
17970
|
payload["receive_code"] = share_payload["receive_code"] or ""
|
17930
17971
|
if use_web_api:
|
17931
|
-
resp =
|
17972
|
+
resp = inst.share_skip_login_download_url_web(payload, async_=async_, **request_kwargs)
|
17932
17973
|
else:
|
17933
|
-
resp =
|
17974
|
+
resp = inst.share_skip_login_download_url_app(payload, app=app, async_=async_, **request_kwargs)
|
17934
17975
|
def get_url(resp: dict, /) -> P115URL:
|
17935
17976
|
info = check_response(resp)["data"]
|
17936
17977
|
file_id = payload["file_id"]
|
17937
17978
|
if not info:
|
17938
17979
|
raise FileNotFoundError(
|
17939
|
-
|
17980
|
+
ENOENT,
|
17940
17981
|
f"no such id: {file_id!r}, with response {resp}",
|
17941
17982
|
)
|
17942
17983
|
url = info["url"]
|
17943
17984
|
if strict and not url:
|
17944
17985
|
raise IsADirectoryError(
|
17945
|
-
|
17986
|
+
EISDIR,
|
17946
17987
|
f"{file_id} is a directory, with response {resp}",
|
17947
17988
|
)
|
17948
17989
|
return P115URL(
|
@@ -17962,8 +18003,8 @@ class P115Client(P115OpenClient):
|
|
17962
18003
|
|
17963
18004
|
@overload
|
17964
18005
|
def share_skip_login_download_url_app(
|
17965
|
-
self,
|
17966
|
-
payload: dict,
|
18006
|
+
self: dict | P115Client,
|
18007
|
+
payload: None | dict = None,
|
17967
18008
|
/,
|
17968
18009
|
app: str = "",
|
17969
18010
|
base_url: bool | str | Callable[[], str] = False,
|
@@ -17974,8 +18015,8 @@ class P115Client(P115OpenClient):
|
|
17974
18015
|
...
|
17975
18016
|
@overload
|
17976
18017
|
def share_skip_login_download_url_app(
|
17977
|
-
self,
|
17978
|
-
payload: dict,
|
18018
|
+
self: dict | P115Client,
|
18019
|
+
payload: None | dict = None,
|
17979
18020
|
/,
|
17980
18021
|
app: str = "",
|
17981
18022
|
base_url: bool | str | Callable[[], str] = False,
|
@@ -17985,8 +18026,8 @@ class P115Client(P115OpenClient):
|
|
17985
18026
|
) -> Coroutine[Any, Any, dict]:
|
17986
18027
|
...
|
17987
18028
|
def share_skip_login_download_url_app(
|
17988
|
-
self,
|
17989
|
-
payload: dict,
|
18029
|
+
self: dict | P115Client,
|
18030
|
+
payload: None | dict = None,
|
17990
18031
|
/,
|
17991
18032
|
app: str = "",
|
17992
18033
|
base_url: bool | str | Callable[[], str] = False,
|
@@ -17998,14 +18039,20 @@ class P115Client(P115OpenClient):
|
|
17998
18039
|
|
17999
18040
|
POST https://proapi.115.com/app/share/skip_login_downurl
|
18000
18041
|
|
18042
|
+
.. important::
|
18043
|
+
这个函数可以作为 staticmethod 使用,只要 `self` 不是 P115Client 类型,此时不需要登录
|
18044
|
+
|
18001
18045
|
:payload:
|
18002
18046
|
- file_id: int | str
|
18003
18047
|
- receive_code: str
|
18004
18048
|
- share_code: str
|
18005
18049
|
"""
|
18050
|
+
if isinstance(self, dict):
|
18051
|
+
payload = self
|
18052
|
+
else:
|
18053
|
+
assert payload is not None
|
18006
18054
|
if app:
|
18007
18055
|
api = complete_proapi("/2.0/share/skip_login_downurl", base_url, app)
|
18008
|
-
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
18009
18056
|
else:
|
18010
18057
|
api = complete_proapi("/app/share/skip_login_downurl", base_url)
|
18011
18058
|
def parse(resp, content: bytes, /) -> dict:
|
@@ -18015,12 +18062,20 @@ class P115Client(P115OpenClient):
|
|
18015
18062
|
return resp
|
18016
18063
|
request_kwargs.setdefault("parse", parse)
|
18017
18064
|
payload = {"data": rsa_encode(dumps(payload)).decode()}
|
18065
|
+
if isinstance(self, P115Client):
|
18018
18066
|
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
18067
|
+
else:
|
18068
|
+
request_kwargs.setdefault("parse", default_parse)
|
18069
|
+
request = request_kwargs.pop("request", None)
|
18070
|
+
if request is None:
|
18071
|
+
return get_default_request()(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
18072
|
+
else:
|
18073
|
+
return request(url=api, method="POST", data=payload, **request_kwargs)
|
18019
18074
|
|
18020
18075
|
@overload
|
18021
18076
|
def share_skip_login_download_url_web(
|
18022
|
-
self,
|
18023
|
-
payload: dict,
|
18077
|
+
self: dict | P115Client,
|
18078
|
+
payload: None | dict = None,
|
18024
18079
|
/,
|
18025
18080
|
base_url: bool | str | Callable[[], str] = False,
|
18026
18081
|
*,
|
@@ -18030,8 +18085,8 @@ class P115Client(P115OpenClient):
|
|
18030
18085
|
...
|
18031
18086
|
@overload
|
18032
18087
|
def share_skip_login_download_url_web(
|
18033
|
-
self,
|
18034
|
-
payload: dict,
|
18088
|
+
self: dict | P115Client,
|
18089
|
+
payload: None | dict = None,
|
18035
18090
|
/,
|
18036
18091
|
base_url: bool | str | Callable[[], str] = False,
|
18037
18092
|
*,
|
@@ -18040,8 +18095,8 @@ class P115Client(P115OpenClient):
|
|
18040
18095
|
) -> Coroutine[Any, Any, dict]:
|
18041
18096
|
...
|
18042
18097
|
def share_skip_login_download_url_web(
|
18043
|
-
self,
|
18044
|
-
payload: dict,
|
18098
|
+
self: dict | P115Client,
|
18099
|
+
payload: None | dict = None,
|
18045
18100
|
/,
|
18046
18101
|
base_url: bool | str | Callable[[], str] = False,
|
18047
18102
|
*,
|
@@ -18052,13 +18107,28 @@ class P115Client(P115OpenClient):
|
|
18052
18107
|
|
18053
18108
|
POST https://webapi.115.com/share/skip_login_downurl
|
18054
18109
|
|
18110
|
+
.. important::
|
18111
|
+
这个函数可以作为 staticmethod 使用,只要 `self` 不是 P115Client 类型,此时不需要登录
|
18112
|
+
|
18055
18113
|
:payload:
|
18056
18114
|
- share_code: str 💡 分享码
|
18057
18115
|
- receive_code: str 💡 接收码(访问密码)
|
18058
18116
|
- file_id: int | str 💡 文件 id
|
18059
18117
|
"""
|
18060
18118
|
api = complete_webapi("/share/skip_login_downurl", base_url=base_url)
|
18061
|
-
|
18119
|
+
if isinstance(self, dict):
|
18120
|
+
payload = self
|
18121
|
+
else:
|
18122
|
+
assert payload is not None
|
18123
|
+
if isinstance(self, P115Client):
|
18124
|
+
return self.request(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
18125
|
+
else:
|
18126
|
+
request_kwargs.setdefault("parse", default_parse)
|
18127
|
+
request = request_kwargs.pop("request", None)
|
18128
|
+
if request is None:
|
18129
|
+
return get_default_request()(url=api, method="POST", data=payload, async_=async_, **request_kwargs)
|
18130
|
+
else:
|
18131
|
+
return request(url=api, method="POST", data=payload, **request_kwargs)
|
18062
18132
|
|
18063
18133
|
@overload
|
18064
18134
|
def share_skip_login_down_first(
|
@@ -18191,7 +18261,7 @@ class P115Client(P115OpenClient):
|
|
18191
18261
|
GET https://webapi.115.com/share/snap
|
18192
18262
|
|
18193
18263
|
.. important::
|
18194
|
-
这个函数可以作为 staticmethod 使用,只要 `self`
|
18264
|
+
这个函数可以作为 staticmethod 使用,只要 `self` 不是 P115Client 类型,此时不需要登录
|
18195
18265
|
|
18196
18266
|
否则,就是登录状态,但如果这个分享是你自己的,则可以不提供 receive_code,而且即使还在审核中,也能获取文件列表
|
18197
18267
|
|
@@ -18266,7 +18336,7 @@ class P115Client(P115OpenClient):
|
|
18266
18336
|
GET https://proapi.115.com/android/2.0/share/snap
|
18267
18337
|
|
18268
18338
|
.. important::
|
18269
|
-
这个函数可以作为 staticmethod 使用,只要 `self`
|
18339
|
+
这个函数可以作为 staticmethod 使用,只要 `self` 不是 P115Client 类型,此时不需要登录
|
18270
18340
|
|
18271
18341
|
否则,就是登录状态,但如果这个分享是你自己的,则可以不提供 receive_code,而且即使还在审核中,也能获取文件列表
|
18272
18342
|
|
@@ -19128,8 +19198,6 @@ class P115Client(P115OpenClient):
|
|
19128
19198
|
|
19129
19199
|
:return: 接口响应
|
19130
19200
|
"""
|
19131
|
-
if filesize >= 1 << 20 and read_range_bytes_or_hash is None:
|
19132
|
-
raise ValueError("filesize >= 1 MB, thus need pass the `read_range_bytes_or_hash` argument")
|
19133
19201
|
filesha1 = filesha1.upper()
|
19134
19202
|
target = f"U_1_{pid}"
|
19135
19203
|
def gen_step():
|
@@ -19315,8 +19383,6 @@ class P115Client(P115OpenClient):
|
|
19315
19383
|
)
|
19316
19384
|
return run_gen_step(gen_step, async_=async_)
|
19317
19385
|
|
19318
|
-
# TODO: 当文件 < 1 MB 时,文件不急着打开,需要时再打开
|
19319
|
-
# TODO: 对于上传空文件,有特别的速度(sha1写死)
|
19320
19386
|
@overload # type: ignore
|
19321
19387
|
def upload_file(
|
19322
19388
|
self,
|
@@ -19455,11 +19521,9 @@ class P115Client(P115OpenClient):
|
|
19455
19521
|
async_=async_, # type: ignore
|
19456
19522
|
**request_kwargs,
|
19457
19523
|
)
|
19458
|
-
|
19459
|
-
|
19460
|
-
|
19461
|
-
multipart_resume_data is None
|
19462
|
-
)
|
19524
|
+
if filesize == 0:
|
19525
|
+
filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
19526
|
+
need_calc_filesha1 = not filesha1 and not upload_directly and multipart_resume_data is None
|
19463
19527
|
read_range_bytes_or_hash: None | Callable = None
|
19464
19528
|
try:
|
19465
19529
|
file = getattr(file, "getbuffer")()
|
@@ -19467,7 +19531,9 @@ class P115Client(P115OpenClient):
|
|
19467
19531
|
pass
|
19468
19532
|
if isinstance(file, Buffer):
|
19469
19533
|
filesize = buffer_length(file)
|
19470
|
-
if
|
19534
|
+
if filesize == 0:
|
19535
|
+
filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
19536
|
+
elif need_calc_filesha1:
|
19471
19537
|
filesha1 = sha1(file).hexdigest()
|
19472
19538
|
if not upload_directly and multipart_resume_data is None and filesize >= 1 << 20:
|
19473
19539
|
view = memoryview(file)
|
@@ -19520,7 +19586,9 @@ class P115Client(P115OpenClient):
|
|
19520
19586
|
filesize = (yield seek(0, 2)) - curpos
|
19521
19587
|
finally:
|
19522
19588
|
yield seek(curpos)
|
19523
|
-
if
|
19589
|
+
if filesize == 0:
|
19590
|
+
filesha1 = "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
19591
|
+
elif not upload_directly and multipart_resume_data is None and filesize >= 1 << 20:
|
19524
19592
|
read: Callable[[int], Buffer] | Callable[[int], Awaitable[Buffer]]
|
19525
19593
|
if seekable:
|
19526
19594
|
if async_:
|
@@ -19577,16 +19645,24 @@ class P115Client(P115OpenClient):
|
|
19577
19645
|
url = cast(str, multipart_resume_data.get("url", ""))
|
19578
19646
|
if not url:
|
19579
19647
|
url = self.upload_endpoint_url(bucket, object)
|
19580
|
-
|
19581
|
-
|
19582
|
-
|
19648
|
+
callback_var = loads(multipart_resume_data["callback"]["callback_var"])
|
19649
|
+
yield self.upload_resume(
|
19650
|
+
{
|
19651
|
+
"fileid": object,
|
19652
|
+
"filesize": multipart_resume_data["filesize"],
|
19653
|
+
"target": callback_var["x:target"],
|
19654
|
+
"pickcode": callback_var["x:pick_code"],
|
19655
|
+
},
|
19656
|
+
async_=async_,
|
19657
|
+
**request_kwargs,
|
19658
|
+
)
|
19583
19659
|
return oss_multipart_upload(
|
19584
19660
|
self.request,
|
19585
19661
|
file, # type: ignore
|
19586
19662
|
url=url,
|
19587
19663
|
bucket=bucket,
|
19588
19664
|
object=object,
|
19589
|
-
token=
|
19665
|
+
token=self.upload_token,
|
19590
19666
|
callback=multipart_resume_data["callback"],
|
19591
19667
|
upload_id=multipart_resume_data["upload_id"],
|
19592
19668
|
partsize=multipart_resume_data["partsize"],
|
@@ -19631,7 +19707,7 @@ class P115Client(P115OpenClient):
|
|
19631
19707
|
elif status == 1 and statuscode == 0:
|
19632
19708
|
bucket, object, callback = resp["bucket"], resp["object"], resp["callback"]
|
19633
19709
|
else:
|
19634
|
-
raise P115OSError(
|
19710
|
+
raise P115OSError(EINVAL, resp)
|
19635
19711
|
url = self.upload_endpoint_url(bucket, object)
|
19636
19712
|
token = self.upload_token
|
19637
19713
|
if partsize <= 0:
|
@@ -19781,11 +19857,10 @@ class P115Client(P115OpenClient):
|
|
19781
19857
|
return self.request(url=api, async_=async_, **request_kwargs)
|
19782
19858
|
|
19783
19859
|
@overload # type: ignore
|
19784
|
-
@staticmethod
|
19785
19860
|
def user_info(
|
19786
|
-
|
19861
|
+
self: int | str | dict | P115Client,
|
19862
|
+
payload: None | int | str | dict = None,
|
19787
19863
|
/,
|
19788
|
-
request: None | Callable = None,
|
19789
19864
|
base_url: bool | str | Callable[[], str] = False,
|
19790
19865
|
*,
|
19791
19866
|
async_: Literal[False] = False,
|
@@ -19793,22 +19868,20 @@ class P115Client(P115OpenClient):
|
|
19793
19868
|
) -> dict:
|
19794
19869
|
...
|
19795
19870
|
@overload
|
19796
|
-
@staticmethod
|
19797
19871
|
def user_info(
|
19798
|
-
|
19872
|
+
self: int | str | dict | P115Client,
|
19873
|
+
payload: None | int | str | dict = None,
|
19799
19874
|
/,
|
19800
|
-
request: None | Callable = None,
|
19801
19875
|
base_url: bool | str | Callable[[], str] = False,
|
19802
19876
|
*,
|
19803
19877
|
async_: Literal[True],
|
19804
19878
|
**request_kwargs,
|
19805
19879
|
) -> Coroutine[Any, Any, dict]:
|
19806
19880
|
...
|
19807
|
-
@staticmethod
|
19808
19881
|
def user_info(
|
19809
|
-
|
19882
|
+
self: int | str | dict | P115Client,
|
19883
|
+
payload: None | int | str | dict = None,
|
19810
19884
|
/,
|
19811
|
-
request: None | Callable = None,
|
19812
19885
|
base_url: bool | str | Callable[[], str] = False,
|
19813
19886
|
*,
|
19814
19887
|
async_: Literal[False, True] = False,
|
@@ -19818,19 +19891,31 @@ class P115Client(P115OpenClient):
|
|
19818
19891
|
|
19819
19892
|
GET https://my.115.com/proapi/3.0/index.php?method=user_info
|
19820
19893
|
|
19894
|
+
.. important::
|
19895
|
+
这个函数可以作为 staticmethod 使用,只要 `self` 不是 P115Client 类型,此时不需要登录
|
19896
|
+
|
19821
19897
|
:payload:
|
19822
19898
|
- uid: int | str
|
19823
19899
|
"""
|
19824
19900
|
api = complete_api("/proapi/3.0/index.php", "my", base_url=base_url)
|
19901
|
+
if isinstance(self, P115Client):
|
19902
|
+
if payload is None:
|
19903
|
+
payload = self.user_id
|
19904
|
+
else:
|
19905
|
+
payload = self
|
19825
19906
|
if isinstance(payload, (int, str)):
|
19826
19907
|
payload = {"uid": payload, "method": "user_info"}
|
19827
19908
|
else:
|
19828
19909
|
payload = {"method": "user_info", **payload}
|
19829
|
-
|
19830
|
-
|
19831
|
-
return get_default_request()(url=api, params=payload, async_=async_, **request_kwargs)
|
19910
|
+
if isinstance(self, P115Client):
|
19911
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
19832
19912
|
else:
|
19833
|
-
|
19913
|
+
request_kwargs.setdefault("parse", default_parse)
|
19914
|
+
request = request_kwargs.pop("request", None)
|
19915
|
+
if request is None:
|
19916
|
+
return get_default_request()(url=api, params=payload, async_=async_, **request_kwargs)
|
19917
|
+
else:
|
19918
|
+
return request(url=api, params=payload, **request_kwargs)
|
19834
19919
|
|
19835
19920
|
@overload
|
19836
19921
|
def user_my(
|
@@ -20363,6 +20448,49 @@ class P115Client(P115OpenClient):
|
|
20363
20448
|
api = complete_proapi("/vip/check_spw", base_url, app)
|
20364
20449
|
return self.request(url=api, async_=async_, **request_kwargs)
|
20365
20450
|
|
20451
|
+
@overload
|
20452
|
+
def user_vip_limit(
|
20453
|
+
self,
|
20454
|
+
payload: int | dict = 2,
|
20455
|
+
/,
|
20456
|
+
base_url: bool | str | Callable[[], str] = False,
|
20457
|
+
*,
|
20458
|
+
async_: Literal[False] = False,
|
20459
|
+
**request_kwargs,
|
20460
|
+
) -> dict:
|
20461
|
+
...
|
20462
|
+
@overload
|
20463
|
+
def user_vip_limit(
|
20464
|
+
self,
|
20465
|
+
payload: int | dict = 2,
|
20466
|
+
/,
|
20467
|
+
base_url: bool | str | Callable[[], str] = False,
|
20468
|
+
*,
|
20469
|
+
async_: Literal[True],
|
20470
|
+
**request_kwargs,
|
20471
|
+
) -> Coroutine[Any, Any, dict]:
|
20472
|
+
...
|
20473
|
+
def user_vip_limit(
|
20474
|
+
self,
|
20475
|
+
payload: int | dict = 2,
|
20476
|
+
/,
|
20477
|
+
base_url: bool | str | Callable[[], str] = False,
|
20478
|
+
*,
|
20479
|
+
async_: Literal[False, True] = False,
|
20480
|
+
**request_kwargs,
|
20481
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
20482
|
+
"""获取 vip 的某些限制
|
20483
|
+
|
20484
|
+
GET https://webapi.115.com/user/vip_limit
|
20485
|
+
|
20486
|
+
:payload:
|
20487
|
+
- feature: int = 2
|
20488
|
+
"""
|
20489
|
+
api = complete_webapi("/user/vip_limit", base_url=base_url)
|
20490
|
+
if isinstance(payload, int):
|
20491
|
+
payload = {"feature": payload}
|
20492
|
+
return self.request(url=api, params=payload, async_=async_, **request_kwargs)
|
20493
|
+
|
20366
20494
|
########## User Share API ##########
|
20367
20495
|
|
20368
20496
|
@overload
|
@@ -1,7 +1,7 @@
|
|
1
1
|
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
2
2
|
p115client/__init__.py,sha256=1mx7njuAlqcuEWONTjSiiGnXyyNyqOcJyNX1FMHqQ-4,214
|
3
3
|
p115client/_upload.py,sha256=j2XHz6-hc9qyfiF92aZY-LPJ3UgbB6e4Jy6CNGQ5rwk,29904
|
4
|
-
p115client/client.py,sha256
|
4
|
+
p115client/client.py,sha256=-ccBfbe6MxmR-YnKK3LAiqbdh6kKXrm142qgdbPqC14,712993
|
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
|
@@ -17,7 +17,7 @@ p115client/tool/request.py,sha256=SWsezW9EYZGS3R-TbZxMG-8bN3YWJ0-GzgvKlvRBSCM,70
|
|
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.3.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
21
|
+
p115client-0.0.5.8.3.dist-info/METADATA,sha256=X_28kGMwtVVlShi6LjvxgWsDpVHsDu0QUnhxEjOiId0,8232
|
22
|
+
p115client-0.0.5.8.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
23
|
+
p115client-0.0.5.8.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|