cloud189-sdk 1.0.7 → 1.0.8
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.
- package/README.md +4 -0
- package/dist/CloudAuthClient.d.ts +41 -0
- package/dist/CloudAuthClient.js +165 -0
- package/dist/CloudClient.d.ts +116 -42
- package/dist/CloudClient.js +507 -213
- package/dist/const.d.ts +1 -0
- package/dist/const.js +2 -1
- package/dist/hook/checkErrorHook.d.ts +2 -0
- package/dist/hook/checkErrorHook.js +9 -0
- package/dist/hook/index.d.ts +3 -0
- package/dist/hook/index.js +7 -0
- package/dist/hook/logHook.d.ts +2 -0
- package/dist/hook/logHook.js +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/signature.d.ts +7 -0
- package/dist/signature.js +55 -0
- package/dist/types.d.ts +333 -1
- package/dist/types.js +23 -0
- package/dist/util.d.ts +13 -1
- package/dist/util.js +94 -4
- package/package.json +2 -2
package/dist/CloudClient.js
CHANGED
|
@@ -4,185 +4,28 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
5
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
6
|
};
|
|
7
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
8
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
|
-
};
|
|
13
7
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
8
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
9
|
};
|
|
16
|
-
var
|
|
10
|
+
var _CloudClient_instances, _CloudClient_valid, _CloudClient_getAccessTokenBySsKey, _CloudClient_generateRsaKey, _CloudClient_isFamily, _CloudClient_partUpload, _CloudClient_singleUpload, _CloudClient_multiUpload;
|
|
17
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.CloudClient =
|
|
19
|
-
const
|
|
12
|
+
exports.CloudClient = void 0;
|
|
13
|
+
const fs_1 = __importDefault(require("fs"));
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
20
15
|
const got_1 = __importDefault(require("got"));
|
|
16
|
+
const types_1 = require("./types");
|
|
21
17
|
const log_1 = require("./log");
|
|
22
18
|
const util_1 = require("./util");
|
|
23
19
|
const const_1 = require("./const");
|
|
20
|
+
const signature_1 = require("./signature");
|
|
21
|
+
const CloudAuthClient_1 = require("./CloudAuthClient");
|
|
22
|
+
const hook_1 = require("./hook");
|
|
24
23
|
const store_1 = require("./store");
|
|
25
|
-
const error_1 = require("./error");
|
|
26
24
|
const config = {
|
|
27
25
|
clientId: '538135150693412',
|
|
28
26
|
model: 'KB2000',
|
|
29
27
|
version: '9.0.6'
|
|
30
28
|
};
|
|
31
|
-
/**
|
|
32
|
-
* @public
|
|
33
|
-
*/
|
|
34
|
-
class CloudAuthClient {
|
|
35
|
-
constructor() {
|
|
36
|
-
_CloudAuthClient_builLoginForm.set(this, (encrypt, appConf, username, password) => {
|
|
37
|
-
const keyData = `-----BEGIN PUBLIC KEY-----\n${encrypt.pubKey}\n-----END PUBLIC KEY-----`;
|
|
38
|
-
const usernameEncrypt = (0, util_1.rsaEncrypt)(keyData, username);
|
|
39
|
-
const passwordEncrypt = (0, util_1.rsaEncrypt)(keyData, password);
|
|
40
|
-
const data = {
|
|
41
|
-
appKey: const_1.AppID,
|
|
42
|
-
accountType: const_1.AccountType,
|
|
43
|
-
// mailSuffix: '@189.cn',
|
|
44
|
-
validateCode: '',
|
|
45
|
-
captchaToken: appConf.captchaToken,
|
|
46
|
-
dynamicCheck: 'FALSE',
|
|
47
|
-
clientType: '1',
|
|
48
|
-
cb_SaveName: '3',
|
|
49
|
-
isOauth2: false,
|
|
50
|
-
returnUrl: const_1.ReturnURL,
|
|
51
|
-
paramId: appConf.paramId,
|
|
52
|
-
userName: `${encrypt.pre}${usernameEncrypt}`,
|
|
53
|
-
password: `${encrypt.pre}${passwordEncrypt}`
|
|
54
|
-
};
|
|
55
|
-
return data;
|
|
56
|
-
});
|
|
57
|
-
this.request = got_1.default.extend({
|
|
58
|
-
headers: {
|
|
59
|
-
'User-Agent': const_1.UserAgent,
|
|
60
|
-
Accept: 'application/json;charset=UTF-8'
|
|
61
|
-
},
|
|
62
|
-
hooks: {
|
|
63
|
-
afterResponse: [
|
|
64
|
-
async (response, retryWithMergedOptions) => {
|
|
65
|
-
log_1.logger.debug(`url: ${response.requestUrl}, response: ${response.body})}`);
|
|
66
|
-
(0, error_1.checkError)(response.body.toString());
|
|
67
|
-
return response;
|
|
68
|
-
}
|
|
69
|
-
]
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* 获取加密参数
|
|
75
|
-
* @returns
|
|
76
|
-
*/
|
|
77
|
-
getEncrypt() {
|
|
78
|
-
return this.request.post(`${const_1.AUTH_URL}/api/logbox/config/encryptConf.do`).json();
|
|
79
|
-
}
|
|
80
|
-
async getLoginForm() {
|
|
81
|
-
const res = await this.request
|
|
82
|
-
.get(`${const_1.WEB_URL}/api/portal/unifyLoginForPC.action`, {
|
|
83
|
-
searchParams: {
|
|
84
|
-
appId: const_1.AppID,
|
|
85
|
-
clientType: const_1.ClientType,
|
|
86
|
-
returnURL: const_1.ReturnURL,
|
|
87
|
-
timeStamp: Date.now()
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
.text();
|
|
91
|
-
if (res) {
|
|
92
|
-
const captchaToken = res.match(`'captchaToken' value='(.+?)'`)[1];
|
|
93
|
-
const lt = res.match(`lt = "(.+?)"`)[1];
|
|
94
|
-
const paramId = res.match(`paramId = "(.+?)"`)[1];
|
|
95
|
-
const reqId = res.match(`reqId = "(.+?)"`)[1];
|
|
96
|
-
return { captchaToken, lt, paramId, reqId };
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
async getSessionForPC(param) {
|
|
101
|
-
const params = Object.assign(Object.assign({ appId: const_1.AppID }, (0, const_1.clientSuffix)()), param);
|
|
102
|
-
const res = await this.request
|
|
103
|
-
.post(`${const_1.API_URL}/getSessionForPC.action`, {
|
|
104
|
-
searchParams: params
|
|
105
|
-
})
|
|
106
|
-
.json();
|
|
107
|
-
return res;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* 用户名密码登录
|
|
111
|
-
* */
|
|
112
|
-
async loginByPassword(username, password) {
|
|
113
|
-
log_1.logger.debug('loginByPassword...');
|
|
114
|
-
try {
|
|
115
|
-
const res = await Promise.all([
|
|
116
|
-
//1.获取公钥
|
|
117
|
-
this.getEncrypt(),
|
|
118
|
-
//2.获取登录参数
|
|
119
|
-
this.getLoginForm()
|
|
120
|
-
]);
|
|
121
|
-
const encrypt = res[0].data;
|
|
122
|
-
const appConf = res[1];
|
|
123
|
-
const data = __classPrivateFieldGet(this, _CloudAuthClient_builLoginForm, "f").call(this, encrypt, appConf, username, password);
|
|
124
|
-
const loginRes = await this.request
|
|
125
|
-
.post(`${const_1.AUTH_URL}/api/logbox/oauth2/loginSubmit.do`, {
|
|
126
|
-
headers: {
|
|
127
|
-
Referer: const_1.AUTH_URL,
|
|
128
|
-
lt: appConf.lt,
|
|
129
|
-
REQID: appConf.reqId
|
|
130
|
-
},
|
|
131
|
-
form: data
|
|
132
|
-
})
|
|
133
|
-
.json();
|
|
134
|
-
return await this.getSessionForPC({ redirectURL: loginRes.toUrl });
|
|
135
|
-
}
|
|
136
|
-
catch (e) {
|
|
137
|
-
log_1.logger.error(e);
|
|
138
|
-
throw e;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* token登录
|
|
143
|
-
*/
|
|
144
|
-
async loginByAccessToken(accessToken) {
|
|
145
|
-
log_1.logger.debug('loginByAccessToken...');
|
|
146
|
-
return await this.getSessionForPC({ accessToken });
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* sso登录
|
|
150
|
-
*/
|
|
151
|
-
async loginBySsoCooike(cookie) {
|
|
152
|
-
log_1.logger.debug('loginBySsoCooike...');
|
|
153
|
-
const res = await this.request.get(`${const_1.WEB_URL}/api/portal/unifyLoginForPC.action`, {
|
|
154
|
-
searchParams: {
|
|
155
|
-
appId: const_1.AppID,
|
|
156
|
-
clientType: const_1.ClientType,
|
|
157
|
-
returnURL: const_1.ReturnURL,
|
|
158
|
-
timeStamp: Date.now()
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
const redirect = await this.request(res.url, {
|
|
162
|
-
headers: {
|
|
163
|
-
Cookie: `SSON=${cookie}`
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
return await this.getSessionForPC({ redirectURL: redirect.url });
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* 刷新token
|
|
170
|
-
*/
|
|
171
|
-
refreshToken(refreshToken) {
|
|
172
|
-
return this.request
|
|
173
|
-
.post(`${const_1.AUTH_URL}/api/oauth2/refreshToken.do`, {
|
|
174
|
-
form: {
|
|
175
|
-
clientId: const_1.AppID,
|
|
176
|
-
refreshToken,
|
|
177
|
-
grantType: 'refresh_token',
|
|
178
|
-
format: 'json'
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
.json();
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
exports.CloudAuthClient = CloudAuthClient;
|
|
185
|
-
_CloudAuthClient_builLoginForm = new WeakMap();
|
|
186
29
|
/**
|
|
187
30
|
* 天翼网盘客户端
|
|
188
31
|
* @public
|
|
@@ -190,27 +33,35 @@ _CloudAuthClient_builLoginForm = new WeakMap();
|
|
|
190
33
|
class CloudClient {
|
|
191
34
|
constructor(_options) {
|
|
192
35
|
_CloudClient_instances.add(this);
|
|
193
|
-
_CloudClient_sessionKeyPromise.set(this, void 0);
|
|
194
|
-
_CloudClient_accessTokenPromise.set(this, void 0);
|
|
195
36
|
_CloudClient_valid.set(this, (options) => {
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
|
|
37
|
+
if (options.ssonCookie) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (options.token) {
|
|
41
|
+
return;
|
|
199
42
|
}
|
|
43
|
+
if (options.username && options.password) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
log_1.logger.error('valid');
|
|
47
|
+
throw new Error('Please provide username and password or token or ssonCooike !');
|
|
200
48
|
});
|
|
201
49
|
__classPrivateFieldGet(this, _CloudClient_valid, "f").call(this, _options);
|
|
202
50
|
this.username = _options.username;
|
|
203
51
|
this.password = _options.password;
|
|
204
52
|
this.ssonCookie = _options.ssonCookie;
|
|
205
53
|
this.tokenStore = _options.token || new store_1.MemoryStore();
|
|
206
|
-
this.authClient = new CloudAuthClient();
|
|
54
|
+
this.authClient = new CloudAuthClient_1.CloudAuthClient();
|
|
207
55
|
this.session = {
|
|
208
56
|
accessToken: '',
|
|
209
57
|
sessionKey: ''
|
|
210
58
|
};
|
|
59
|
+
this.rsaKey = null;
|
|
211
60
|
this.request = got_1.default.extend({
|
|
212
61
|
retry: {
|
|
213
|
-
limit:
|
|
62
|
+
limit: 2,
|
|
63
|
+
statusCodes: [408, 413, 429],
|
|
64
|
+
errorCodes: ['ETIMEDOUT', 'ECONNRESET']
|
|
214
65
|
},
|
|
215
66
|
headers: {
|
|
216
67
|
'User-Agent': const_1.UserAgent,
|
|
@@ -222,47 +73,44 @@ class CloudClient {
|
|
|
222
73
|
async (options) => {
|
|
223
74
|
if (options.url.href.includes(const_1.API_URL)) {
|
|
224
75
|
const accessToken = await this.getAccessToken();
|
|
225
|
-
|
|
226
|
-
const time = String(Date.now());
|
|
227
|
-
const signature = (0, util_1.getSignature)(Object.assign(Object.assign({}, (options.method === 'GET' ? query : options.json)), { Timestamp: time, AccessToken: accessToken }));
|
|
228
|
-
options.headers['Sign-Type'] = '1';
|
|
229
|
-
options.headers['Signature'] = signature;
|
|
230
|
-
options.headers['Timestamp'] = time;
|
|
231
|
-
options.headers['Accesstoken'] = accessToken;
|
|
76
|
+
(0, signature_1.signatureAccesstoken)(options, accessToken);
|
|
232
77
|
}
|
|
233
78
|
else if (options.url.href.includes(const_1.WEB_URL)) {
|
|
234
|
-
const urlObj = new URL(options.url);
|
|
235
79
|
if (options.url.href.includes('/open')) {
|
|
236
|
-
const time = String(Date.now());
|
|
237
80
|
const appkey = '600100422';
|
|
238
|
-
|
|
239
|
-
options.headers['Sign-Type'] = '1';
|
|
240
|
-
options.headers['Signature'] = signature;
|
|
241
|
-
options.headers['Timestamp'] = time;
|
|
242
|
-
options.headers['AppKey'] = appkey;
|
|
81
|
+
(0, signature_1.signatureAppKey)(options, appkey);
|
|
243
82
|
}
|
|
244
83
|
const sessionKey = await this.getSessionKey();
|
|
245
|
-
|
|
246
|
-
|
|
84
|
+
options.url.searchParams.set('sessionKey', sessionKey);
|
|
85
|
+
}
|
|
86
|
+
else if (options.url.href.includes(const_1.UPLOAD_URL)) {
|
|
87
|
+
const sessionKey = await this.getSessionKey();
|
|
88
|
+
const rsaKey = await this.generateRsaKey();
|
|
89
|
+
(0, signature_1.signatureUpload)(options, rsaKey, sessionKey);
|
|
247
90
|
}
|
|
248
91
|
}
|
|
249
92
|
],
|
|
250
93
|
afterResponse: [
|
|
94
|
+
hook_1.logHook,
|
|
251
95
|
async (response, retryWithMergedOptions) => {
|
|
252
|
-
log_1.logger.debug(`url: ${response.requestUrl}, response: ${response.body}`);
|
|
253
96
|
if (response.statusCode === 400) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
97
|
+
try {
|
|
98
|
+
const { errorCode, errorMsg } = JSON.parse(response.body.toString());
|
|
99
|
+
if (errorCode === 'InvalidAccessToken') {
|
|
100
|
+
log_1.logger.debug(`InvalidAccessToken retry..., errorMsg: ${errorMsg}`);
|
|
101
|
+
log_1.logger.debug('Refresh AccessToken');
|
|
102
|
+
this.session.accessToken = '';
|
|
103
|
+
return retryWithMergedOptions({});
|
|
104
|
+
}
|
|
105
|
+
else if (errorCode === 'InvalidSessionKey') {
|
|
106
|
+
log_1.logger.debug(`InvalidSessionKey retry..., errorMsg: ${errorMsg}`);
|
|
107
|
+
log_1.logger.debug('Refresh InvalidSessionKey');
|
|
108
|
+
this.session.sessionKey = '';
|
|
109
|
+
return retryWithMergedOptions({});
|
|
110
|
+
}
|
|
260
111
|
}
|
|
261
|
-
|
|
262
|
-
log_1.logger.
|
|
263
|
-
log_1.logger.debug('Refresh InvalidSessionKey');
|
|
264
|
-
this.session.sessionKey = '';
|
|
265
|
-
return retryWithMergedOptions({});
|
|
112
|
+
catch (e) {
|
|
113
|
+
log_1.logger.error(e);
|
|
266
114
|
}
|
|
267
115
|
}
|
|
268
116
|
return response;
|
|
@@ -333,18 +181,18 @@ class CloudClient {
|
|
|
333
181
|
if (this.session.sessionKey) {
|
|
334
182
|
return this.session.sessionKey;
|
|
335
183
|
}
|
|
336
|
-
if (!
|
|
337
|
-
|
|
184
|
+
if (!this.sessionKeyPromise) {
|
|
185
|
+
this.sessionKeyPromise = this.getSession()
|
|
338
186
|
.then((result) => {
|
|
339
187
|
this.session.sessionKey = result.sessionKey;
|
|
340
|
-
return result;
|
|
188
|
+
return result.sessionKey;
|
|
341
189
|
})
|
|
342
190
|
.finally(() => {
|
|
343
|
-
|
|
344
|
-
})
|
|
191
|
+
this.sessionKeyPromise = null;
|
|
192
|
+
});
|
|
345
193
|
}
|
|
346
|
-
const result = await
|
|
347
|
-
return result
|
|
194
|
+
const result = await this.sessionKeyPromise;
|
|
195
|
+
return result;
|
|
348
196
|
}
|
|
349
197
|
/**
|
|
350
198
|
* 获取 accessToken
|
|
@@ -354,19 +202,45 @@ class CloudClient {
|
|
|
354
202
|
if (this.session.accessToken) {
|
|
355
203
|
return this.session.accessToken;
|
|
356
204
|
}
|
|
357
|
-
if (!
|
|
358
|
-
|
|
205
|
+
if (!this.accessTokenPromise) {
|
|
206
|
+
this.accessTokenPromise = __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_getAccessTokenBySsKey).call(this)
|
|
359
207
|
.then((result) => {
|
|
360
208
|
this.session.accessToken = result.accessToken;
|
|
361
209
|
return result;
|
|
362
210
|
})
|
|
363
211
|
.finally(() => {
|
|
364
|
-
|
|
365
|
-
})
|
|
212
|
+
this.accessTokenPromise = null;
|
|
213
|
+
});
|
|
366
214
|
}
|
|
367
|
-
const result = await
|
|
215
|
+
const result = await this.accessTokenPromise;
|
|
368
216
|
return result.accessToken;
|
|
369
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* 获取 RSA key
|
|
220
|
+
* @returns RSAKey
|
|
221
|
+
*/
|
|
222
|
+
async generateRsaKey() {
|
|
223
|
+
if (this.rsaKey && new Date(this.rsaKey.expire).getTime() > Date.now()) {
|
|
224
|
+
return this.rsaKey;
|
|
225
|
+
}
|
|
226
|
+
if (!this.generateRsaKeyPromise) {
|
|
227
|
+
this.generateRsaKeyPromise = __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_generateRsaKey).call(this)
|
|
228
|
+
.then((res) => {
|
|
229
|
+
this.rsaKey = {
|
|
230
|
+
expire: res.expire,
|
|
231
|
+
pubKey: res.pubKey,
|
|
232
|
+
pkId: res.pkId,
|
|
233
|
+
ver: res.ver
|
|
234
|
+
};
|
|
235
|
+
return res;
|
|
236
|
+
})
|
|
237
|
+
.finally(() => {
|
|
238
|
+
this.generateRsaKeyPromise = null;
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
const result = await this.generateRsaKeyPromise;
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
370
244
|
/**
|
|
371
245
|
* 获取用户网盘存储容量信息
|
|
372
246
|
* @returns 账号容量结果
|
|
@@ -394,14 +268,434 @@ class CloudClient {
|
|
|
394
268
|
* 家庭签到任务
|
|
395
269
|
* @param familyId - 家庭id
|
|
396
270
|
* @returns 签到结果
|
|
271
|
+
* @deprecated 已无效
|
|
397
272
|
*/
|
|
398
273
|
familyUserSign(familyId) {
|
|
399
274
|
return this.request
|
|
400
275
|
.get(`${const_1.API_URL}/open/family/manage/exeFamilyUserSign.action?familyId=${familyId}`)
|
|
401
276
|
.json();
|
|
402
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* 获取文件列表
|
|
280
|
+
* @param pageQuery - 查询参数
|
|
281
|
+
* @returns
|
|
282
|
+
*/
|
|
283
|
+
getListFiles(pageQuery, familyId) {
|
|
284
|
+
const defaultQuery = {
|
|
285
|
+
pageNum: 1,
|
|
286
|
+
pageSize: 60,
|
|
287
|
+
mediaType: types_1.MediaType.ALL.toString(),
|
|
288
|
+
orderBy: types_1.OrderByType.LAST_OP_TIME.toString(),
|
|
289
|
+
descending: true,
|
|
290
|
+
folderId: '',
|
|
291
|
+
iconOption: 5
|
|
292
|
+
};
|
|
293
|
+
const query = Object.assign(Object.assign({}, defaultQuery), pageQuery);
|
|
294
|
+
if (familyId) {
|
|
295
|
+
return this.request
|
|
296
|
+
.get(`${const_1.API_URL}/open/family/file/listFiles.action`, {
|
|
297
|
+
searchParams: Object.assign(Object.assign({}, query), { familyId })
|
|
298
|
+
})
|
|
299
|
+
.json();
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
return this.request
|
|
303
|
+
.get(`${const_1.API_URL}/open/file/listFiles.action`, {
|
|
304
|
+
searchParams: Object.assign({}, query)
|
|
305
|
+
})
|
|
306
|
+
.json();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* 创建文件夹
|
|
311
|
+
* @param createFolderRequest - 创建文件夹请求
|
|
312
|
+
* @returns
|
|
313
|
+
*/
|
|
314
|
+
createFolder(createFolderRequest) {
|
|
315
|
+
const url = __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_isFamily).call(this, createFolderRequest)
|
|
316
|
+
? `${const_1.API_URL}/open/family/file/createFolder.action`
|
|
317
|
+
: `${const_1.API_URL}/open/file/createFolder.action`;
|
|
318
|
+
return this.request
|
|
319
|
+
.post(url, {
|
|
320
|
+
form: createFolderRequest
|
|
321
|
+
})
|
|
322
|
+
.json();
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* 重命名文件夹
|
|
326
|
+
* @param renameFolderRequest - 重名文件夹请求
|
|
327
|
+
* @returns
|
|
328
|
+
*/
|
|
329
|
+
renameFolder(renameFolderRequest) {
|
|
330
|
+
let url = `${const_1.API_URL}/open/file/renameFolder.action`;
|
|
331
|
+
let form = {
|
|
332
|
+
destFolderName: renameFolderRequest.folderName,
|
|
333
|
+
folderId: renameFolderRequest.folderId
|
|
334
|
+
};
|
|
335
|
+
if (__classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_isFamily).call(this, renameFolderRequest)) {
|
|
336
|
+
url = `${const_1.API_URL}/open/family/file/renameFolder.action`;
|
|
337
|
+
form = Object.assign(form, {
|
|
338
|
+
familyId: renameFolderRequest.familyId
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
return this.request
|
|
342
|
+
.post(url, {
|
|
343
|
+
form
|
|
344
|
+
})
|
|
345
|
+
.json();
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* 初始化上传
|
|
349
|
+
* @param initMultiUploadRequest - 初始化请求
|
|
350
|
+
* @returns
|
|
351
|
+
*/
|
|
352
|
+
async initMultiUpload(initMultiUploadRequest) {
|
|
353
|
+
const { parentFolderId, fileName, fileSize, sliceSize, fileMd5, sliceMd5 } = initMultiUploadRequest;
|
|
354
|
+
let initParams = Object.assign({ parentFolderId,
|
|
355
|
+
fileName,
|
|
356
|
+
fileSize,
|
|
357
|
+
sliceSize }, (fileMd5 && sliceMd5 ? { fileMd5, sliceMd5 } : { lazyCheck: 1 }));
|
|
358
|
+
let url = `${const_1.UPLOAD_URL}/person/initMultiUpload`;
|
|
359
|
+
if (__classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_isFamily).call(this, initMultiUploadRequest)) {
|
|
360
|
+
url = `${const_1.UPLOAD_URL}/family/initMultiUpload`;
|
|
361
|
+
initParams = Object.assign(initParams, {
|
|
362
|
+
familyId: initMultiUploadRequest.familyId
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
return await this.request
|
|
366
|
+
.get(url, {
|
|
367
|
+
searchParams: Object.assign({}, initParams)
|
|
368
|
+
})
|
|
369
|
+
.json();
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* 提交上传
|
|
373
|
+
* @param commitMultiUploadRequest - 提交请求
|
|
374
|
+
* @returns
|
|
375
|
+
*/
|
|
376
|
+
commitMultiUpload(commitMultiUploadRequest) {
|
|
377
|
+
const url = __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_isFamily).call(this, commitMultiUploadRequest)
|
|
378
|
+
? `${const_1.UPLOAD_URL}/family/commitMultiUploadFile`
|
|
379
|
+
: `${const_1.UPLOAD_URL}/person/commitMultiUploadFile`;
|
|
380
|
+
return this.request
|
|
381
|
+
.get(url, {
|
|
382
|
+
searchParams: Object.assign({}, commitMultiUploadRequest)
|
|
383
|
+
})
|
|
384
|
+
.json();
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* 检测秒传
|
|
388
|
+
* @param params - 检查参数
|
|
389
|
+
* @returns
|
|
390
|
+
*/
|
|
391
|
+
checkTransSecond(params) {
|
|
392
|
+
const url = __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_isFamily).call(this, params)
|
|
393
|
+
? `${const_1.UPLOAD_URL}/family/checkTransSecond`
|
|
394
|
+
: `${const_1.UPLOAD_URL}/person/checkTransSecond`;
|
|
395
|
+
return this.request
|
|
396
|
+
.get(url, {
|
|
397
|
+
searchParams: params
|
|
398
|
+
})
|
|
399
|
+
.json();
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* 文件上传
|
|
403
|
+
* @param param - 上传参数
|
|
404
|
+
* @param callbacks - 上传回调
|
|
405
|
+
* @returns
|
|
406
|
+
*/
|
|
407
|
+
async upload(param, callbacks = {}) {
|
|
408
|
+
const { filePath, parentFolderId, familyId } = param;
|
|
409
|
+
const { size } = await fs_1.default.promises.stat(filePath);
|
|
410
|
+
const fileName = encodeURIComponent(path_1.default.basename(filePath));
|
|
411
|
+
const sliceSize = (0, util_1.partSize)(size);
|
|
412
|
+
const { fileMd5, chunkMd5s } = await (0, util_1.calculateFileAndChunkMD5)(filePath, sliceSize);
|
|
413
|
+
if (chunkMd5s.length === 1) {
|
|
414
|
+
log_1.logger.debug('single file upload');
|
|
415
|
+
return __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_singleUpload).call(this, {
|
|
416
|
+
parentFolderId,
|
|
417
|
+
filePath,
|
|
418
|
+
fileName,
|
|
419
|
+
fileSize: size,
|
|
420
|
+
sliceSize,
|
|
421
|
+
fileMd5,
|
|
422
|
+
familyId
|
|
423
|
+
}, callbacks);
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
log_1.logger.debug('multi file upload');
|
|
427
|
+
return __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_multiUpload).call(this, {
|
|
428
|
+
parentFolderId,
|
|
429
|
+
filePath,
|
|
430
|
+
fileName,
|
|
431
|
+
fileSize: size,
|
|
432
|
+
sliceSize,
|
|
433
|
+
fileMd5,
|
|
434
|
+
chunkMd5s,
|
|
435
|
+
familyId
|
|
436
|
+
}, callbacks);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* 检测任务状态
|
|
441
|
+
* @param type - 任务类型
|
|
442
|
+
* @param taskId - 任务Id
|
|
443
|
+
* @param maxAttempts - 重试次数
|
|
444
|
+
* @param interval - 重试间隔
|
|
445
|
+
* @returns
|
|
446
|
+
*/
|
|
447
|
+
async checkTaskStatus(type, taskId, maxAttempts = 120, interval = 500) {
|
|
448
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
449
|
+
try {
|
|
450
|
+
const { taskStatus, successedFileIdList } = await this.request
|
|
451
|
+
.post(`${const_1.API_URL}/open/batch/checkBatchTask.action`, {
|
|
452
|
+
form: { type, taskId }
|
|
453
|
+
})
|
|
454
|
+
.json();
|
|
455
|
+
if (taskStatus === -1) {
|
|
456
|
+
log_1.logger.error('创建任务异常');
|
|
457
|
+
return {
|
|
458
|
+
taskId,
|
|
459
|
+
taskStatus
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
//重名
|
|
463
|
+
if (taskStatus === 2) {
|
|
464
|
+
log_1.logger.error('文件重名任务异常');
|
|
465
|
+
return {
|
|
466
|
+
taskId,
|
|
467
|
+
taskStatus
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
//成功
|
|
471
|
+
if (taskStatus === 4) {
|
|
472
|
+
return { successedFileIdList, taskId, taskStatus };
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (e) {
|
|
476
|
+
log_1.logger.error(`Check task status attempt ${attempt + 1} failed:` + e);
|
|
477
|
+
}
|
|
478
|
+
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* 创建任务
|
|
483
|
+
* @param createBatchTaskRequest - 创建任务参数
|
|
484
|
+
* @returns
|
|
485
|
+
*/
|
|
486
|
+
async createBatchTask(createBatchTaskRequest) {
|
|
487
|
+
let form = {
|
|
488
|
+
type: createBatchTaskRequest.type,
|
|
489
|
+
taskInfos: JSON.stringify(createBatchTaskRequest.taskInfos)
|
|
490
|
+
};
|
|
491
|
+
if (createBatchTaskRequest.targetFolderId) {
|
|
492
|
+
form = Object.assign(form, {
|
|
493
|
+
targetFolderId: createBatchTaskRequest.targetFolderId
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
if (__classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_isFamily).call(this, createBatchTaskRequest)) {
|
|
497
|
+
form = Object.assign(form, {
|
|
498
|
+
familyId: createBatchTaskRequest.familyId
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
try {
|
|
502
|
+
const { taskId } = await this.request
|
|
503
|
+
.post(`${const_1.API_URL}/open/batch/createBatchTask.action`, {
|
|
504
|
+
form
|
|
505
|
+
})
|
|
506
|
+
.json();
|
|
507
|
+
return await this.checkTaskStatus(createBatchTaskRequest.type, taskId);
|
|
508
|
+
}
|
|
509
|
+
catch (error) {
|
|
510
|
+
log_1.logger.error('Batch task creation failed:' + error);
|
|
511
|
+
throw error;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* 获取文件下载路径
|
|
516
|
+
* @param params - 文件参数
|
|
517
|
+
* @returns
|
|
518
|
+
*/
|
|
519
|
+
getFileDownloadUrl(params) {
|
|
520
|
+
const url = params.familyId
|
|
521
|
+
? `${const_1.API_URL}/open/family/file/getFileDownloadUrl.action`
|
|
522
|
+
: `${const_1.API_URL}/open/file/getFileDownloadUrl.action`;
|
|
523
|
+
return this.request(url, {
|
|
524
|
+
searchParams: params
|
|
525
|
+
}).json();
|
|
526
|
+
}
|
|
403
527
|
}
|
|
404
528
|
exports.CloudClient = CloudClient;
|
|
405
|
-
|
|
529
|
+
_CloudClient_valid = new WeakMap(), _CloudClient_instances = new WeakSet(), _CloudClient_getAccessTokenBySsKey = function _CloudClient_getAccessTokenBySsKey() {
|
|
406
530
|
return this.request.get(`${const_1.WEB_URL}/api/open/oauth2/getAccessTokenBySsKey.action`).json();
|
|
531
|
+
}, _CloudClient_generateRsaKey = function _CloudClient_generateRsaKey() {
|
|
532
|
+
return this.request.get(`${const_1.WEB_URL}/api/security/generateRsaKey.action`).json();
|
|
533
|
+
}, _CloudClient_isFamily = function _CloudClient_isFamily(request) {
|
|
534
|
+
return 'familyId' in request && request.familyId !== undefined;
|
|
535
|
+
}, _CloudClient_partUpload = async function _CloudClient_partUpload({ partNumber, md5, buffer, uploadFileId, familyId }, callbacks = {}) {
|
|
536
|
+
const partInfo = `${partNumber}-${(0, util_1.hexToBase64)(md5)}`;
|
|
537
|
+
log_1.logger.debug(`upload part: ${partNumber}`);
|
|
538
|
+
const multiUploadUrParams = {
|
|
539
|
+
partInfo,
|
|
540
|
+
uploadFileId
|
|
541
|
+
};
|
|
542
|
+
const url = familyId
|
|
543
|
+
? `${const_1.UPLOAD_URL}/family/getMultiUploadUrls`
|
|
544
|
+
: `${const_1.UPLOAD_URL}/person/getMultiUploadUrls`;
|
|
545
|
+
const urls = await this.request
|
|
546
|
+
.get(url, {
|
|
547
|
+
searchParams: multiUploadUrParams
|
|
548
|
+
})
|
|
549
|
+
.json();
|
|
550
|
+
const { requestURL, requestHeader } = urls.uploadUrls[`partNumber_${partNumber}`];
|
|
551
|
+
const headers = requestHeader.split('&').reduce((acc, pair) => {
|
|
552
|
+
const key = pair.split('=')[0];
|
|
553
|
+
const value = pair.match(/=(.*)/)[1];
|
|
554
|
+
acc[key] = value;
|
|
555
|
+
return acc;
|
|
556
|
+
}, {});
|
|
557
|
+
log_1.logger.debug(`Upload URL: ${requestURL}`);
|
|
558
|
+
log_1.logger.debug(`Upload Headers: ${JSON.stringify(headers)}`);
|
|
559
|
+
await got_1.default
|
|
560
|
+
.put(requestURL, {
|
|
561
|
+
headers,
|
|
562
|
+
body: buffer
|
|
563
|
+
})
|
|
564
|
+
.on('uploadProgress', (progress) => {
|
|
565
|
+
var _a;
|
|
566
|
+
(_a = callbacks.onProgress) === null || _a === void 0 ? void 0 : _a.call(callbacks, (progress.transferred * 100) / progress.total);
|
|
567
|
+
});
|
|
568
|
+
}, _CloudClient_singleUpload =
|
|
569
|
+
/**
|
|
570
|
+
* 单个小文件上传
|
|
571
|
+
*/
|
|
572
|
+
async function _CloudClient_singleUpload({ parentFolderId, filePath, fileName, fileSize, fileMd5, sliceSize, familyId }, callbacks = {}) {
|
|
573
|
+
var _a, _b, _c;
|
|
574
|
+
const sliceMd5 = fileMd5;
|
|
575
|
+
const initParams = {
|
|
576
|
+
parentFolderId,
|
|
577
|
+
fileName,
|
|
578
|
+
fileSize,
|
|
579
|
+
sliceSize,
|
|
580
|
+
fileMd5,
|
|
581
|
+
sliceMd5,
|
|
582
|
+
familyId
|
|
583
|
+
};
|
|
584
|
+
let fd;
|
|
585
|
+
try {
|
|
586
|
+
// md5校验
|
|
587
|
+
const res = await this.initMultiUpload(initParams);
|
|
588
|
+
const { uploadFileId, fileDataExists } = res.data;
|
|
589
|
+
if (!fileDataExists) {
|
|
590
|
+
fd = await fs_1.default.promises.open(filePath, 'r');
|
|
591
|
+
const buffer = Buffer.alloc(fileSize);
|
|
592
|
+
await fd.read(buffer, 0, fileSize);
|
|
593
|
+
await __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_partUpload).call(this, {
|
|
594
|
+
partNumber: 1,
|
|
595
|
+
md5: fileMd5,
|
|
596
|
+
buffer,
|
|
597
|
+
uploadFileId,
|
|
598
|
+
familyId
|
|
599
|
+
}, {
|
|
600
|
+
onProgress: callbacks.onProgress,
|
|
601
|
+
onError: callbacks.onError
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
log_1.logger.debug(`单文件 ${filePath} 秒传: ${uploadFileId}`);
|
|
606
|
+
(_a = callbacks.onProgress) === null || _a === void 0 ? void 0 : _a.call(callbacks, 100); // 秒传直接显示100%
|
|
607
|
+
}
|
|
608
|
+
const commitResult = Object.assign(Object.assign({}, (await this.commitMultiUpload({
|
|
609
|
+
fileMd5,
|
|
610
|
+
sliceMd5,
|
|
611
|
+
uploadFileId,
|
|
612
|
+
familyId
|
|
613
|
+
}))), { fileDataExists });
|
|
614
|
+
(_b = callbacks.onComplete) === null || _b === void 0 ? void 0 : _b.call(callbacks, commitResult);
|
|
615
|
+
return commitResult;
|
|
616
|
+
}
|
|
617
|
+
catch (e) {
|
|
618
|
+
(_c = callbacks.onError) === null || _c === void 0 ? void 0 : _c.call(callbacks, e);
|
|
619
|
+
throw e;
|
|
620
|
+
}
|
|
621
|
+
finally {
|
|
622
|
+
fd === null || fd === void 0 ? void 0 : fd.close();
|
|
623
|
+
}
|
|
624
|
+
}, _CloudClient_multiUpload =
|
|
625
|
+
/**
|
|
626
|
+
* 大文件分块上传
|
|
627
|
+
*/
|
|
628
|
+
async function _CloudClient_multiUpload({ parentFolderId, filePath, fileName, fileSize, fileMd5, sliceSize, chunkMd5s, familyId }, callbacks = {}) {
|
|
629
|
+
var _a, _b, _c;
|
|
630
|
+
const sliceMd5 = (0, util_1.md5)(chunkMd5s.join('\n'));
|
|
631
|
+
const initParams = {
|
|
632
|
+
parentFolderId,
|
|
633
|
+
fileName,
|
|
634
|
+
fileSize,
|
|
635
|
+
sliceSize,
|
|
636
|
+
familyId
|
|
637
|
+
};
|
|
638
|
+
let fd;
|
|
639
|
+
try {
|
|
640
|
+
const res = await this.initMultiUpload(initParams);
|
|
641
|
+
const { uploadFileId } = res.data;
|
|
642
|
+
const checkTransSecondParams = {
|
|
643
|
+
fileMd5,
|
|
644
|
+
sliceMd5,
|
|
645
|
+
uploadFileId,
|
|
646
|
+
familyId
|
|
647
|
+
};
|
|
648
|
+
// md5校验
|
|
649
|
+
const checkRes = await this.checkTransSecond(checkTransSecondParams);
|
|
650
|
+
const { fileDataExists } = checkRes.data;
|
|
651
|
+
if (!fileDataExists) {
|
|
652
|
+
fd = await fs_1.default.promises.open(filePath, 'r');
|
|
653
|
+
const chunkCount = chunkMd5s.length;
|
|
654
|
+
const progressMap = {};
|
|
655
|
+
await (0, util_1.asyncPool)(5, [...Array(chunkCount).keys()], async (i) => {
|
|
656
|
+
const partNumber = i + 1;
|
|
657
|
+
const position = i * sliceSize;
|
|
658
|
+
const length = Math.min(sliceSize, fileSize - position);
|
|
659
|
+
const buffer = Buffer.alloc(length);
|
|
660
|
+
await fd.read(buffer, 0, length, position);
|
|
661
|
+
await __classPrivateFieldGet(this, _CloudClient_instances, "m", _CloudClient_partUpload).call(this, {
|
|
662
|
+
partNumber: partNumber,
|
|
663
|
+
md5: chunkMd5s[i],
|
|
664
|
+
buffer,
|
|
665
|
+
uploadFileId,
|
|
666
|
+
familyId
|
|
667
|
+
}, {
|
|
668
|
+
onProgress: (chunkProgress) => {
|
|
669
|
+
if (callbacks.onProgress) {
|
|
670
|
+
// 计算整体进度
|
|
671
|
+
progressMap[`partNumber_${partNumber}`] = chunkProgress;
|
|
672
|
+
const totalProgress = Object.values(progressMap).reduce((sum, p) => sum + p, 0) / chunkCount;
|
|
673
|
+
callbacks.onProgress(totalProgress);
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
onError: callbacks.onError
|
|
677
|
+
});
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
log_1.logger.debug(`多块文件 ${filePath} 秒传: ${uploadFileId}`);
|
|
682
|
+
(_a = callbacks.onProgress) === null || _a === void 0 ? void 0 : _a.call(callbacks, 100); // 秒传直接显示100%
|
|
683
|
+
}
|
|
684
|
+
const commitResult = Object.assign(Object.assign({}, (await this.commitMultiUpload({
|
|
685
|
+
fileMd5,
|
|
686
|
+
sliceMd5,
|
|
687
|
+
uploadFileId,
|
|
688
|
+
lazyCheck: 1,
|
|
689
|
+
familyId
|
|
690
|
+
}))), { fileDataExists });
|
|
691
|
+
(_b = callbacks.onComplete) === null || _b === void 0 ? void 0 : _b.call(callbacks, commitResult);
|
|
692
|
+
return commitResult;
|
|
693
|
+
}
|
|
694
|
+
catch (e) {
|
|
695
|
+
(_c = callbacks.onError) === null || _c === void 0 ? void 0 : _c.call(callbacks, e);
|
|
696
|
+
throw e;
|
|
697
|
+
}
|
|
698
|
+
finally {
|
|
699
|
+
fd === null || fd === void 0 ? void 0 : fd.close();
|
|
700
|
+
}
|
|
407
701
|
};
|