refactor: send music card

feat: send mface
This commit is contained in:
linyuchen 2024-05-02 22:23:59 +08:00
parent 8ae0d07ec1
commit 2662e875ca
6 changed files with 121 additions and 120 deletions

@ -1 +1 @@
Subproject commit b8167109159bfda7057b95936e5470929462e4a0 Subproject commit f22a4cee7dd1e41073b8e1ad7e99ada33c863992

Binary file not shown.

View File

@ -1,4 +1,4 @@
import { getGroup } from '@/core/data'; import { getGroup, groupMembers } from '@/core/data';
import { OB11GroupMember } from '../../types'; import { OB11GroupMember } from '../../types';
import { OB11Constructor } from '../../constructor'; import { OB11Constructor } from '../../constructor';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
@ -8,7 +8,8 @@ import { WebApi } from '@/core/apis/webapi';
import { logDebug } from '@/common/utils/log'; import { logDebug } from '@/common/utils/log';
export interface PayloadType { export interface PayloadType {
group_id: number group_id: number,
no_cache?: boolean | string
} }
@ -23,10 +24,15 @@ class GetGroupMemberList extends BaseAction<PayloadType, OB11GroupMember[]> {
if (!group) { if (!group) {
throw (`${payload.group_id}不存在`); throw (`${payload.group_id}不存在`);
} }
const GroupMember = OB11Constructor.groupMembers(group); if (payload.no_cache || payload.no_cache === 'true') {
const _groupMembers = await NTQQGroupApi.getGroupMembers(payload.group_id.toString());
groupMembers.set(group.groupCode, _groupMembers);
}
const _groupMembers = OB11Constructor.groupMembers(group);
// 方便索引处理 // 方便索引处理
for (let i = 0, len = GroupMember.length; i < len; i++) { for (let i = 0, len = _groupMembers.length; i < len; i++) {
MemberMap.set(GroupMember[i].user_id, GroupMember[i]); MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
} }
// 合并数据 // 合并数据
for (let i = 0, len = WebGroupMember.length; i < len; i++) { for (let i = 0, len = WebGroupMember.length; i < len; i++) {

View File

@ -12,7 +12,7 @@ import {
import { import {
OB11MessageCustomMusic, OB11MessageCustomMusic,
OB11MessageData, OB11MessageData,
OB11MessageDataType, OB11MessageDataType, OB11MessageIdMusic,
OB11MessageMixType, OB11MessageMixType,
OB11MessageNode, OB11MessageNode,
OB11PostSendMsg OB11PostSendMsg
@ -27,10 +27,10 @@ import { log, logDebug, logError } from '@/common/utils/log';
import { sleep } from '@/common/utils/helper'; import { sleep } from '@/common/utils/helper';
import { uri2local } from '@/common/utils/file'; import { uri2local } from '@/common/utils/file';
import { getFriend, getGroup, getGroupMember, getUidByUin, selfInfo } from '@/core/data'; import { getFriend, getGroup, getGroupMember, getUidByUin, selfInfo } from '@/core/data';
import { NTQQMsgApi } from '../../../core/src/apis'; import { NTQQMsgApi } from '@/core/apis';
import { NTQQFileApi } from '../../../core/src/apis'; import { NTQQFileApi } from '@/core/apis';
import { ob11Config } from '@/onebot11/config'; import { ob11Config } from '@/onebot11/config';
import { CustomMusicSignPostData, MusicSign } from '@/core/apis/sign'; import { CustomMusicSignPostData, IdMusicSignPostData, MusicSign } from '@/core/apis/sign';
const ALLOW_SEND_TEMP_MSG = false; const ALLOW_SEND_TEMP_MSG = false;
@ -46,23 +46,29 @@ function checkSendMessage(sendMsgList: OB11MessageData[]) {
const data = msg['data']; const data = msg['data'];
if (type === 'text' && !data['text']) { if (type === 'text' && !data['text']) {
return 400; return 400;
} else if (['image', 'voice', 'record'].includes(type)) { }
else if (['image', 'voice', 'record'].includes(type)) {
if (!data['file']) { if (!data['file']) {
return 400; return 400;
} else { }
else {
if (checkUri(data['file'])) { if (checkUri(data['file'])) {
return 200; return 200;
} else { }
else {
return 400; return 400;
} }
} }
} else if (type === 'at' && !data['qq']) { }
return 400; else if (type === 'at' && !data['qq']) {
} else if (type === 'reply' && !data['id']) {
return 400; return 400;
} }
} else { else if (type === 'reply' && !data['id']) {
return 400;
}
}
else {
return 400; return 400;
} }
} }
@ -82,16 +88,18 @@ export function convertMessage2List(message: OB11MessageMixType, autoEscape = fa
text: message text: message
} }
}]; }];
} else { }
else {
message = decodeCQCode(message.toString()); message = decodeCQCode(message.toString());
} }
} else if (!Array.isArray(message)) { }
else if (!Array.isArray(message)) {
message = [message]; message = [message];
} }
return message; return message;
} }
async function genCustomMusicElement(url: string, audio: string, title: string, image: string | undefined, singer: string | undefined): Promise<SendArkElement | undefined> { async function genMusicElement(postData: IdMusicSignPostData | CustomMusicSignPostData): Promise<SendArkElement | undefined> {
// const musicJson = { // const musicJson = {
// app: 'com.tencent.structmsg', // app: 'com.tencent.structmsg',
// config: { // config: {
@ -123,35 +131,19 @@ async function genCustomMusicElement(url: string, audio: string, title: string,
// ver: '0.0.0.1', // ver: '0.0.0.1',
// view: 'news' // view: 'news'
// }; // };
try{ const signUrl = ob11Config.musicSignUrl;
const postData: CustomMusicSignPostData = { if (!signUrl) {
type: 'custom', throw Error('音乐消息签名地址未配置');
url,
audio,
title,
image,
singer
};
const musicJson = await new MusicSign(ob11Config.musicSignUrl).sign(postData);
return SendMsgElementConstructor.ark(musicJson);
}catch (e) {
logError('生成音乐消息失败', e);
} }
}
async function genIdMusicElement(type: 'qq' | '163', id: string | number): Promise<SendArkElement | undefined> {
try { try {
const postData = { const musicJson = await new MusicSign(signUrl).sign(postData);
type,
id
};
const musicJson = await new MusicSign(ob11Config.musicSignUrl).sign(postData);
return SendMsgElementConstructor.ark(musicJson); return SendMsgElementConstructor.ark(musicJson);
} catch (e) { } catch (e) {
logError('生成音乐消息失败', e); logError('生成音乐消息失败', e);
} }
} }
export async function createSendElements(messageData: OB11MessageData[], group: Group | undefined, ignoreTypes: OB11MessageDataType[] = []) { export async function createSendElements(messageData: OB11MessageData[], group: Group | undefined, ignoreTypes: OB11MessageDataType[] = []) {
const sendElements: SendMessageElement[] = []; const sendElements: SendMessageElement[] = [];
const deleteAfterSentFiles: string[] = []; const deleteAfterSentFiles: string[] = [];
@ -176,7 +168,8 @@ export async function createSendElements(messageData: OB11MessageData[], group:
atQQ = atQQ.toString(); atQQ = atQQ.toString();
if (atQQ === 'all') { if (atQQ === 'all') {
sendElements.push(SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员')); sendElements.push(SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员'));
} else { }
else {
// const atMember = group?.members.find(m => m.uin == atQQ) // const atMember = group?.members.find(m => m.uin == atQQ)
const atMember = await getGroupMember(group?.groupCode, atQQ); const atMember = await getGroupMember(group?.groupCode, atQQ);
if (atMember) { if (atMember) {
@ -203,7 +196,12 @@ export async function createSendElements(messageData: OB11MessageData[], group:
} }
} }
break; break;
case OB11MessageDataType.mface: {
sendElements.push(
SendMsgElementConstructor.mface(sendMsg.data.emoji_package_id, sendMsg.data.emoji_id, sendMsg.data.key, sendMsg.data.summary),
);
}
break;
case OB11MessageDataType.image: case OB11MessageDataType.image:
case OB11MessageDataType.file: case OB11MessageDataType.file:
case OB11MessageDataType.video: case OB11MessageDataType.video:
@ -215,9 +213,11 @@ export async function createSendElements(messageData: OB11MessageData[], group:
if (cache) { if (cache) {
if (fs.existsSync(cache.path)) { if (fs.existsSync(cache.path)) {
file = 'file://' + cache.path; file = 'file://' + cache.path;
} else if (cache.url) { }
else if (cache.url) {
file = cache.url; file = cache.url;
} else { }
else {
const fileMsg = await dbUtil.getMsgByLongId(cache.msgId); const fileMsg = await dbUtil.getMsgByLongId(cache.msgId);
if (fileMsg) { if (fileMsg) {
const downloadPath = await NTQQFileApi.downloadMedia(fileMsg.msgId, fileMsg.chatType, fileMsg.peerUid, const downloadPath = await NTQQFileApi.downloadMedia(fileMsg.msgId, fileMsg.chatType, fileMsg.peerUid,
@ -247,7 +247,8 @@ export async function createSendElements(messageData: OB11MessageData[], group:
if (sendMsg.type === OB11MessageDataType.file) { if (sendMsg.type === OB11MessageDataType.file) {
logDebug('发送文件', path, payloadFileName || fileName); logDebug('发送文件', path, payloadFileName || fileName);
sendElements.push(await SendMsgElementConstructor.file(path, payloadFileName || fileName)); sendElements.push(await SendMsgElementConstructor.file(path, payloadFileName || fileName));
} else if (sendMsg.type === OB11MessageDataType.video) { }
else if (sendMsg.type === OB11MessageDataType.video) {
logDebug('发送视频', path, payloadFileName || fileName); logDebug('发送视频', path, payloadFileName || fileName);
let thumb = sendMsg.data?.thumb; let thumb = sendMsg.data?.thumb;
if (thumb) { if (thumb) {
@ -257,9 +258,11 @@ export async function createSendElements(messageData: OB11MessageData[], group:
} }
} }
sendElements.push(await SendMsgElementConstructor.video(path, payloadFileName || fileName, thumb)); sendElements.push(await SendMsgElementConstructor.video(path, payloadFileName || fileName, thumb));
} else if (sendMsg.type === OB11MessageDataType.voice) { }
else if (sendMsg.type === OB11MessageDataType.voice) {
sendElements.push(await SendMsgElementConstructor.ptt(path)); sendElements.push(await SendMsgElementConstructor.ptt(path));
} else if (sendMsg.type === OB11MessageDataType.image) { }
else if (sendMsg.type === OB11MessageDataType.image) {
sendElements.push(await SendMsgElementConstructor.pic(path, sendMsg.data.summary || '', <PicSubType>parseInt(sendMsg.data?.subType?.toString() || '0'))); sendElements.push(await SendMsgElementConstructor.pic(path, sendMsg.data.summary || '', <PicSubType>parseInt(sendMsg.data?.subType?.toString() || '0')));
} }
} }
@ -283,43 +286,38 @@ export async function createSendElements(messageData: OB11MessageData[], group:
case OB11MessageDataType.markdown: { case OB11MessageDataType.markdown: {
const content = sendMsg.data?.content; const content = sendMsg.data?.content;
sendElements.push(SendMsgElementConstructor.markdown(content)); sendElements.push(SendMsgElementConstructor.markdown(content));
}break; }
case OB11MessageDataType.music:{ break;
case OB11MessageDataType.music: {
const musicData = sendMsg.data; const musicData = sendMsg.data;
try { if (musicData.type === 'custom') {
let musicMsgElement: SendArkElement | undefined; if (!musicData.url) {
if (musicData.type === 'custom'){ logError('自定义音卡缺少参数url');
if (!musicData.url){ break;
logError('自定义音卡缺少参数url');
break;
}
if (!musicData.audio){
logError('自定义音卡缺少参数audio');
break;
}
if (!musicData.title){
logError('自定义音卡缺少参数title');
break;
}
musicMsgElement = await genCustomMusicElement(musicData.url, musicData.audio, musicData.title, musicData.image, musicData.singer);
} }
else{ if (!musicData.audio) {
if (!['qq', '163'].includes(musicData.type)){ logError('自定义音卡缺少参数audio');
logError('音乐卡片type错误, 只支持qq和163当前type:', musicData.type); break;
break;
}
if (!musicData.id){
logError('音乐卡片缺少参数id');
break;
}
musicMsgElement = await genIdMusicElement(musicData.type, musicData.id);
} }
logDebug('生成音乐消息', musicMsgElement); if (!musicData.title) {
if (musicMsgElement) { logError('自定义音卡缺少参数title');
sendElements.push(musicMsgElement); break;
} }
} catch (e) { }
logError('生成音乐消息失败', e); else {
if (!['qq', '163'].includes(musicData.type)) {
logError('音乐卡片type错误, 只支持qq、163、custom当前type:', musicData.type);
break;
}
if (!musicData.id) {
logError('音乐卡片缺少参数id');
break;
}
}
const musicMsgElement = await genMusicElement(sendMsg.data);
logDebug('生成音乐消息', musicMsgElement);
if (musicMsgElement) {
sendElements.push(musicMsgElement);
} }
} }
} }
@ -412,7 +410,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (friend) { if (friend) {
// peer.name = friend.nickName // peer.name = friend.nickName
peer.peerUid = friend.uid; peer.peerUid = friend.uid;
} else { }
else {
peer.chatType = ChatType.temp; peer.chatType = ChatType.temp;
const tempUserUid = getUidByUin(payload.user_id.toString()); const tempUserUid = getUidByUin(payload.user_id.toString());
if (!tempUserUid) { if (!tempUserUid) {
@ -426,11 +425,14 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (payload?.group_id && payload.message_type === 'group') { if (payload?.group_id && payload.message_type === 'group') {
await genGroupPeer(); await genGroupPeer();
} else if (payload?.user_id) { }
else if (payload?.user_id) {
await genFriendPeer(); await genFriendPeer();
} else if (payload.group_id) { }
else if (payload.group_id) {
await genGroupPeer(); await genGroupPeer();
} else { }
else {
throw ('发送消息参数错误, 请指定group_id或user_id'); throw ('发送消息参数错误, 请指定group_id或user_id');
} }
const messages = convertMessage2List(payload.message, payload.auto_escape === true || payload.auto_escape === 'true'); const messages = convertMessage2List(payload.message, payload.auto_escape === true || payload.auto_escape === 'true');
@ -440,25 +442,19 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (returnMsg) { if (returnMsg) {
const msgShortId = await dbUtil.addMsg(returnMsg!, false); const msgShortId = await dbUtil.addMsg(returnMsg!, false);
return { message_id: msgShortId }; return { message_id: msgShortId };
} else { }
else {
throw Error('发送转发消息失败'); throw Error('发送转发消息失败');
} }
} catch (e: any) { } catch (e: any) {
throw Error('发送转发消息失败 ' + e.toString()); throw Error('发送转发消息失败 ' + e.toString());
} }
} else { }
else {
if (this.getSpecialMsgNum(payload, OB11MessageDataType.music)) { if (this.getSpecialMsgNum(payload, OB11MessageDataType.music)) {
const music: OB11MessageCustomMusic = messages[0] as OB11MessageCustomMusic; const music: OB11MessageCustomMusic = messages[0] as OB11MessageCustomMusic;
if (music) { // 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}
}
} }
} }
// log("send msg:", peer, sendElements) // log("send msg:", peer, sendElements)
@ -525,7 +521,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
const nodeMsg = await dbUtil.getMsgByShortId(parseInt(nodeId)); const nodeMsg = await dbUtil.getMsgByShortId(parseInt(nodeId));
if (!needClone) { if (!needClone) {
nodeMsgIds.push(nodeMsg!.msgId); nodeMsgIds.push(nodeMsg!.msgId);
} else { }
else {
if (nodeMsg!.peerUid !== selfInfo.uid) { if (nodeMsg!.peerUid !== selfInfo.uid) {
const cloneMsg = await this.cloneMsg(nodeMsg!); const cloneMsg = await this.cloneMsg(nodeMsg!);
if (cloneMsg) { if (cloneMsg) {
@ -533,7 +530,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} }
} }
} }
} else { }
else {
// 自定义的消息 // 自定义的消息
// 提取消息段发给自己生成消息id // 提取消息段发给自己生成消息id
try { try {
@ -555,7 +553,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} }
sendElementsSplit[splitIndex] = [ele]; sendElementsSplit[splitIndex] = [ele];
splitIndex++; splitIndex++;
} else { }
else {
sendElementsSplit[splitIndex].push(ele); sendElementsSplit[splitIndex].push(ele);
} }
logDebug(sendElementsSplit); logDebug(sendElementsSplit);
@ -586,7 +585,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
nodeMsgArray.push(nodeMsg); nodeMsgArray.push(nodeMsg);
if (!srcPeer) { if (!srcPeer) {
srcPeer = { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid }; srcPeer = { chatType: nodeMsg.chatType, peerUid: nodeMsg.peerUid };
} else if (srcPeer.peerUid !== nodeMsg.peerUid) { }
else if (srcPeer.peerUid !== nodeMsg.peerUid) {
needSendSelf = true; needSendSelf = true;
srcPeer = selfPeer; srcPeer = selfPeer;
} }
@ -628,7 +628,6 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} }
} }
export default SendMsg; export default SendMsg;

View File

@ -17,7 +17,7 @@ import {
GrayTipElementSubType, GrayTipElementSubType,
Group, Group,
GroupMember, GroupMember,
IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, IMAGE_HTTP_HOST, IMAGE_HTTP_HOST_NT, mFaceCache,
RawMessage, RawMessage,
SelfInfo, SelfInfo,
Sex, Sex,
@ -232,7 +232,7 @@ export class OB11Constructor {
} }
else if (element.marketFaceElement) { else if (element.marketFaceElement) {
message_data['type'] = OB11MessageDataType.mface; message_data['type'] = OB11MessageDataType.mface;
message_data['data']['text'] = element.marketFaceElement.faceName; message_data['data']['summary'] = element.marketFaceElement.faceName;
const md5 = element.marketFaceElement.emojiId; const md5 = element.marketFaceElement.emojiId;
// 取md5的前两位 // 取md5的前两位
const dir = md5.substring(0, 2); const dir = md5.substring(0, 2);
@ -240,6 +240,10 @@ export class OB11Constructor {
// const url = `https://p.qpic.cn/CDN_STATIC/0/data/imgcache/htdocs/club/item/parcel/item/${dir}/${md5}/300x300.gif?max_age=31536000`; // const url = `https://p.qpic.cn/CDN_STATIC/0/data/imgcache/htdocs/club/item/parcel/item/${dir}/${md5}/300x300.gif?max_age=31536000`;
const url = `https://gxh.vip.qq.com/club/item/parcel/item/${dir}/${md5}/raw300.gif`; const url = `https://gxh.vip.qq.com/club/item/parcel/item/${dir}/${md5}/raw300.gif`;
message_data['data']['url'] = url; message_data['data']['url'] = url;
message_data['data']['emoji_id'] = element.marketFaceElement.emojiId;
message_data['data']['emoji_package_id'] = String(element.marketFaceElement.emojiPackageId);
message_data['data']['key'] = element.marketFaceElement.key;
mFaceCache.set(md5, element.marketFaceElement.faceName);
} }
else if (element.markdownElement) { else if (element.markdownElement) {
message_data['type'] = OB11MessageDataType.markdown; message_data['type'] = OB11MessageDataType.markdown;

View File

@ -1,5 +1,6 @@
import { PicSubType, RawMessage } from '@/core'; import { PicSubType, RawMessage } from '@/core';
import { EventType } from './event/OB11BaseEvent'; import { EventType } from './event/OB11BaseEvent';
import { CustomMusicSignPostData, IdMusicSignPostData } from '@/core/apis/sign';
export interface OB11User { export interface OB11User {
user_id: number; user_id: number;
@ -124,10 +125,12 @@ export enum OB11MessageDataType {
} }
export interface OB11MessageMFace { export interface OB11MessageMFace {
type: OB11MessageDataType.mface, type: OB11MessageDataType.mface
data: { data: {
text: string, emoji_package_id: number
url: string emoji_id: string
key: string
summary: string
} }
} }
@ -203,22 +206,11 @@ export interface OB11MessageNode {
export interface OB11MessageIdMusic { export interface OB11MessageIdMusic {
type: OB11MessageDataType.music type: OB11MessageDataType.music
data: { data: IdMusicSignPostData
type: 'qq' | '163',
id: string | number,
}
} }
export interface OB11MessageCustomMusic { export interface OB11MessageCustomMusic {
type: OB11MessageDataType.music type: OB11MessageDataType.music
data: { data: CustomMusicSignPostData
type: 'custom'
url: string,
audio: string,
title: string,
content?: string,
image?: string,
singer?: string,
}
} }
export interface OB11MessageJson { export interface OB11MessageJson {