diff --git a/src/common/config.ts b/src/common/config.ts index a4d73fd..b6e1f4c 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -52,6 +52,7 @@ export class ConfigUtil { autoDeleteFile: false, autoDeleteFileSecond: 60, enablePoke: false, + musicSignUrl: '', } if (!fs.existsSync(this.configPath)) { diff --git a/src/common/types.ts b/src/common/types.ts index 58fd136..82e3a32 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -28,6 +28,7 @@ export interface Config { autoDeleteFileSecond?: number ffmpeg?: string // ffmpeg路径 enablePoke?: boolean + musicSignUrl?: string } export interface LLOneBotError { diff --git a/src/common/utils/sign.ts b/src/common/utils/sign.ts new file mode 100644 index 0000000..07de2f6 --- /dev/null +++ b/src/common/utils/sign.ts @@ -0,0 +1,35 @@ +import { log } from './log' + +export interface IdMusicSignPostData { + type: 'qq' | '163' + id: string | number +} + +export interface CustomMusicSignPostData { + type: 'custom' + url: string + audio: string + title: string + image?: string + singer?: string +} + +export class MusicSign { + private readonly url: string + + constructor(url: string) { + this.url = url + } + + async sign(postData: CustomMusicSignPostData | IdMusicSignPostData): Promise { + const resp = await fetch(this.url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(postData), + }) + if (!resp.ok) throw new Error(resp.statusText) + const data = await resp.json() + log('音乐消息生成成功', data) + return data + } +} diff --git a/src/onebot11/action/msg/SendMsg.ts b/src/onebot11/action/msg/SendMsg.ts index 8ec7f4d..7f07065 100644 --- a/src/onebot11/action/msg/SendMsg.ts +++ b/src/onebot11/action/msg/SendMsg.ts @@ -16,6 +16,7 @@ import { OB11MessageData, OB11MessageDataType, OB11MessageMixType, + OB11MessageMusic, OB11MessageNode, OB11PostSendMsg, } from '../../types' @@ -26,12 +27,13 @@ import { ActionName, BaseCheckResult } from '../types' import * as fs from 'node:fs' import { decodeCQCode } from '../../cqcode' import { dbUtil } from '../../../common/db' -import { ALLOW_SEND_TEMP_MSG } from '../../../common/config' +import { ALLOW_SEND_TEMP_MSG, getConfigUtil } from '../../../common/config' import { log } from '../../../common/utils/log' import { sleep } from '../../../common/utils/helper' import { uri2local } from '../../../common/utils' import { crychic } from '../../../ntqqapi/external/crychic' import { NTQQGroupApi } from '../../../ntqqapi/api' +import { MusicSign } from '../../../common/utils/sign' function checkSendMessage(sendMsgList: OB11MessageData[]) { function checkUri(uri: string): boolean { @@ -376,16 +378,26 @@ export class SendMsg extends BaseAction { } } else { if (this.getSpecialMsgNum(payload, OB11MessageDataType.music)) { - const music: OB11MessageCustomMusic = messages[0] as OB11MessageCustomMusic + const music = messages[0] as OB11MessageMusic if (music) { - const { url, audio, title, content, image } = music.data - const selfPeer: Peer = { peerUid: selfInfo.uid, chatType: ChatType.friend } - // 搞不定! - // const musicMsg = await this.send(selfPeer, [this.genMusicElement(url, audio, title, content, image)], [], false) - // 转发 - // const res = await NTQQApi.forwardMsg(selfPeer, peer, [musicMsg.msgId]) - // log("转发音乐消息成功", res); - // return {message_id: musicMsg.msgShortId} + const { musicSignUrl } = getConfigUtil().getConfig() + if (!musicSignUrl) { + throw '音乐签名地址未配置' + } + const { type } = music.data + if (!['qq', '163', 'custom'].includes(type)) { + throw `不支持的音乐类型 ${type}` + } + let jsonContent: string + try { + jsonContent = await new MusicSign(musicSignUrl).sign(music.data) + } catch (e) { + throw `签名音乐消息失败:${e}` + } + messages[0] = { + type: OB11MessageDataType.json, + data: { data: jsonContent }, + } } } } diff --git a/src/onebot11/types.ts b/src/onebot11/types.ts index 8b9040c..3dd281b 100644 --- a/src/onebot11/types.ts +++ b/src/onebot11/types.ts @@ -1,5 +1,6 @@ import { PicSubType, RawMessage } from '../ntqqapi/types' import { EventType } from './event/OB11BaseEvent' +import { IdMusicSignPostData, CustomMusicSignPostData } from '../common/utils/sign' export interface OB11User { user_id: number @@ -219,18 +220,18 @@ export interface OB11MessageNode { } } +export interface OB11MessageIdMusic { + type: OB11MessageDataType.music + data: IdMusicSignPostData +} + export interface OB11MessageCustomMusic { type: OB11MessageDataType.music - data: { - type: 'custom' - url: string - audio: string - title: string - content?: string - image?: string - } + data: Omit & { content?: string } } +export type OB11MessageMusic = OB11MessageIdMusic | OB11MessageCustomMusic + export interface OB11MessageJson { type: OB11MessageDataType.json data: { config: { token: string } } & any @@ -247,6 +248,7 @@ export type OB11MessageData = | OB11MessageFile | OB11MessageVideo | OB11MessageNode + | OB11MessageIdMusic | OB11MessageCustomMusic | OB11MessageJson | OB11MessagePoke diff --git a/src/renderer/index.ts b/src/renderer/index.ts index 557d120..259941f 100644 --- a/src/renderer/index.ts +++ b/src/renderer/index.ts @@ -95,7 +95,9 @@ async function onSettingWindowCreated(view: Element) { HTTP 事件上报密钥
- +
@@ -158,9 +160,17 @@ async function onSettingWindowCreated(view: Element) { ), SettingItem( 'ffmpeg 路径,发送语音、视频需要,同时保证ffprobe和ffmpeg在一起', - ` 下载地址 , 路径:${!isEmpty(config.ffmpeg) ? config.ffmpeg : '未指定'}`, + ` 下载地址 , 路径:${ + !isEmpty(config.ffmpeg) ? config.ffmpeg : '未指定' + }`, SettingButton('选择ffmpeg', 'config-ffmpeg-select'), ), + SettingItem( + '音乐卡片签名地址', + null, + `
`, + 'config-musicSignUrl', + ), SettingItem('', null, SettingButton('保存', 'config-ob11-save', 'primary')), ]), SettingList([