diff --git a/src/core/apis/packet.ts b/src/core/apis/packet.ts index d6fc11fb..e2f70569 100644 --- a/src/core/apis/packet.ts +++ b/src/core/apis/packet.ts @@ -18,6 +18,8 @@ import { PacketMsgPttElement, PacketMsgVideoElement } from "@/core/packet/message/element"; +import { MiniAppReqParams, MiniAppRawData } from "@/core/packet/entities/miniApp"; +import { MiniAppAdaptShareInfoResp } from "@/core/packet/proto/action/miniAppAdaptShareInfo"; interface OffsetType { @@ -186,7 +188,10 @@ export class NTQQPacketApi { return `https://${resp.download.downloadDns}/ftn_handler/${Buffer.from(resp.download.downloadUrl).toString('hex')}/?fname=`; } - async signMiniAppShareInfo(appid: string, title: string, desc: string, time: number, scene: number, templateType: number, businessType: number, picUrl: string, vidUrl: string, jumpUrl: string, iconUrl: string, verType: number, shareType: number, versionId: string, withShareTicket: number, webURL: string, appidRich: string, template: any, field20: string) { - + async sendMiniAppShareInfoReq(param: MiniAppReqParams) { + const data = this.packetSession?.packer.packMiniAppAdaptShareInfo(param); + const ret = await this.sendPacket("LightAppSvc.mini_app_share.AdaptShareInfo", data!, true); + const body = new NapProtoMsg(MiniAppAdaptShareInfoResp).decode(Buffer.from(ret.hex_data, 'hex')) + return JSON.parse(body.content.jsonContent) as MiniAppRawData; } } diff --git a/src/core/packet/entities/miniApp.ts b/src/core/packet/entities/miniApp.ts new file mode 100644 index 00000000..62a29c2b --- /dev/null +++ b/src/core/packet/entities/miniApp.ts @@ -0,0 +1,79 @@ +export interface MiniAppReqCustomParams { + title: string; + desc: string; + picUrl: string; + jumpUrl: string; +} + +export interface MiniAppReqTemplateParams { + sdkId: string; + appId: string; + scene: number; + iconUrl: string; + templateType: number; + businessType: number; + verType: number; + shareType: number; + versionId: string; + withShareTicket: number; +} + +export interface MiniAppReqParams extends MiniAppReqCustomParams, MiniAppReqTemplateParams {} + +export interface MiniAppData { + ver: string; + prompt: string; + config: Config; + app: string; + view: string; + meta: MetaData; + miniappShareOrigin: number; + miniappOpenRefer: string; +} + +export interface MiniAppRawData { + appName: string; + appView: string; + ver: string; + desc: string; + prompt: string; + metaData: MetaData; + config: Config; +} + +interface Config { + type: string; + width: number; + height: number; + forward: number; + autoSize: number; + ctime: number; + token: string; +} + +interface Host { + uin: number; + nick: string; +} + +interface Detail { + appid: string; + appType: number; + title: string; + desc: string; + icon: string; + preview: string; + url: string; + scene: number; + host: Host; + shareTemplateId: string; + shareTemplateData: Record; + showLittleTail: string; + gamePoints: string; + gamePointsUrl: string; + shareOrigin: number; +} + +interface MetaData { + detail_1: Detail; +} diff --git a/src/core/packet/helper/miniAppHelper.ts b/src/core/packet/helper/miniAppHelper.ts new file mode 100644 index 00000000..62fb1366 --- /dev/null +++ b/src/core/packet/helper/miniAppHelper.ts @@ -0,0 +1,94 @@ +import { + MiniAppData, + MiniAppReqParams, + MiniAppRawData, + MiniAppReqCustomParams, + MiniAppReqTemplateParams +} from "@/core/packet/entities/miniApp"; + +type MiniAppTemplateNameList = "bili" | "weibo"; + +export abstract class MiniAppInfo { + static sdkId: string = "V1_PC_MINISDK_99.99.99_1_APP_A"; + template: MiniAppReqTemplateParams; + + private static appMap = new Map(); + + protected constructor(template: MiniAppReqTemplateParams) { + this.template = template; + } + + static get(name: MiniAppTemplateNameList): MiniAppInfo | undefined { + return this.appMap.get(name); + } + + static Bili = new class extends MiniAppInfo { + constructor() { + super({ + sdkId: MiniAppInfo.sdkId, + appId: "1109937557", + scene: 1, + templateType: 1, + businessType: 0, + verType: 3, + shareType: 0, + versionId: "cfc5f7b05b44b5956502edaecf9d2240", + withShareTicket: 0, + iconUrl: "https://miniapp.gtimg.cn/public/appicon/51f90239b78a2e4994c11215f4c4ba15_200.jpg" + }); + MiniAppInfo.appMap.set("bili", this); + } + } + + static WeiBo = new class extends MiniAppInfo { + constructor() { + super({ + sdkId: MiniAppInfo.sdkId, + appId: "1109224783", + scene: 1, + templateType: 1, + businessType: 0, + verType: 3, + shareType: 0, + versionId: "e482a3cc4e574d9b772e96ba6eec9ba2", + withShareTicket: 0, + iconUrl: "https://miniapp.gtimg.cn/public/appicon/35bbb44dc68e65194cfacfb206b8f1f7_200.jpg" + }); + MiniAppInfo.appMap.set("weibo", this); + } + } +} + +export class MiniAppInfoHelper { + static generateReq(custom: MiniAppReqCustomParams, template: MiniAppReqTemplateParams): MiniAppReqParams { + return { + ...custom, + ...template + }; + } + + static RawToSend(rawData: MiniAppRawData): MiniAppData { + return { + ver: rawData.ver, + prompt: rawData.prompt, + config: rawData.config, + app: rawData.appName, + view: rawData.appView, + meta: rawData.metaData, + miniappShareOrigin: 3, + miniappOpenRefer: "10002", + }; + } + + static SendToRaw(data: MiniAppData): MiniAppRawData { + return { + appName: data.app, + appView: data.view, + ver: data.ver, + desc: data.meta.detail_1.desc, + prompt: data.prompt, + metaData: data.meta, + config: data.config, + }; + } +} diff --git a/src/core/packet/packer.ts b/src/core/packet/packer.ts index 7e0ca0bf..eff1bec5 100644 --- a/src/core/packet/packer.ts +++ b/src/core/packet/packer.ts @@ -26,6 +26,8 @@ import { PacketClient } from "@/core/packet/client"; import { OidbSvcTrpcTcp0XE37_1700 } from "@/core/packet/proto/oidb/Oidb.0xE37_1700"; import { OidbSvcTrpcTcp0XE37_800 } from "@/core/packet/proto/oidb/Oidb.0XE37_800"; import { OidbSvcTrpcTcp0XEB7 } from "./proto/oidb/Oidb.0xEB7"; +import { MiniAppReqParams } from "@/core/packet/entities/miniApp"; +import { MiniAppAdaptShareInfoReq } from "@/core/packet/proto/action/miniAppAdaptShareInfo"; export type PacketHexStr = string & { readonly hexNya: unique symbol }; @@ -705,4 +707,41 @@ export class PacketPacker { } ), false, false); } + + packMiniAppAdaptShareInfo(req: MiniAppReqParams): PacketHexStr { + return this.packetPacket( + new NapProtoMsg(MiniAppAdaptShareInfoReq).encode( + { + appId: req.sdkId, + body: { + extInfo: { + field2: Buffer.alloc(0) + }, + appid: req.appId, + title: req.title, + desc: req.desc, + time: BigInt(Date.now()), + scene: req.scene, + templateType: req.templateType, + businessType: req.businessType, + picUrl: req.picUrl, + vidUrl: "", + jumpUrl: req.jumpUrl, + iconUrl: req.iconUrl, + verType: req.verType, + shareType: req.shareType, + versionId: req.versionId, + withShareTicket: req.withShareTicket, + webURL: "", + appidRich: Buffer.alloc(0), + template: { + templateId: "", + templateData: "" + }, + field20: "" + } + } + ) + ) + } } diff --git a/src/core/packet/proto/action/miniAppAdaptShareInfo.ts b/src/core/packet/proto/action/miniAppAdaptShareInfo.ts new file mode 100644 index 00000000..76bb2829 --- /dev/null +++ b/src/core/packet/proto/action/miniAppAdaptShareInfo.ts @@ -0,0 +1,49 @@ +import { ScalarType } from "@protobuf-ts/runtime"; +import { ProtoField } from "../NapProto"; + +export const MiniAppAdaptShareInfoReq = { + appId: ProtoField(2, ScalarType.STRING), + body: ProtoField(4, () => MiniAppAdaptShareInfoReqBody), +}; + +export const MiniAppAdaptShareInfoReqBody = { + extInfo: ProtoField(1, () => ExtInfo), + appid: ProtoField(2, ScalarType.STRING), + title: ProtoField(3, ScalarType.STRING), + desc: ProtoField(4, ScalarType.STRING), + time: ProtoField(5, ScalarType.UINT64), + scene: ProtoField(6, ScalarType.UINT32), + templateType: ProtoField(7, ScalarType.UINT32), + businessType: ProtoField(8, ScalarType.UINT32), + picUrl: ProtoField(9, ScalarType.STRING), + vidUrl: ProtoField(10, ScalarType.STRING), + jumpUrl: ProtoField(11, ScalarType.STRING), + iconUrl: ProtoField(12, ScalarType.STRING), + verType: ProtoField(13, ScalarType.UINT32), + shareType: ProtoField(14, ScalarType.UINT32), + versionId: ProtoField(15, ScalarType.STRING), + withShareTicket: ProtoField(16, ScalarType.UINT32), + webURL: ProtoField(17, ScalarType.STRING), + appidRich: ProtoField(18, ScalarType.BYTES), + template: ProtoField(19, () => Template), + field20: ProtoField(20, ScalarType.STRING), +}; + +export const ExtInfo = { + field2: ProtoField(2, ScalarType.BYTES), +}; + +export const Template = { + templateId: ProtoField(1, ScalarType.STRING), + templateData: ProtoField(2, ScalarType.STRING), +}; + +export const MiniAppAdaptShareInfoResp = { + field2: ProtoField(2, ScalarType.UINT32), + field3: ProtoField(3, ScalarType.STRING), + content: ProtoField(4, () => MiniAppAdaptShareInfoRespContent), +}; + +export const MiniAppAdaptShareInfoRespContent = { + jsonContent: ProtoField(2, ScalarType.STRING), +}; diff --git a/src/onebot/action/extends/GetMiniAppArk.ts b/src/onebot/action/extends/GetMiniAppArk.ts new file mode 100644 index 00000000..73ae5d74 --- /dev/null +++ b/src/onebot/action/extends/GetMiniAppArk.ts @@ -0,0 +1,85 @@ +import {ActionName} from '../types'; +import {FromSchema, JSONSchema} from 'json-schema-to-ts'; +import {GetPacketStatusDepends} from "@/onebot/action/packet/GetPacketStatus"; +import {MiniAppData, MiniAppRawData, MiniAppReqCustomParams, MiniAppReqParams} from "@/core/packet/entities/miniApp"; +import {MiniAppInfo, MiniAppInfoHelper} from "@/core/packet/helper/miniAppHelper"; + +const SchemaData = { + type: 'object', + properties: { + type: { + type: 'string', + enum: ['bili', 'weibo'] + }, + title: {type: 'string'}, + desc: {type: 'string'}, + picUrl: {type: 'string'}, + jumpUrl: {type: 'string'}, + iconUrl: {type: 'string'}, + sdkId: {type: 'string'}, + appId: {type: 'string'}, + scene: {type: ['number', 'string']}, + templateType: {type: ['number', 'string']}, + businessType: {type: ['number', 'string']}, + verType: {type: ['number', 'string']}, + shareType: {type: ['number', 'string']}, + versionId: {type: 'string'}, + withShareTicket: {type: ['number', 'string']}, + rawArkData: {type: ['boolean', 'string']} + }, + oneOf: [ + { + required: ['type', 'title', 'desc', 'picUrl', 'jumpUrl'] + }, + { + required: [ + 'title', 'desc', 'picUrl', 'jumpUrl', + 'iconUrl', 'appId', 'scene', 'templateType', 'businessType', + 'verType', 'shareType', 'versionId', 'withShareTicket' + ] + } + ] +} as const satisfies JSONSchema; + +type Payload = FromSchema; + +export class GetMiniAppArk extends GetPacketStatusDepends { + actionName = ActionName.GetMiniAppArk; + payloadSchema = SchemaData; + + async _handle(payload: Payload) { + let reqParam: MiniAppReqParams; + const customParams = { + title: payload.title, + desc: payload.desc, + picUrl: payload.picUrl, + jumpUrl: payload.jumpUrl + } as MiniAppReqCustomParams; + if (payload.type) { + reqParam = MiniAppInfoHelper.generateReq(customParams, MiniAppInfo.get(payload.type)!.template); + } else { + const { appId, scene, iconUrl, templateType, businessType, verType, shareType, versionId, withShareTicket } = payload as Required; + reqParam = MiniAppInfoHelper.generateReq( + customParams, + { + sdkId: payload.sdkId ?? MiniAppInfo.sdkId, + appId: appId, + scene: +scene, + iconUrl: iconUrl, + templateType: +templateType, + businessType: +businessType, + verType: +verType, + shareType: +shareType, + versionId: versionId, + withShareTicket: +withShareTicket + } + ) + } + const arkData = await this.core.apis.PacketApi.sendMiniAppShareInfoReq(reqParam); + return { + data: Boolean(payload.rawArkData) ? arkData : MiniAppInfoHelper.RawToSend(arkData) + } + } +} diff --git a/src/onebot/action/index.ts b/src/onebot/action/index.ts index aae77979..12ea7127 100644 --- a/src/onebot/action/index.ts +++ b/src/onebot/action/index.ts @@ -98,6 +98,7 @@ import { GoCQHTTPCheckUrlSafely } from './go-cqhttp/GoCQHTTPCheckUrlSafely'; import { GoCQHTTPGetModelShow } from './go-cqhttp/GoCQHTTPGetModelShow'; import { GoCQHTTPSetModelShow } from './go-cqhttp/GoCQHTTPSetModelShow'; import { GoCQHTTPDeleteFriend } from './go-cqhttp/GoCQHTTPDeleteFriend'; +import { GetMiniAppArk } from "@/onebot/action/extends/GetMiniAppArk"; export type ActionMap = Map>; @@ -210,6 +211,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo // new UploadForwardMsg(obContext, core), new GetGroupShutList(obContext, core), new GetGroupFileUrl(obContext, core), + new GetMiniAppArk(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 5a4e5fc9..5c998a47 100644 --- a/src/onebot/action/types.ts +++ b/src/onebot/action/types.ts @@ -134,7 +134,8 @@ export enum ActionName { GetGuildProfile = 'get_guild_service_profile', GetGroupIgnoredNotifies = 'get_group_ignored_notifies', - + SetGroupSign = "set_group_sign", + GetMiniAppArk = "get_mini_app_ark", // UploadForwardMsg = "upload_forward_msg", }