oicq-icalingua-plus-plus 1.26.29 → 1.26.30
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/index.d.ts +19 -1
- package/index.js +2 -1
- package/lib/message/qfile.js +43 -9
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -975,6 +975,22 @@ export interface FlashTransferUploadSource {
|
|
|
975
975
|
sha1: Buffer | string;
|
|
976
976
|
}
|
|
977
977
|
|
|
978
|
+
/** 客户端分片上传所需的凭证。 */
|
|
979
|
+
export interface FlashTransferUploadCredential {
|
|
980
|
+
ukey: string;
|
|
981
|
+
appid: number;
|
|
982
|
+
file_id: string;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/** 由远程 QQ 客户端执行控制操作,文件内容在上传方本地传输。 */
|
|
986
|
+
export interface FlashTransferUploadController<T extends FlashTransferUploadCredential = FlashTransferUploadCredential> {
|
|
987
|
+
create(name: string, options?: FlashTransferCreateOptions): Promise<FlashTransferTask>;
|
|
988
|
+
addFiles(task: FlashTransferTask, files: FlashTransferMetadata[]): Promise<FlashTransferFile[]>;
|
|
989
|
+
applyUpload(task: FlashTransferTask, file: FlashTransferFile, source: FlashTransferUploadSource): Promise<T>;
|
|
990
|
+
completeFile(ticket: T): Promise<void>;
|
|
991
|
+
submit(task_id: string): Promise<void>;
|
|
992
|
+
}
|
|
993
|
+
|
|
978
994
|
/** 由 applyUpload 返回,保留服务端的 IndexNode、存储参数和业务透传信息。 */
|
|
979
995
|
export interface FlashTransferUploadTicket {
|
|
980
996
|
upload: Record<number, any>;
|
|
@@ -1033,6 +1049,8 @@ export interface FlashTransferDownload {
|
|
|
1033
1049
|
/** 与 Gfs 一样,以下方法会 reject;控制接口保留官网的 snake_case 字段。 */
|
|
1034
1050
|
export class FlashTransfer {
|
|
1035
1051
|
private constructor();
|
|
1052
|
+
/** 文件在本机分片上传,创建、登记及完成提交由 control 执行;无需本机登录 QQ */
|
|
1053
|
+
static upload<T extends FlashTransferUploadCredential>(files: FlashTransferUploadInput | FlashTransferUploadInput[], control: FlashTransferUploadController<T>, name?: string, callback?: (percentage: string) => void, options?: FlashTransferCreateOptions & { timeout?: number }): Promise<FlashTransferUploadResult>;
|
|
1036
1054
|
/** 分享码或 https://qfile.qq.com/q/... 链接转换为文件集 ID */
|
|
1037
1055
|
resolve(code: string): Promise<string>;
|
|
1038
1056
|
/** 原生创建文件集,需要在线客户端;保留 task_id 用于完成提交 */
|
|
@@ -1042,7 +1060,7 @@ export class FlashTransfer {
|
|
|
1042
1060
|
/** 分批登记目录及已计算摘要的文件,返回顺序与请求一致 */
|
|
1043
1061
|
addFiles(task: Pick<FlashTransferTask, "fileset_id" | "task_id">, files: FlashTransferMetadata[]): Promise<FlashTransferFile[]>;
|
|
1044
1062
|
/** 底层上传申请;文件必须是 addFiles 返回的节点,source 提供其名称、大小及摘要 */
|
|
1045
|
-
applyUpload(task: Pick<FlashTransferTask, "fileset_id">, file: FlashTransferFile, source: FlashTransferUploadSource): Promise<FlashTransferUploadTicket>;
|
|
1063
|
+
applyUpload(task: Pick<FlashTransferTask, "fileset_id">, file: FlashTransferFile, source: FlashTransferUploadSource): Promise<FlashTransferUploadTicket & FlashTransferUploadCredential>;
|
|
1046
1064
|
/** 分片上传或秒传成功后同步单个文件,随后才能提交整个任务 */
|
|
1047
1065
|
completeFile(ticket: FlashTransferUploadTicket): Promise<void>;
|
|
1048
1066
|
/** 文件级完成同步之后提交整个任务,参数是 task_id */
|
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { Client } = require("./lib/oicq");
|
|
3
|
+
const { FlashTransfer } = require("./lib/message/qfile");
|
|
3
4
|
const { segment, cqcode } = require("./util");
|
|
4
5
|
const { checkUin, NOOP } = require("./lib/common");
|
|
5
6
|
const pb = require("./lib/algo/pb");
|
|
@@ -20,7 +21,7 @@ const constants = {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
module.exports = {
|
|
23
|
-
Client, createClient,
|
|
24
|
+
Client, createClient, FlashTransfer,
|
|
24
25
|
segment, cqcode,
|
|
25
26
|
/** @deprecated */
|
|
26
27
|
setGlobalConfig: NOOP,
|
package/lib/message/qfile.js
CHANGED
|
@@ -236,10 +236,11 @@ class FlashTransfer {
|
|
|
236
236
|
* @param {Pick<import("../../").FlashTransferTask, "fileset_id">} task
|
|
237
237
|
* @param {import("../../").FlashTransferFile} file
|
|
238
238
|
* @param {import("../../").FlashTransferUploadSource} source
|
|
239
|
-
* @returns {Promise<import("../../").FlashTransferUploadTicket>}
|
|
239
|
+
* @returns {Promise<import("../../").FlashTransferUploadTicket & import("../../").FlashTransferUploadCredential>}
|
|
240
240
|
*/
|
|
241
|
-
applyUpload(task, file, source) {
|
|
242
|
-
|
|
241
|
+
async applyUpload(task, file, source) {
|
|
242
|
+
const ticket = await native.applyUpload(this.c, source, native.getBizTransInfo(task, file), file.is_cover ? 23 : 22);
|
|
243
|
+
return { ...ticket, file_id: String(ticket.info[1][2]) };
|
|
243
244
|
}
|
|
244
245
|
|
|
245
246
|
/**
|
|
@@ -260,6 +261,39 @@ class FlashTransfer {
|
|
|
260
261
|
*/
|
|
261
262
|
async upload(files, name, callback, options = {}) {
|
|
262
263
|
native.checkOnline(this.c);
|
|
264
|
+
return this._upload(files, name, callback, options, this);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 文件在本机读取和上传,控制操作由调用方提供;无需在本机登录 QQ。
|
|
269
|
+
* @param {import("../../").FlashTransferUploadInput | import("../../").FlashTransferUploadInput[]} files
|
|
270
|
+
* @template {import("../../").FlashTransferUploadCredential} T
|
|
271
|
+
* @param {import("../../").FlashTransferUploadController<T>} control
|
|
272
|
+
* @param {string} [name]
|
|
273
|
+
* @param {(percentage: string) => void} [callback]
|
|
274
|
+
* @param {import("../../").FlashTransferCreateOptions & {timeout?: number}} [options]
|
|
275
|
+
* @returns {Promise<import("../../").FlashTransferUploadResult>}
|
|
276
|
+
*/
|
|
277
|
+
static async upload(files, control, name, callback, options = {}) {
|
|
278
|
+
for (const method of ["create", "addFiles", "applyUpload", "completeFile", "submit"]) {
|
|
279
|
+
if (typeof control?.[method] !== "function")
|
|
280
|
+
throw new TypeError("upload controller has no " + method);
|
|
281
|
+
}
|
|
282
|
+
const { timeout, ...createOptions } = options;
|
|
283
|
+
return new FlashTransfer(undefined, { timeout })._upload(files, name, callback, createOptions, control);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @private
|
|
288
|
+
* @param {import("../../").FlashTransferUploadInput | import("../../").FlashTransferUploadInput[]} files
|
|
289
|
+
* @param {string} name
|
|
290
|
+
* @param {(percentage: string) => void} callback
|
|
291
|
+
* @param {import("../../").FlashTransferCreateOptions} options
|
|
292
|
+
* @template {import("../../").FlashTransferUploadCredential} T
|
|
293
|
+
* @param {import("../../").FlashTransferUploadController<T>} control
|
|
294
|
+
* @returns {Promise<import("../../").FlashTransferUploadResult>}
|
|
295
|
+
*/
|
|
296
|
+
async _upload(files, name, callback, options, control) {
|
|
263
297
|
if (callback !== undefined && typeof callback !== "function")
|
|
264
298
|
throw new TypeError("upload callback must be a function");
|
|
265
299
|
if (name !== undefined)
|
|
@@ -341,14 +375,14 @@ class FlashTransfer {
|
|
|
341
375
|
}
|
|
342
376
|
stage = "create";
|
|
343
377
|
const total = [...sources.values()].reduce((size, source) => size + source.size, 0);
|
|
344
|
-
task = await
|
|
378
|
+
task = await control.create(name || metadata[0].name, {
|
|
345
379
|
...options,
|
|
346
380
|
total_file_count: sources.size,
|
|
347
381
|
total_file_size: total,
|
|
348
382
|
first_level_item_count: metadata.filter(file => !file.parent_id).length,
|
|
349
383
|
});
|
|
350
384
|
stage = "add_files";
|
|
351
|
-
const added = await
|
|
385
|
+
const added = await control.addFiles(task, metadata);
|
|
352
386
|
let transferred = 0, completed = 0;
|
|
353
387
|
for (const file of added) {
|
|
354
388
|
if (file.is_dir)
|
|
@@ -357,7 +391,7 @@ class FlashTransfer {
|
|
|
357
391
|
if (!source)
|
|
358
392
|
throw new FlashTransferError(-1, "upload response has an unknown client file id");
|
|
359
393
|
stage = "apply_upload";
|
|
360
|
-
const ticket = await
|
|
394
|
+
const ticket = await control.applyUpload(task, file, source);
|
|
361
395
|
stage = "upload";
|
|
362
396
|
if (ticket.ukey && source.size) {
|
|
363
397
|
await uploadFile(source, ticket.ukey, ticket.appid, this._http, callback ? percentage => {
|
|
@@ -366,15 +400,15 @@ class FlashTransfer {
|
|
|
366
400
|
}
|
|
367
401
|
await source.close();
|
|
368
402
|
stage = "complete_file";
|
|
369
|
-
await
|
|
370
|
-
file.physical = { id: String(ticket.
|
|
403
|
+
await control.completeFile(ticket);
|
|
404
|
+
file.physical = { id: String(ticket.file_id), status: 2 };
|
|
371
405
|
transferred += source.size;
|
|
372
406
|
++completed;
|
|
373
407
|
if (callback)
|
|
374
408
|
callback((total ? transferred / total * 100 : completed / sources.size * 100).toFixed(2));
|
|
375
409
|
}
|
|
376
410
|
stage = "submit";
|
|
377
|
-
await
|
|
411
|
+
await control.submit(task.task_id);
|
|
378
412
|
return { ...task, files: added };
|
|
379
413
|
} catch (error) {
|
|
380
414
|
if (error instanceof Error) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oicq-icalingua-plus-plus",
|
|
3
3
|
"app_name": "oicq-icalingua-plus-plus",
|
|
4
|
-
"version": "1.26.
|
|
5
|
-
"app_version": "1.26.
|
|
4
|
+
"version": "1.26.30",
|
|
5
|
+
"app_version": "1.26.30",
|
|
6
6
|
"upday": "2026/11/14",
|
|
7
7
|
"protocol_version": "v11",
|
|
8
8
|
"description": "oicq(https://github.com/takayama-lily/oicq) v1 for Icalingua++",
|