diff --git a/src/core/apis/packet.ts b/src/core/apis/packet.ts index 8091a095..04d1ad28 100644 --- a/src/core/apis/packet.ts +++ b/src/core/apis/packet.ts @@ -8,9 +8,10 @@ import { NapProtoMsg } from '@/core/packet/proto/NapProto'; import { OidbSvcTrpcTcp0X9067_202_Rsp_Body } from '@/core/packet/proto/oidb/Oidb.0x9067_202'; import { OidbSvcTrpcTcpBase, OidbSvcTrpcTcpBaseRsp } from '@/core/packet/proto/oidb/OidbBase'; import { OidbSvcTrpcTcp0XFE1_2RSP } from '@/core/packet/proto/oidb/Oidb.0XFE1_2'; -import {LogWrapper} from "@/common/log"; -import {SendLongMsgResp} from "@/core/packet/proto/message/action"; -import {PacketMsg} from "@/core/packet/msg/message"; +import { LogWrapper } from "@/common/log"; +import { SendLongMsgResp } from "@/core/packet/proto/message/action"; +import { PacketMsg } from "@/core/packet/msg/message"; +import { OidbSvcTrpcTcp0x6D6Response } from "@/core/packet/proto/oidb/Oidb.0x6D6"; interface OffsetType { [key: string]: { @@ -112,4 +113,15 @@ export class NTQQPacketApi { const resp = new NapProtoMsg(SendLongMsgResp).decode(Buffer.from(ret.hex_data, 'hex')); return resp.result.resId; } + + async sendGroupFileDownloadReq(groupUin: number, fileUUID: string) { + const data = this.packetPacker.packGroupFileDownloadReq(groupUin, fileUUID); + const ret = await this.sendPacket('OidbSvcTrpcTcp.0x6d6_2', data, true); + const body = new NapProtoMsg(OidbSvcTrpcTcpBaseRsp).decode(Buffer.from(ret.hex_data, 'hex')).body; + const resp = new NapProtoMsg(OidbSvcTrpcTcp0x6D6Response).decode(body); + if (resp.download.retCode !== 0){ + throw new Error(`sendGroupFileDownloadReq error: ${resp.download.clientWording}`); + } + return `https://${resp.download.downloadDns}/ftn_handler/${Buffer.from(resp.download.downloadUrl).toString('hex')}/?fname=` + } } diff --git a/src/core/packet/packer.ts b/src/core/packet/packer.ts index 243e9559..be064aa0 100644 --- a/src/core/packet/packer.ts +++ b/src/core/packet/packer.ts @@ -288,14 +288,14 @@ export class PacketPacker { packGroupFileDownloadReq(groupUin: number, fileUUID: string): PacketHexStr { return this.toHexStr( - new NapProtoMsg(OidbSvcTrpcTcp0x6D6).encode({ + this.packOidbPacket(0x6D6, 2, new NapProtoMsg(OidbSvcTrpcTcp0x6D6).encode({ download: { groupUin: groupUin, appId: 7, busId: 102, fileId: fileUUID } - }) + }), true, false) ) } diff --git a/src/onebot/action/file/GetGroupFileUrl.ts b/src/onebot/action/file/GetGroupFileUrl.ts new file mode 100644 index 00000000..281f6e06 --- /dev/null +++ b/src/onebot/action/file/GetGroupFileUrl.ts @@ -0,0 +1,37 @@ +import BaseAction from '../BaseAction'; +import { ActionName } from '../types'; +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; +import {FileNapCatOneBotUUID} from "@/common/helper"; + +const SchemaData = { + type: 'object', + properties: { + group_id: { type: ['number', 'string'] }, + file_id: { type: ['string'] }, + }, + required: ['group_id', 'file_id'], +} as const satisfies JSONSchema; + +type Payload = FromSchema; + +interface GetGroupFileUrlResponse { + url?: string; +} + +export class GetGroupFileUrl extends BaseAction { + actionName = ActionName.GOCQHTTP_GetGroupFileUrl; + payloadSchema = SchemaData; + + async _handle(payload: Payload) { + if (!this.core.apis.PacketApi.available) { + throw new Error('PacketClient is not init'); + } + const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file_id) || FileNapCatOneBotUUID.decodeModelId(payload.file_id); + if (contextMsgFile?.fileUUID) { + return { + url: await this.core.apis.PacketApi.sendGroupFileDownloadReq(+payload.group_id, contextMsgFile.fileUUID) + } + } + throw new Error('real fileUUID not found!'); + } +} diff --git a/src/onebot/action/index.ts b/src/onebot/action/index.ts index 6d97e24e..08616991 100644 --- a/src/onebot/action/index.ts +++ b/src/onebot/action/index.ts @@ -90,6 +90,7 @@ import { SetSpecialTittle } from './extends/SetSpecialTittle'; import { UploadForwardMsg } from "@/onebot/action/extends/UploadForwardMsg"; import { GetGroupShutList } from './group/GetGroupShutList'; import { GetGroupMemberList } from './group/GetGroupMemberList'; +import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl"; export type ActionMap = Map>; @@ -192,6 +193,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo new SetSpecialTittle(obContext, core), new UploadForwardMsg(obContext, core), new GetGroupShutList(obContext, core), + new GetGroupFileUrl(obContext, core), ]; const actionMap = new Map(); for (const action of actionHandlers) { diff --git a/src/onebot/action/types.ts b/src/onebot/action/types.ts index abc30876..7e776920 100644 --- a/src/onebot/action/types.ts +++ b/src/onebot/action/types.ts @@ -85,6 +85,7 @@ export enum ActionName { MarkGroupMsgAsRead = 'mark_group_msg_as_read', GoCQHTTP_UploadGroupFile = 'upload_group_file', GOCQHTTP_DeleteGroupFile = 'delete_group_file', + GOCQHTTP_GetGroupFileUrl = 'get_group_file_url', GoCQHTTP_CreateGroupFileFolder = 'create_group_file_folder', GoCQHTTP_DeleteGroupFileFolder = 'delete_group_file_folder', GoCQHTTP_GetGroupFileSystemInfo = 'get_group_file_system_info',