p123client 0.0.6__py3-none-any.whl → 0.0.6.2__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.
- p123client/client.py +240 -73
- p123client/exception.py +12 -1
- p123client/tool/__init__.py +5 -4
- {p123client-0.0.6.dist-info → p123client-0.0.6.2.dist-info}/METADATA +1 -1
- p123client-0.0.6.2.dist-info/RECORD +12 -0
- p123client-0.0.6.dist-info/RECORD +0 -12
- {p123client-0.0.6.dist-info → p123client-0.0.6.2.dist-info}/LICENSE +0 -0
- {p123client-0.0.6.dist-info → p123client-0.0.6.2.dist-info}/WHEEL +0 -0
p123client/client.py
CHANGED
@@ -6,8 +6,8 @@ from __future__ import annotations
|
|
6
6
|
__all__ = ["check_response", "P123OpenClient", "P123Client"]
|
7
7
|
|
8
8
|
from collections.abc import (
|
9
|
-
AsyncIterable, Awaitable, Buffer, Callable, Coroutine,
|
10
|
-
Iterable, Iterator, Mapping, MutableMapping,
|
9
|
+
AsyncIterable, Awaitable, Buffer, Callable, Coroutine,
|
10
|
+
ItemsView, Iterable, Iterator, Mapping, MutableMapping,
|
11
11
|
)
|
12
12
|
from errno import EIO, EISDIR, ENOENT
|
13
13
|
from functools import partial
|
@@ -17,7 +17,6 @@ from inspect import isawaitable
|
|
17
17
|
from itertools import chain
|
18
18
|
from os import fsdecode, fstat, PathLike
|
19
19
|
from os.path import basename
|
20
|
-
from platform import system
|
21
20
|
from re import compile as re_compile
|
22
21
|
from tempfile import TemporaryFile
|
23
22
|
from typing import cast, overload, Any, Literal
|
@@ -40,18 +39,6 @@ from yarl import URL
|
|
40
39
|
from .exception import P123OSError, P123BrokenUpload
|
41
40
|
|
42
41
|
|
43
|
-
# 当前的系统平台
|
44
|
-
SYS_PLATFORM = system()
|
45
|
-
# 替换表,用于半角转全角,包括了 Windows 中不允许出现在文件名中的字符
|
46
|
-
match SYS_PLATFORM:
|
47
|
-
case "Windows":
|
48
|
-
NAME_TANSTAB_FULLWIDH = {c: chr(c+65248) for c in b"\\/:*?|><"}
|
49
|
-
case "Darwin":
|
50
|
-
NAME_TANSTAB_FULLWIDH = {ord("/"): ":", ord(":"): ":"}
|
51
|
-
case _:
|
52
|
-
NAME_TANSTAB_FULLWIDH = {ord("/"): "/"}
|
53
|
-
# 查找大写字母(除了左边第 1 个)
|
54
|
-
CRE_UPPER_ALPHABET_sub = re_compile("(?<!^)[A-Z]").sub
|
55
42
|
# 默认使用的域名
|
56
43
|
DEFAULT_BASE_URL = "https://www.123pan.com/b"
|
57
44
|
DEFAULT_LOGIN_BASE_URL = "https://login.123pan.com"
|
@@ -120,6 +107,14 @@ def dict_to_lower_merge[K, V](
|
|
120
107
|
return m
|
121
108
|
|
122
109
|
|
110
|
+
def escape_filename(
|
111
|
+
s: str,
|
112
|
+
/,
|
113
|
+
table: dict[int, int | str] = {c: chr(c+65248) for c in b'"\\/:*?|><'}, # type: ignore
|
114
|
+
) -> str:
|
115
|
+
return s.translate(table)
|
116
|
+
|
117
|
+
|
123
118
|
def items[K, V](
|
124
119
|
m: Mapping[K, V] | Iterable[tuple[K, V]],
|
125
120
|
/,
|
@@ -710,6 +705,170 @@ class P123OpenClient:
|
|
710
705
|
})
|
711
706
|
return self.request(api, params=payload, async_=async_, **request_kwargs)
|
712
707
|
|
708
|
+
@overload
|
709
|
+
def dlink_m3u8(
|
710
|
+
self,
|
711
|
+
payload: dict | int | str,
|
712
|
+
/,
|
713
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
714
|
+
*,
|
715
|
+
async_: Literal[False] = False,
|
716
|
+
**request_kwargs,
|
717
|
+
) -> dict:
|
718
|
+
...
|
719
|
+
@overload
|
720
|
+
def dlink_m3u8(
|
721
|
+
self,
|
722
|
+
payload: dict | int | str,
|
723
|
+
/,
|
724
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
725
|
+
*,
|
726
|
+
async_: Literal[True],
|
727
|
+
**request_kwargs,
|
728
|
+
) -> Coroutine[Any, Any, dict]:
|
729
|
+
...
|
730
|
+
def dlink_m3u8(
|
731
|
+
self,
|
732
|
+
payload: dict | int | str,
|
733
|
+
/,
|
734
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
735
|
+
*,
|
736
|
+
async_: Literal[False, True] = False,
|
737
|
+
**request_kwargs,
|
738
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
739
|
+
"""获取直链转码链接
|
740
|
+
|
741
|
+
GET https://open-api.123pan.com/api/v1/direct-link/get/m3u8
|
742
|
+
|
743
|
+
:payload:
|
744
|
+
- fileID: int 💡 文件 id
|
745
|
+
|
746
|
+
:return:
|
747
|
+
响应数据的 data 字段是一个字典,键值如下:
|
748
|
+
|
749
|
+
+---------------------+--------+----------+--------------------------------------------------------------+
|
750
|
+
| 名称 | 类型 | 是否必填 | 说明 |
|
751
|
+
+=====================+========+==========+==============================================================+
|
752
|
+
| list | array | 必填 | 响应列表 |
|
753
|
+
+---------------------+--------+----------+--------------------------------------------------------------|
|
754
|
+
| list[*].resolutions | string | 必填 | 分辨率 |
|
755
|
+
+---------------------+--------+----------+--------------------------------------------------------------|
|
756
|
+
| list[*].address | string | 必填 | 播放地址。请将播放地址放入支持的 hls 协议的播放器中进行播放。|
|
757
|
+
| | | | 示例在线播放地址: https://m3u8-player.com/ |
|
758
|
+
| | | | 请注意:转码链接播放过程中将会消耗您的直链流量。 |
|
759
|
+
| | | | 如果您开启了直链鉴权,也需要将转码链接根据鉴权指引进行签名。 |
|
760
|
+
+---------------------+--------+----------+--------------------------------------------------------------+
|
761
|
+
"""
|
762
|
+
api = complete_url("/api/v1/direct-link/get/m3u8", base_url)
|
763
|
+
if not isinstance(payload, dict):
|
764
|
+
payload = {"fileID": payload}
|
765
|
+
return self.request(api, params=payload, async_=async_, **request_kwargs)
|
766
|
+
|
767
|
+
@overload
|
768
|
+
def dlink_transcode(
|
769
|
+
self,
|
770
|
+
payload: dict | int | str | Iterable[int | str],
|
771
|
+
/,
|
772
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
773
|
+
*,
|
774
|
+
async_: Literal[False] = False,
|
775
|
+
**request_kwargs,
|
776
|
+
) -> dict:
|
777
|
+
...
|
778
|
+
@overload
|
779
|
+
def dlink_transcode(
|
780
|
+
self,
|
781
|
+
payload: dict | int | str | Iterable[int | str],
|
782
|
+
/,
|
783
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
784
|
+
*,
|
785
|
+
async_: Literal[True],
|
786
|
+
**request_kwargs,
|
787
|
+
) -> Coroutine[Any, Any, dict]:
|
788
|
+
...
|
789
|
+
def dlink_transcode(
|
790
|
+
self,
|
791
|
+
payload: dict | int | str | Iterable[int | str],
|
792
|
+
/,
|
793
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
794
|
+
*,
|
795
|
+
async_: Literal[False, True] = False,
|
796
|
+
**request_kwargs,
|
797
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
798
|
+
"""发起直链转码
|
799
|
+
|
800
|
+
POST https://open-api.123pan.com/api/v1/direct-link/doTranscode
|
801
|
+
|
802
|
+
:payload:
|
803
|
+
- ids: list[int] 💡 视频文件 id 列表
|
804
|
+
"""
|
805
|
+
api = complete_url("/api/v1/direct-link/doTranscode", base_url)
|
806
|
+
if not isinstance(payload, dict):
|
807
|
+
if isinstance(payload, (int, str)):
|
808
|
+
payload = [payload]
|
809
|
+
elif not isinstance(payload, (tuple, list)):
|
810
|
+
payload = list(payload)
|
811
|
+
payload = {"ids": payload}
|
812
|
+
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
813
|
+
|
814
|
+
@overload
|
815
|
+
def dlink_transcode_query(
|
816
|
+
self,
|
817
|
+
payload: dict | int | str | Iterable[int | str],
|
818
|
+
/,
|
819
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
820
|
+
*,
|
821
|
+
async_: Literal[False] = False,
|
822
|
+
**request_kwargs,
|
823
|
+
) -> dict:
|
824
|
+
...
|
825
|
+
@overload
|
826
|
+
def dlink_transcode_query(
|
827
|
+
self,
|
828
|
+
payload: dict | int | str | Iterable[int | str],
|
829
|
+
/,
|
830
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
831
|
+
*,
|
832
|
+
async_: Literal[True],
|
833
|
+
**request_kwargs,
|
834
|
+
) -> Coroutine[Any, Any, dict]:
|
835
|
+
...
|
836
|
+
def dlink_transcode_query(
|
837
|
+
self,
|
838
|
+
payload: dict | int | str | Iterable[int | str],
|
839
|
+
/,
|
840
|
+
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
841
|
+
*,
|
842
|
+
async_: Literal[False, True] = False,
|
843
|
+
**request_kwargs,
|
844
|
+
) -> dict | Coroutine[Any, Any, dict]:
|
845
|
+
"""查询直链转码进度
|
846
|
+
|
847
|
+
POST https://open-api.123pan.com/api/v1/direct-link/queryTranscode
|
848
|
+
|
849
|
+
:payload:
|
850
|
+
- ids: str 💡 视频文件 id 列表
|
851
|
+
|
852
|
+
:return:
|
853
|
+
响应数据的 data 字段是一个字典,键值如下:
|
854
|
+
|
855
|
+
+-----------+-------+----------+-------------------------------------------+
|
856
|
+
| 名称 | 类型 | 是否必填 | 说明 |
|
857
|
+
+===========+=======+==========+===========================================+
|
858
|
+
| noneList | array | 必填 | 未发起过转码的 ID |
|
859
|
+
| errorList | array | 必填 | 错误文件ID列表,这些文件ID无法进行转码操作 |
|
860
|
+
| success | array | 必填 | 转码成功的文件ID列表 |
|
861
|
+
+-----------+-------+----------+-------------------------------------------+
|
862
|
+
"""
|
863
|
+
api = complete_url("/api/v1/direct-link/queryTranscode", base_url)
|
864
|
+
if not isinstance(payload, dict):
|
865
|
+
if isinstance(payload, (int, str)):
|
866
|
+
payload = [payload]
|
867
|
+
elif not isinstance(payload, (tuple, list)):
|
868
|
+
payload = list(payload)
|
869
|
+
payload = {"ids": payload}
|
870
|
+
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
871
|
+
|
713
872
|
@overload
|
714
873
|
def dlink_url(
|
715
874
|
self,
|
@@ -751,7 +910,7 @@ class P123OpenClient:
|
|
751
910
|
https://123yunpan.yuque.com/org-wiki-123yunpan-muaork/cr6ced/tdxfsmtemp4gu4o2
|
752
911
|
|
753
912
|
:payload:
|
754
|
-
- fileID: int 💡
|
913
|
+
- fileID: int 💡 文件 id
|
755
914
|
"""
|
756
915
|
api = complete_url("/api/v1/direct-link/url", base_url)
|
757
916
|
if not isinstance(payload, dict):
|
@@ -1596,7 +1755,7 @@ class P123OpenClient:
|
|
1596
1755
|
https://123yunpan.yuque.com/org-wiki-123yunpan-muaork/cr6ced/trahy3lmds4o0i3r
|
1597
1756
|
|
1598
1757
|
:payload:
|
1599
|
-
- fileIDs: list[int] 💡 文件 id
|
1758
|
+
- fileIDs: list[int] 💡 文件 id 列表
|
1600
1759
|
- toParentFileID: int = 0 💡 要移动到的目标目录 id,默认为根目录
|
1601
1760
|
- sourceType: int = 1 💡 复制来源:1:云盘
|
1602
1761
|
- type: int = 1 💡 业务类型,固定为 1
|
@@ -1770,7 +1929,7 @@ class P123OpenClient:
|
|
1770
1929
|
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
1771
1930
|
|
1772
1931
|
@overload
|
1773
|
-
def
|
1932
|
+
def oss_detail(
|
1774
1933
|
self,
|
1775
1934
|
payload: dict | int | str,
|
1776
1935
|
/,
|
@@ -1781,7 +1940,7 @@ class P123OpenClient:
|
|
1781
1940
|
) -> dict:
|
1782
1941
|
...
|
1783
1942
|
@overload
|
1784
|
-
def
|
1943
|
+
def oss_detail(
|
1785
1944
|
self,
|
1786
1945
|
payload: dict | int | str,
|
1787
1946
|
/,
|
@@ -1791,7 +1950,7 @@ class P123OpenClient:
|
|
1791
1950
|
**request_kwargs,
|
1792
1951
|
) -> Coroutine[Any, Any, dict]:
|
1793
1952
|
...
|
1794
|
-
def
|
1953
|
+
def oss_detail(
|
1795
1954
|
self,
|
1796
1955
|
payload: dict | int | str,
|
1797
1956
|
/,
|
@@ -2144,7 +2303,7 @@ class P123OpenClient:
|
|
2144
2303
|
|
2145
2304
|
:payload:
|
2146
2305
|
- filename: str 💡 文件名
|
2147
|
-
- duplicate: 0 | 1 | 2 = 0 💡 处理同名:0:
|
2306
|
+
- duplicate: 0 | 1 | 2 = 0 💡 处理同名:0: 跳过/报错 1: 保留/后缀编号 2: 替换/覆盖
|
2148
2307
|
- etag: str 💡 文件 md5
|
2149
2308
|
- parentFileID: int = 0 💡 父目录 id,默认为根目录
|
2150
2309
|
- size: int 💡 文件大小,单位:字节
|
@@ -2163,7 +2322,9 @@ class P123OpenClient:
|
|
2163
2322
|
}
|
2164
2323
|
"""
|
2165
2324
|
api = complete_url("/upload/v1/oss/file/create", base_url)
|
2166
|
-
payload = dict_to_lower_merge(payload,
|
2325
|
+
payload = dict_to_lower_merge(payload, type=1)
|
2326
|
+
if "duplicate" in payload and not payload["duplicate"]:
|
2327
|
+
del payload["duplicate"]
|
2167
2328
|
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
2168
2329
|
|
2169
2330
|
@overload
|
@@ -2437,7 +2598,7 @@ class P123OpenClient:
|
|
2437
2598
|
"""上传文件
|
2438
2599
|
|
2439
2600
|
.. note::
|
2440
|
-
|
2601
|
+
如果文件名中包含字符 "\\/:*?|><,则转换为对应的全角字符
|
2441
2602
|
|
2442
2603
|
.. admonition:: Reference
|
2443
2604
|
/API列表/图床/上传图片/💡上传流程说明
|
@@ -2571,7 +2732,7 @@ class P123OpenClient:
|
|
2571
2732
|
file_name = getattr(file, "name", "")
|
2572
2733
|
file_name = basename(file_name)
|
2573
2734
|
if file_name:
|
2574
|
-
file_name = file_name
|
2735
|
+
file_name = escape_filename(file_name)
|
2575
2736
|
else:
|
2576
2737
|
file_name = str(uuid4())
|
2577
2738
|
if file_size < 0:
|
@@ -2726,7 +2887,7 @@ class P123OpenClient:
|
|
2726
2887
|
:payload:
|
2727
2888
|
- fileIDList: str 💡 分享文件 id 列表,最多 100 个,用逗号,分隔连接
|
2728
2889
|
- shareExpire: 0 | 1 | 7 | 30 = 0 💡 分享链接有效期天数,0 为永久
|
2729
|
-
- shareName: str 💡 分享链接名称,须小于 35 个字符且不能包含特殊字符
|
2890
|
+
- shareName: str 💡 分享链接名称,须小于 35 个字符且不能包含特殊字符 "\\/:*?|><
|
2730
2891
|
- sharePwd: str = "" 💡 设置分享链接提取码
|
2731
2892
|
- trafficLimit: int = <default> 💡 免登陆限制流量,单位:字节
|
2732
2893
|
- trafficLimitSwitch: 1 | 2 = <default> 💡 免登录流量限制开关:1:关闭 2:打开
|
@@ -2781,7 +2942,7 @@ class P123OpenClient:
|
|
2781
2942
|
- isReward: 0 | 1 = 0 💡 是否开启打赏
|
2782
2943
|
- payAmount: int = 1 💡 金额,从 1 到 99,单位:元
|
2783
2944
|
- resourceDesc: str = "" 💡 资源描述
|
2784
|
-
- shareName: str 💡 分享链接名称,须小于 35 个字符且不能包含特殊字符
|
2945
|
+
- shareName: str 💡 分享链接名称,须小于 35 个字符且不能包含特殊字符 "\\/:*?|><
|
2785
2946
|
"""
|
2786
2947
|
api = complete_url("/api/v1/share/content-payment/create", base_url)
|
2787
2948
|
payload = dict_to_lower_merge(payload, {"payAmount": 1, "isReward": 0, "resourceDesc": ""})
|
@@ -2991,9 +3152,9 @@ class P123OpenClient:
|
|
2991
3152
|
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
2992
3153
|
|
2993
3154
|
@overload
|
2994
|
-
def
|
3155
|
+
def transcode_download_all(
|
2995
3156
|
self,
|
2996
|
-
payload: dict,
|
3157
|
+
payload: dict | int | str,
|
2997
3158
|
/,
|
2998
3159
|
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
2999
3160
|
*,
|
@@ -3002,9 +3163,9 @@ class P123OpenClient:
|
|
3002
3163
|
) -> dict:
|
3003
3164
|
...
|
3004
3165
|
@overload
|
3005
|
-
def
|
3166
|
+
def transcode_download_all(
|
3006
3167
|
self,
|
3007
|
-
payload: dict,
|
3168
|
+
payload: dict | int | str,
|
3008
3169
|
/,
|
3009
3170
|
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
3010
3171
|
*,
|
@@ -3012,37 +3173,41 @@ class P123OpenClient:
|
|
3012
3173
|
**request_kwargs,
|
3013
3174
|
) -> Coroutine[Any, Any, dict]:
|
3014
3175
|
...
|
3015
|
-
def
|
3176
|
+
def transcode_download_all(
|
3016
3177
|
self,
|
3017
|
-
payload: dict,
|
3178
|
+
payload: dict | int | str,
|
3018
3179
|
/,
|
3019
3180
|
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
3020
3181
|
*,
|
3021
3182
|
async_: Literal[False, True] = False,
|
3022
3183
|
**request_kwargs,
|
3023
3184
|
) -> dict | Coroutine[Any, Any, dict]:
|
3024
|
-
"""
|
3185
|
+
"""某个视频全部转码文件下载
|
3025
3186
|
|
3026
|
-
POST https://open-api.123pan.com/api/v1/transcode/
|
3187
|
+
POST https://open-api.123pan.com/api/v1/transcode/file/download/all
|
3188
|
+
|
3189
|
+
.. attention::
|
3190
|
+
该接口需要轮询去查询结果,建议 10s 一次
|
3027
3191
|
|
3028
3192
|
.. admonition:: Reference
|
3029
|
-
/API
|
3193
|
+
/API列表/视频转码/视频文件下载/某个视频全部转码文件下载
|
3030
3194
|
|
3031
|
-
https://123yunpan.yuque.com/org-wiki-123yunpan-muaork/cr6ced/
|
3195
|
+
https://123yunpan.yuque.com/org-wiki-123yunpan-muaork/cr6ced/yb7hrb0x2gym7xic
|
3032
3196
|
|
3033
3197
|
:payload:
|
3034
|
-
- fileId: int
|
3035
|
-
-
|
3036
|
-
- type: int 💡 文件类型:1:m3u8 2:ts
|
3037
|
-
- tsName: str 💡 下载 ts 文件时必须要指定名称,请参考查询某个视频的转码结果
|
3198
|
+
- fileId: int 💡 文件 id
|
3199
|
+
- zipName: str = f"转码{file_id}.zip" 💡 下载 zip 文件的名字
|
3038
3200
|
"""
|
3039
|
-
api = complete_url("/api/v1/transcode/
|
3201
|
+
api = complete_url("/api/v1/transcode/file/download/all", base_url)
|
3202
|
+
if not isinstance(payload, dict):
|
3203
|
+
payload = {"fileId": payload}
|
3204
|
+
payload = dict_to_lower_merge(payload, zipName=f"转码{payload.get('fileid', '')}.zip")
|
3040
3205
|
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
3041
3206
|
|
3042
3207
|
@overload
|
3043
|
-
def
|
3208
|
+
def transcode_m3u8_ts_download(
|
3044
3209
|
self,
|
3045
|
-
payload: dict
|
3210
|
+
payload: dict,
|
3046
3211
|
/,
|
3047
3212
|
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
3048
3213
|
*,
|
@@ -3051,9 +3216,9 @@ class P123OpenClient:
|
|
3051
3216
|
) -> dict:
|
3052
3217
|
...
|
3053
3218
|
@overload
|
3054
|
-
def
|
3219
|
+
def transcode_m3u8_ts_download(
|
3055
3220
|
self,
|
3056
|
-
payload: dict
|
3221
|
+
payload: dict,
|
3057
3222
|
/,
|
3058
3223
|
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
3059
3224
|
*,
|
@@ -3061,35 +3226,31 @@ class P123OpenClient:
|
|
3061
3226
|
**request_kwargs,
|
3062
3227
|
) -> Coroutine[Any, Any, dict]:
|
3063
3228
|
...
|
3064
|
-
def
|
3229
|
+
def transcode_m3u8_ts_download(
|
3065
3230
|
self,
|
3066
|
-
payload: dict
|
3231
|
+
payload: dict,
|
3067
3232
|
/,
|
3068
3233
|
base_url: str | Callable[[], str] = DEFAULT_OPEN_BASE_URL,
|
3069
3234
|
*,
|
3070
3235
|
async_: Literal[False, True] = False,
|
3071
3236
|
**request_kwargs,
|
3072
3237
|
) -> dict | Coroutine[Any, Any, dict]:
|
3073
|
-
"""
|
3074
|
-
|
3075
|
-
POST https://open-api.123pan.com/api/v1/transcode/file/download/all
|
3238
|
+
"""单个转码文件下载(m3u8或ts)
|
3076
3239
|
|
3077
|
-
|
3078
|
-
该接口需要轮询去查询结果,建议 10s 一次
|
3240
|
+
POST https://open-api.123pan.com/api/v1/transcode/m3u8_ts/download
|
3079
3241
|
|
3080
3242
|
.. admonition:: Reference
|
3081
|
-
/API
|
3243
|
+
/API列表/视频转码/视频文件下载/单个转码文件下载(m3u8或ts)
|
3082
3244
|
|
3083
|
-
https://123yunpan.yuque.com/org-wiki-123yunpan-muaork/cr6ced/
|
3245
|
+
https://123yunpan.yuque.com/org-wiki-123yunpan-muaork/cr6ced/yf97p60yyzb8mzbr
|
3084
3246
|
|
3085
3247
|
:payload:
|
3086
|
-
- fileId: int
|
3087
|
-
-
|
3248
|
+
- fileId: int 💡 文件 id
|
3249
|
+
- resolution: str 💡 分辨率
|
3250
|
+
- type: int 💡 文件类型:1:m3u8 2:ts
|
3251
|
+
- tsName: str 💡 下载 ts 文件时必须要指定名称,请参考查询某个视频的转码结果
|
3088
3252
|
"""
|
3089
|
-
api = complete_url("/api/v1/transcode/
|
3090
|
-
if not isinstance(payload, dict):
|
3091
|
-
payload = {"fileId": payload}
|
3092
|
-
payload = dict_to_lower_merge(payload, zipName=f"转码{payload.get('fileid', '')}.zip")
|
3253
|
+
api = complete_url("/api/v1/transcode/m3u8_ts/download", base_url)
|
3093
3254
|
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
3094
3255
|
|
3095
3256
|
@overload
|
@@ -3486,7 +3647,7 @@ class P123OpenClient:
|
|
3486
3647
|
:payload:
|
3487
3648
|
- containDir: "false" | "true" = "false" 💡 上传文件是否包含路径
|
3488
3649
|
- filename: str 💡 文件名,但 `containDir` 为 "true" 时,视为路径
|
3489
|
-
- duplicate: 0 | 1 | 2 = 0 💡 处理同名:0:
|
3650
|
+
- duplicate: 0 | 1 | 2 = 0 💡 处理同名:0: 跳过/报错 1: 保留/后缀编号 2: 替换/覆盖
|
3490
3651
|
- etag: str 💡 文件 md5
|
3491
3652
|
- parentFileID: int = 0 💡 父目录 id,根目录是 0
|
3492
3653
|
- size: int 💡 文件大小,单位:字节
|
@@ -3505,10 +3666,11 @@ class P123OpenClient:
|
|
3505
3666
|
"""
|
3506
3667
|
api = complete_url("/upload/v1/file/create", base_url)
|
3507
3668
|
payload = dict_to_lower_merge(payload, {
|
3508
|
-
"duplicate": 0,
|
3509
3669
|
"parentFileId": 0,
|
3510
3670
|
"containDir": "false",
|
3511
3671
|
})
|
3672
|
+
if "duplicate" in payload and not payload["duplicate"]:
|
3673
|
+
del payload["duplicate"]
|
3512
3674
|
return self.request(api, "POST", json=payload, async_=async_, **request_kwargs)
|
3513
3675
|
|
3514
3676
|
@overload
|
@@ -3788,7 +3950,7 @@ class P123OpenClient:
|
|
3788
3950
|
"""上传文件
|
3789
3951
|
|
3790
3952
|
.. note::
|
3791
|
-
|
3953
|
+
如果文件名中包含字符 "\\/:*?|><,则转换为对应的全角字符
|
3792
3954
|
|
3793
3955
|
.. admonition:: Reference
|
3794
3956
|
/API列表/文件管理/上传/v1/💡上传流程说明
|
@@ -3926,7 +4088,7 @@ class P123OpenClient:
|
|
3926
4088
|
file_name = getattr(file, "name", "")
|
3927
4089
|
file_name = basename(file_name)
|
3928
4090
|
if file_name:
|
3929
|
-
file_name = file_name
|
4091
|
+
file_name = escape_filename(file_name)
|
3930
4092
|
else:
|
3931
4093
|
file_name = str(uuid4())
|
3932
4094
|
if file_size < 0:
|
@@ -4099,6 +4261,9 @@ class P123OpenClient:
|
|
4099
4261
|
dlink_disable_open = dlink_disable
|
4100
4262
|
dlink_enable_open = dlink_enable
|
4101
4263
|
dlink_log_open = dlink_log
|
4264
|
+
dlink_m3u8_open = dlink_m3u8
|
4265
|
+
dlink_transcode_open = dlink_transcode
|
4266
|
+
dlink_transcode_query_open = dlink_transcode_query
|
4102
4267
|
dlink_url_open = dlink_url
|
4103
4268
|
download_info_open = download_info
|
4104
4269
|
fs_delete_open = fs_delete
|
@@ -4118,7 +4283,7 @@ class P123OpenClient:
|
|
4118
4283
|
oss_copy_fail_open = oss_copy_fail
|
4119
4284
|
oss_copy_process_open = oss_copy_process
|
4120
4285
|
oss_delete_open = oss_delete
|
4121
|
-
|
4286
|
+
oss_detail_open = oss_detail
|
4122
4287
|
oss_list_open = oss_list
|
4123
4288
|
oss_mkdir_open = oss_mkdir
|
4124
4289
|
oss_move_open = oss_move
|
@@ -4137,7 +4302,7 @@ class P123OpenClient:
|
|
4137
4302
|
transcode_delete_open = transcode_delete
|
4138
4303
|
transcode_download_open = transcode_download
|
4139
4304
|
transcode_download_all_open = transcode_download_all
|
4140
|
-
|
4305
|
+
transcode_m3u8_ts_download_open = transcode_m3u8_ts_download
|
4141
4306
|
transcode_info_open = transcode_info
|
4142
4307
|
transcode_list_open = transcode_list
|
4143
4308
|
transcode_record_open = transcode_record
|
@@ -5894,7 +6059,8 @@ class P123Client(P123OpenClient):
|
|
5894
6059
|
def to_snake_case(
|
5895
6060
|
payload: dict[str, Any],
|
5896
6061
|
/,
|
5897
|
-
|
6062
|
+
*,
|
6063
|
+
_map = {
|
5898
6064
|
"sharekey": "share_key",
|
5899
6065
|
"sharepwd": "share_pwd",
|
5900
6066
|
"filelist": "file_list",
|
@@ -5903,15 +6069,16 @@ class P123Client(P123OpenClient):
|
|
5903
6069
|
"parentfileid": "parent_file_id",
|
5904
6070
|
"driveid": "drive_id",
|
5905
6071
|
"currentlevel": "current_level",
|
5906
|
-
},
|
6072
|
+
}.get,
|
6073
|
+
_sub = re_compile("(?<!^)[A-Z]").sub,
|
5907
6074
|
):
|
5908
6075
|
d: dict[str, Any] = {}
|
5909
6076
|
for k, v in payload.items():
|
5910
6077
|
if "_" in k:
|
5911
6078
|
d[k.lower()] = v
|
5912
|
-
elif k2 :=
|
6079
|
+
elif k2 := _map(k.lower()):
|
5913
6080
|
d[k2] = v
|
5914
|
-
elif (k2 :=
|
6081
|
+
elif (k2 := _sub(r"_\g<0>", k)) != k:
|
5915
6082
|
d[k2.lower()] = v
|
5916
6083
|
else:
|
5917
6084
|
d[k] = v
|
@@ -6610,7 +6777,7 @@ class P123Client(P123OpenClient):
|
|
6610
6777
|
"""上传文件
|
6611
6778
|
|
6612
6779
|
.. note::
|
6613
|
-
|
6780
|
+
如果文件名中包含字符 "\\/:*?|><,则转换为对应的全角字符
|
6614
6781
|
|
6615
6782
|
:param file: 待上传的文件
|
6616
6783
|
|
@@ -6737,7 +6904,7 @@ class P123Client(P123OpenClient):
|
|
6737
6904
|
file_name = getattr(file, "name", "")
|
6738
6905
|
file_name = basename(file_name)
|
6739
6906
|
if file_name:
|
6740
|
-
file_name = file_name
|
6907
|
+
file_name = escape_filename(file_name)
|
6741
6908
|
else:
|
6742
6909
|
file_name = str(uuid4())
|
6743
6910
|
if file_size < 0:
|
@@ -6967,7 +7134,7 @@ class P123Client(P123OpenClient):
|
|
6967
7134
|
file_name = getattr(file, "name", "")
|
6968
7135
|
file_name = basename(file_name)
|
6969
7136
|
if file_name:
|
6970
|
-
file_name = file_name
|
7137
|
+
file_name = escape_filename(file_name)
|
6971
7138
|
if not file_name:
|
6972
7139
|
file_name = str(uuid4())
|
6973
7140
|
if file_size < 0:
|
p123client/exception.py
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
|
-
__all__ = [
|
4
|
+
__all__ = [
|
5
|
+
"P123Warning", "P123OSError", "P123BrokenUpload",
|
6
|
+
"P123AccessTokenError", "P123AuthenticationError",
|
7
|
+
]
|
5
8
|
|
6
9
|
import warnings
|
7
10
|
|
@@ -47,3 +50,11 @@ class P123OSError(OSError):
|
|
47
50
|
class P123BrokenUpload(P123OSError):
|
48
51
|
pass
|
49
52
|
|
53
|
+
|
54
|
+
class P123AccessTokenError(P123OSError):
|
55
|
+
pass
|
56
|
+
|
57
|
+
|
58
|
+
class P123AuthenticationError(P123OSError):
|
59
|
+
pass
|
60
|
+
|
p123client/tool/__init__.py
CHANGED
@@ -280,7 +280,7 @@ def _iterdir(
|
|
280
280
|
:return: 迭代器,产生文件或目录的信息
|
281
281
|
"""
|
282
282
|
default_payload = payload
|
283
|
-
page_size = int(payload
|
283
|
+
page_size = int(payload.setdefault("limit", 100))
|
284
284
|
def gen_step():
|
285
285
|
nonlocal parent_id
|
286
286
|
dq: deque[tuple[int, int, str]] = deque()
|
@@ -302,7 +302,8 @@ def _iterdir(
|
|
302
302
|
if interval > 0:
|
303
303
|
last_ts = time()
|
304
304
|
check_response(resp)
|
305
|
-
|
305
|
+
info_list = resp["data"]["InfoList"]
|
306
|
+
for info in info_list:
|
306
307
|
is_dir = info["is_dir"] = bool(info["Type"])
|
307
308
|
fid = info["id"] = int(info["FileId"])
|
308
309
|
info["parent_id"] = parent_id
|
@@ -328,8 +329,8 @@ def _iterdir(
|
|
328
329
|
if is_dir and (max_depth < 0 or depth < max_depth):
|
329
330
|
put((depth, fid, relpath + "/"))
|
330
331
|
if (
|
331
|
-
not
|
332
|
-
len(
|
332
|
+
not info_list or
|
333
|
+
len(info_list) < page_size or
|
333
334
|
resp["data"]["Next"] == "-1"
|
334
335
|
):
|
335
336
|
break
|
@@ -0,0 +1,12 @@
|
|
1
|
+
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
2
|
+
p123client/__init__.py,sha256=gfUum-q3f_XuXOk2HpArDAIxAlscZm8Fau1kiNkNFpg,214
|
3
|
+
p123client/client.py,sha256=AfMgAc5OY_5lTP4RXVlILImB3Cx_RSB5nMPdZZ6-YOE,246733
|
4
|
+
p123client/const.py,sha256=T17OzPQrnIG6w_Hzjc8TF_fFMKa-hQMSn1gff8pVcBc,56
|
5
|
+
p123client/exception.py,sha256=020xGo8WQmGCJz1UzNg9oFzpEvToQcgTye0s6lkFASQ,1540
|
6
|
+
p123client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
p123client/tool/__init__.py,sha256=2k_tcc67O9QG4wzESIdnAwqNHybCGlrsnxo_uBqBhEI,16673
|
8
|
+
p123client/type.py,sha256=T17OzPQrnIG6w_Hzjc8TF_fFMKa-hQMSn1gff8pVcBc,56
|
9
|
+
p123client-0.0.6.2.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
10
|
+
p123client-0.0.6.2.dist-info/METADATA,sha256=J1kKf76ITb6pxdXOW4GE7Rpxto3UncAUf1nVDO2VTbc,8869
|
11
|
+
p123client-0.0.6.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
12
|
+
p123client-0.0.6.2.dist-info/RECORD,,
|
@@ -1,12 +0,0 @@
|
|
1
|
-
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
2
|
-
p123client/__init__.py,sha256=gfUum-q3f_XuXOk2HpArDAIxAlscZm8Fau1kiNkNFpg,214
|
3
|
-
p123client/client.py,sha256=Vo1QbNuDdNQBrrjXJki1n5IXFxoYd0QsK4R2eL5-Wxg,240077
|
4
|
-
p123client/const.py,sha256=T17OzPQrnIG6w_Hzjc8TF_fFMKa-hQMSn1gff8pVcBc,56
|
5
|
-
p123client/exception.py,sha256=d2PN6mRJuw6SXNiTOBfjZQ6qfInAvkERkcbx4PQ-7vA,1369
|
6
|
-
p123client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
p123client/tool/__init__.py,sha256=zlKMg_ETifq4pFsbmqAS_BqU-fuqrYWbCs_HD4Vra6o,16649
|
8
|
-
p123client/type.py,sha256=T17OzPQrnIG6w_Hzjc8TF_fFMKa-hQMSn1gff8pVcBc,56
|
9
|
-
p123client-0.0.6.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
10
|
-
p123client-0.0.6.dist-info/METADATA,sha256=7JhGIxHwVQHzN9dc2fWzTFDkZCVBq6RXZWxfLmpeZo0,8867
|
11
|
-
p123client-0.0.6.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
12
|
-
p123client-0.0.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|