Add timeout parameter to file and packet API methods
Some checks are pending
Build Action / Build-LiteLoader (push) Waiting to run
Build Action / Build-Shell (push) Waiting to run

Introduces an optional timeout parameter (defaulting to 20000ms) to various file and packet API methods for improved control over request duration. Updates all relevant method calls and internal usages to support the new timeout argument, including OneBot message API calls with a shorter timeout for file, video, and ptt URL retrieval.
This commit is contained in:
手瓜一十雪 2025-09-02 09:54:42 +08:00
parent 7ab44dcb34
commit f3c07ed8fc
5 changed files with 32 additions and 32 deletions

View File

@ -64,13 +64,13 @@ export class NTQQFileApi {
} }
} }
async getFileUrl(chatType: ChatType, peer: string, fileUUID?: string, file10MMd5?: string | undefined) { async getFileUrl(chatType: ChatType, peer: string, fileUUID?: string, file10MMd5?: string | undefined,timeout: number = 20000) {
if (this.core.apis.PacketApi.packetStatus) { if (this.core.apis.PacketApi.packetStatus) {
try { try {
if (chatType === ChatType.KCHATTYPEGROUP && fileUUID) { if (chatType === ChatType.KCHATTYPEGROUP && fileUUID) {
return this.core.apis.PacketApi.pkt.operation.GetGroupFileUrl(+peer, fileUUID); return this.core.apis.PacketApi.pkt.operation.GetGroupFileUrl(+peer, fileUUID, timeout);
} else if (file10MMd5 && fileUUID) { } else if (file10MMd5 && fileUUID) {
return this.core.apis.PacketApi.pkt.operation.GetPrivateFileUrl(peer, fileUUID, file10MMd5); return this.core.apis.PacketApi.pkt.operation.GetPrivateFileUrl(peer, fileUUID, file10MMd5, timeout);
} }
} catch (error) { } catch (error) {
this.context.logger.logError('获取文件URL失败', (error as Error).message); this.context.logger.logError('获取文件URL失败', (error as Error).message);
@ -79,7 +79,7 @@ export class NTQQFileApi {
throw new Error('fileUUID or file10MMd5 is undefined'); throw new Error('fileUUID or file10MMd5 is undefined');
} }
async getPttUrl(peer: string, fileUUID?: string) { async getPttUrl(peer: string, fileUUID?: string,timeout: number = 20000) {
if (this.core.apis.PacketApi.packetStatus && fileUUID) { if (this.core.apis.PacketApi.packetStatus && fileUUID) {
let appid = new NapProtoMsg(FileId).decode(Buffer.from(fileUUID.replaceAll('-', '+').replaceAll('_', '/'), 'base64')).appid; let appid = new NapProtoMsg(FileId).decode(Buffer.from(fileUUID.replaceAll('-', '+').replaceAll('_', '/'), 'base64')).appid;
try { try {
@ -90,7 +90,7 @@ export class NTQQFileApi {
uploadTime: 0, uploadTime: 0,
ttl: 0, ttl: 0,
subType: 0, subType: 0,
}); }, timeout);
} else if (fileUUID) { } else if (fileUUID) {
return this.core.apis.PacketApi.pkt.operation.GetPttUrl(peer, { return this.core.apis.PacketApi.pkt.operation.GetPttUrl(peer, {
fileUuid: fileUUID, fileUuid: fileUUID,
@ -98,7 +98,7 @@ export class NTQQFileApi {
uploadTime: 0, uploadTime: 0,
ttl: 0, ttl: 0,
subType: 0, subType: 0,
}); }, timeout);
} }
} catch (error) { } catch (error) {
this.context.logger.logError('获取文件URL失败', (error as Error).message); this.context.logger.logError('获取文件URL失败', (error as Error).message);
@ -107,7 +107,7 @@ export class NTQQFileApi {
throw new Error('packet cant get ptt url'); throw new Error('packet cant get ptt url');
} }
async getVideoUrlPacket(peer: string, fileUUID?: string) { async getVideoUrlPacket(peer: string, fileUUID?: string,timeout: number = 20000) {
if (this.core.apis.PacketApi.packetStatus && fileUUID) { if (this.core.apis.PacketApi.packetStatus && fileUUID) {
let appid = new NapProtoMsg(FileId).decode(Buffer.from(fileUUID.replaceAll('-', '+').replaceAll('_', '/'), 'base64')).appid; let appid = new NapProtoMsg(FileId).decode(Buffer.from(fileUUID.replaceAll('-', '+').replaceAll('_', '/'), 'base64')).appid;
try { try {
@ -118,7 +118,7 @@ export class NTQQFileApi {
uploadTime: 0, uploadTime: 0,
ttl: 0, ttl: 0,
subType: 0, subType: 0,
}); }, timeout);
} else if (fileUUID) { } else if (fileUUID) {
return this.core.apis.PacketApi.pkt.operation.GetVideoUrl(peer, { return this.core.apis.PacketApi.pkt.operation.GetVideoUrl(peer, {
fileUuid: fileUUID, fileUuid: fileUUID,
@ -126,7 +126,7 @@ export class NTQQFileApi {
uploadTime: 0, uploadTime: 0,
ttl: 0, ttl: 0,
subType: 0, subType: 0,
}); }, timeout);
} }
} catch (error) { } catch (error) {
this.context.logger.logError('获取文件URL失败', (error as Error).message); this.context.logger.logError('获取文件URL失败', (error as Error).message);

View File

@ -80,15 +80,15 @@ export abstract class IPacketClient {
}); });
} }
async sendPacket(cmd: string, data: PacketHexStr, rsp = false): Promise<RecvPacketData> { async sendPacket(cmd: string, data: PacketHexStr, rsp = false, timeout = 20000): Promise<RecvPacketData> {
const md5 = crypto.createHash('md5').update(data).digest('hex'); const md5 = crypto.createHash('md5').update(data).digest('hex');
const trace_id = (randText(4) + md5 + data).slice(0, data.length / 2); const trace_id = (randText(4) + md5 + data).slice(0, data.length / 2);
return this.sendCommand(cmd, data, trace_id, rsp, 20000, async () => { return this.sendCommand(cmd, data, trace_id, rsp, timeout, async () => {
await this.napcore.sendSsoCmdReqByContend(cmd, trace_id); await this.napcore.sendSsoCmdReqByContend(cmd, trace_id);
}); });
} }
async sendOidbPacket(pkt: OidbPacket, rsp = false): Promise<RecvPacketData> { async sendOidbPacket(pkt: OidbPacket, rsp = false, timeout = 20000): Promise<RecvPacketData> {
return this.sendPacket(pkt.cmd, pkt.data, rsp); return this.sendPacket(pkt.cmd, pkt.data, rsp, timeout);
} }
} }

View File

@ -73,8 +73,8 @@ export class PacketClientContext {
await this._client.init(pid, recv, send); await this._client.init(pid, recv, send);
} }
async sendOidbPacket<T extends boolean = false>(pkt: OidbPacket, rsp?: T): Promise<T extends true ? Buffer : void> { async sendOidbPacket<T extends boolean = false>(pkt: OidbPacket, rsp?: T, timeout?: number): Promise<T extends true ? Buffer : void> {
const raw = await this._client.sendOidbPacket(pkt, rsp); const raw = await this._client.sendOidbPacket(pkt, rsp, timeout);
return (rsp ? Buffer.from(raw.hex_data, 'hex') : undefined) as T extends true ? Buffer : void; return (rsp ? Buffer.from(raw.hex_data, 'hex') : undefined) as T extends true ? Buffer : void;
} }

View File

@ -122,37 +122,37 @@ export class PacketOperationContext {
return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`; return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`;
} }
async GetPttUrl(selfUid: string, node: NapProtoEncodeStructType<typeof IndexNode>) { async GetPttUrl(selfUid: string, node: NapProtoEncodeStructType<typeof IndexNode>,timeout: number = 20000) {
const req = trans.DownloadPtt.build(selfUid, node); const req = trans.DownloadPtt.build(selfUid, node);
const resp = await this.context.client.sendOidbPacket(req, true); const resp = await this.context.client.sendOidbPacket(req, true, timeout);
const res = trans.DownloadPtt.parse(resp); const res = trans.DownloadPtt.parse(resp);
return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`; return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`;
} }
async GetVideoUrl(selfUid: string, node: NapProtoEncodeStructType<typeof IndexNode>) { async GetVideoUrl(selfUid: string, node: NapProtoEncodeStructType<typeof IndexNode>, timeout: number = 20000) {
const req = trans.DownloadVideo.build(selfUid, node); const req = trans.DownloadVideo.build(selfUid, node);
const resp = await this.context.client.sendOidbPacket(req, true); const resp = await this.context.client.sendOidbPacket(req, true, timeout);
const res = trans.DownloadVideo.parse(resp); const res = trans.DownloadVideo.parse(resp);
return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`; return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`;
} }
async GetGroupImageUrl(groupUin: number, node: NapProtoEncodeStructType<typeof IndexNode>) { async GetGroupImageUrl(groupUin: number, node: NapProtoEncodeStructType<typeof IndexNode>, timeout: number = 20000) {
const req = trans.DownloadGroupImage.build(groupUin, node); const req = trans.DownloadGroupImage.build(groupUin, node);
const resp = await this.context.client.sendOidbPacket(req, true); const resp = await this.context.client.sendOidbPacket(req, true, timeout);
const res = trans.DownloadImage.parse(resp); const res = trans.DownloadImage.parse(resp);
return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`; return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`;
} }
async GetGroupPttUrl(groupUin: number, node: NapProtoEncodeStructType<typeof IndexNode>) { async GetGroupPttUrl(groupUin: number, node: NapProtoEncodeStructType<typeof IndexNode>, timeout: number = 20000) {
const req = trans.DownloadGroupPtt.build(groupUin, node); const req = trans.DownloadGroupPtt.build(groupUin, node);
const resp = await this.context.client.sendOidbPacket(req, true); const resp = await this.context.client.sendOidbPacket(req, true, timeout);
const res = trans.DownloadImage.parse(resp); const res = trans.DownloadImage.parse(resp);
return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`; return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`;
} }
async GetGroupVideoUrl(groupUin: number, node: NapProtoEncodeStructType<typeof IndexNode>) { async GetGroupVideoUrl(groupUin: number, node: NapProtoEncodeStructType<typeof IndexNode>, timeout: number = 20000) {
const req = trans.DownloadGroupVideo.build(groupUin, node); const req = trans.DownloadGroupVideo.build(groupUin, node);
const resp = await this.context.client.sendOidbPacket(req, true); const resp = await this.context.client.sendOidbPacket(req, true, timeout);
const res = trans.DownloadImage.parse(resp); const res = trans.DownloadImage.parse(resp);
return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`; return `https://${res.download.info.domain}${res.download.info.urlPath}${res.download.rKeyParam}`;
} }
@ -243,16 +243,16 @@ export class PacketOperationContext {
return res.rename.retCode; return res.rename.retCode;
} }
async GetGroupFileUrl(groupUin: number, fileUUID: string) { async GetGroupFileUrl(groupUin: number, fileUUID: string,timeout: number = 20000) {
const req = trans.DownloadGroupFile.build(groupUin, fileUUID); const req = trans.DownloadGroupFile.build(groupUin, fileUUID);
const resp = await this.context.client.sendOidbPacket(req, true); const resp = await this.context.client.sendOidbPacket(req, true, timeout);
const res = trans.DownloadGroupFile.parse(resp); const res = trans.DownloadGroupFile.parse(resp);
return `https://${res.download.downloadDns}/ftn_handler/${Buffer.from(res.download.downloadUrl).toString('hex')}/?fname=`; return `https://${res.download.downloadDns}/ftn_handler/${Buffer.from(res.download.downloadUrl).toString('hex')}/?fname=`;
} }
async GetPrivateFileUrl(self_id: string, fileUUID: string, md5: string) { async GetPrivateFileUrl(self_id: string, fileUUID: string, md5: string, timeout: number = 20000) {
const req = trans.DownloadPrivateFile.build(self_id, fileUUID, md5); const req = trans.DownloadPrivateFile.build(self_id, fileUUID, md5);
const resp = await this.context.client.sendOidbPacket(req, true); const resp = await this.context.client.sendOidbPacket(req, true, timeout);
const res = trans.DownloadPrivateFile.parse(resp); const res = trans.DownloadPrivateFile.parse(resp);
return `http://${res.body?.result?.server}:${res.body?.result?.port}${res.body?.result?.url?.slice(8)}&isthumb=0`; return `http://${res.body?.result?.server}:${res.body?.result?.port}${res.body?.result?.url?.slice(8)}&isthumb=0`;
} }

View File

@ -150,7 +150,7 @@ export class OneBotMsgApi {
if (this.core.apis.PacketApi.packetStatus) { if (this.core.apis.PacketApi.packetStatus) {
let url; let url;
try { try {
url = await this.core.apis.FileApi.getFileUrl(msg.chatType, msg.peerUid, element.fileUuid, element.file10MMd5) url = await this.core.apis.FileApi.getFileUrl(msg.chatType, msg.peerUid, element.fileUuid, element.file10MMd5, 1500)
} catch (error) { } catch (error) {
url = ''; url = '';
} }
@ -393,7 +393,7 @@ export class OneBotMsgApi {
if (!videoDownUrl) { if (!videoDownUrl) {
if (this.core.apis.PacketApi.packetStatus) { if (this.core.apis.PacketApi.packetStatus) {
try { try {
videoDownUrl = await this.core.apis.FileApi.getVideoUrlPacket(msg.peerUid, element.fileUuid); videoDownUrl = await this.core.apis.FileApi.getVideoUrlPacket(msg.peerUid, element.fileUuid, 1500);
} catch (e) { } catch (e) {
this.core.context.logger.logError('获取视频url失败', (e as Error).stack); this.core.context.logger.logError('获取视频url失败', (e as Error).stack);
videoDownUrl = element.filePath; videoDownUrl = element.filePath;
@ -424,7 +424,7 @@ export class OneBotMsgApi {
let pttUrl = ''; let pttUrl = '';
if (this.core.apis.PacketApi.packetStatus) { if (this.core.apis.PacketApi.packetStatus) {
try { try {
pttUrl = await this.core.apis.FileApi.getPttUrl(msg.peerUid, element.fileUuid); pttUrl = await this.core.apis.FileApi.getPttUrl(msg.peerUid, element.fileUuid, 1500);
} catch (e) { } catch (e) {
this.core.context.logger.logError('获取语音url失败', (e as Error).stack); this.core.context.logger.logError('获取语音url失败', (e as Error).stack);
pttUrl = element.filePath; pttUrl = element.filePath;