Add streaming file upload and download actions

Introduces new OneBot actions for streaming file upload and download, including chunked file transfer with memory/disk management and SHA256 verification. Adds CleanStreamTempFile, DownloadFileStream, UploadFileStream, and TestStreamDownload actions, updates action routing and network adapters to support streaming via HTTP and WebSocket, and provides Python test scripts for concurrent upload testing.
This commit is contained in:
手瓜一十雪
2025-09-16 23:24:00 +08:00
parent 66f30e1ebf
commit 890d032794
14 changed files with 1163 additions and 17 deletions

View File

@@ -29,7 +29,9 @@ export class OB11Response {
return this.createResponse(null, 'failed', retcode, err, echo);
}
}
export interface OneBotRequestToolkit<T = unknown> {
send: (data: T) => Promise<void>;
}
export abstract class OneBotAction<PayloadType, ReturnDataType> {
actionName: typeof ActionName[keyof typeof ActionName] = ActionName.Unknown;
core: NapCatCore;
@@ -57,27 +59,27 @@ export abstract class OneBotAction<PayloadType, ReturnDataType> {
return { valid: true };
}
public async handle(payload: PayloadType, adaptername: string, config: NetworkAdapterConfig): Promise<OB11Return<ReturnDataType | null>> {
public async handle(payload: PayloadType, adaptername: string, config: NetworkAdapterConfig, req: OneBotRequestToolkit = { send: async () => { } }, echo?: string): Promise<OB11Return<ReturnDataType | null>> {
const result = await this.check(payload);
if (!result.valid) {
return OB11Response.error(result.message, 400);
}
try {
const resData = await this._handle(payload, adaptername, config);
return OB11Response.ok(resData);
const resData = await this._handle(payload, adaptername, config, req);
return OB11Response.ok(resData, echo);
} catch (e: unknown) {
this.core.context.logger.logError('发生错误', e);
return OB11Response.error((e as Error).message.toString() || (e as Error)?.stack?.toString() || '未知错误,可能操作超时', 200);
return OB11Response.error((e as Error).message.toString() || (e as Error)?.stack?.toString() || '未知错误,可能操作超时', 200, echo);
}
}
public async websocketHandle(payload: PayloadType, echo: unknown, adaptername: string, config: NetworkAdapterConfig): Promise<OB11Return<ReturnDataType | null>> {
public async websocketHandle(payload: PayloadType, echo: unknown, adaptername: string, config: NetworkAdapterConfig, req: OneBotRequestToolkit = { send: async () => { } }): Promise<OB11Return<ReturnDataType | null>> {
const result = await this.check(payload);
if (!result.valid) {
return OB11Response.error(result.message, 1400, echo);
}
try {
const resData = await this._handle(payload, adaptername, config);
const resData = await this._handle(payload, adaptername, config, req);
return OB11Response.ok(resData, echo);
} catch (e: unknown) {
this.core.context.logger.logError('发生错误', e);
@@ -85,5 +87,5 @@ export abstract class OneBotAction<PayloadType, ReturnDataType> {
}
}
abstract _handle(payload: PayloadType, adaptername: string, config: NetworkAdapterConfig): Promise<ReturnDataType>;
abstract _handle(payload: PayloadType, adaptername: string, config: NetworkAdapterConfig, req: OneBotRequestToolkit): Promise<ReturnDataType>;
}