mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
276 lines
11 KiB
TypeScript
276 lines
11 KiB
TypeScript
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/entities';
|
||
import { InstanceContext, NapCatCore } from '@/core';
|
||
import { GeneralCallResult } from '@/core/services/common';
|
||
|
||
export class NTQQMsgApi {
|
||
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
||
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
|
||
// 其实以官方文档为准是最好的,https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType
|
||
|
||
context: InstanceContext;
|
||
core: NapCatCore;
|
||
|
||
constructor(context: InstanceContext, core: NapCatCore) {
|
||
this.context = context;
|
||
this.core = core;
|
||
}
|
||
|
||
async getAioFirstViewLatestMsgs(peer: Peer, MsgCount: number) {
|
||
return this.context.session.getMsgService().getAioFirstViewLatestMsgs(peer, MsgCount);
|
||
}
|
||
|
||
async getLatestDbMsgs(peer: Peer, MsgCount: number) {
|
||
return this.context.session.getMsgService().getLatestDbMsgs(peer, MsgCount);
|
||
}
|
||
|
||
async FetchLongMsg(peer: Peer, msgId: string) {
|
||
return this.context.session.getMsgService().fetchLongMsg(peer, msgId);
|
||
}
|
||
|
||
async sendShowInputStatusReq(peer: Peer, eventType: number) {
|
||
return this.context.session.getMsgService().sendShowInputStatusReq(peer.chatType, eventType, peer.peerUid);
|
||
}
|
||
|
||
async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
|
||
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
|
||
return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, count);
|
||
}
|
||
|
||
async setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set: boolean = true) {
|
||
// nt_qq//global//nt_data//Emoji//emoji-resource//sysface_res/apng/ 下可以看到所有QQ表情预览
|
||
// nt_qq\global\nt_data\Emoji\emoji-resource\face_config.json 里面有所有表情的id, 自带表情id是QSid, 标准emoji表情id是QCid
|
||
// 其实以官方文档为准是最好的,https://bot.q.qq.com/wiki/develop/api-v2/openapi/emoji/model.html#EmojiType
|
||
emojiId = emojiId.toString();
|
||
return this.context.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set);
|
||
}
|
||
|
||
async getMultiMsg(peer: Peer, rootMsgId: string, parentMsgId: string): Promise<GeneralCallResult & {
|
||
msgList: RawMessage[]
|
||
} | undefined> {
|
||
return this.context.session.getMsgService().getMultiMsg(peer, rootMsgId, parentMsgId);
|
||
}
|
||
|
||
async ForwardMsg(peer: Peer, msgIds: string[]) {
|
||
return this.context.session.getMsgService().forwardMsg(msgIds, peer, [peer], new Map());
|
||
}
|
||
|
||
async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
|
||
if (!peer) throw new Error('peer is not allowed');
|
||
if (!msgIds) throw new Error('msgIds is not allowed');
|
||
//MliKiowa: 参数不合规会导致NC异常崩溃 原因是TX未对进入参数判断 对应Android标记@NotNull AndroidJADX分析可得
|
||
return await this.context.session.getMsgService().getMsgsByMsgId(peer, msgIds);
|
||
}
|
||
|
||
async getSingleMsg(peer: Peer, seq: string) {
|
||
return await this.context.session.getMsgService().getSingleMsg(peer, seq);
|
||
}
|
||
|
||
async fetchFavEmojiList(num: number) {
|
||
return this.context.session.getMsgService().fetchFavEmojiList('', num, true, true);
|
||
}
|
||
|
||
async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
|
||
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||
chatInfo: peer,
|
||
filterMsgType: [],
|
||
filterSendersUid: [],
|
||
filterMsgToTime: '0',
|
||
filterMsgFromTime: '0',
|
||
isReverseOrder: false,
|
||
isIncludeCurrent: true,
|
||
pageLimit: 1,
|
||
});
|
||
}
|
||
async queryMsgsWithFilterExWithSeqV2(peer: Peer, msgSeq: string, MsgTime: string, SendersUid: string[]) {
|
||
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||
chatInfo: peer,
|
||
filterMsgType: [],
|
||
filterSendersUid: SendersUid,
|
||
filterMsgToTime: MsgTime,
|
||
filterMsgFromTime: MsgTime,
|
||
isReverseOrder: false,
|
||
isIncludeCurrent: true,
|
||
pageLimit: 1,
|
||
});
|
||
}
|
||
async queryFirstMsgBySeq(peer: Peer, msgSeq: string) {
|
||
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||
chatInfo: peer,
|
||
filterMsgType: [],
|
||
filterSendersUid: [],
|
||
filterMsgToTime: '0',
|
||
filterMsgFromTime: '0',
|
||
isReverseOrder: true,
|
||
isIncludeCurrent: true,
|
||
pageLimit: 1,
|
||
});
|
||
}
|
||
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
|
||
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
|
||
}
|
||
async getMsgBySeqList(peer: Peer, msgSeqList: string[]) {
|
||
//坏的
|
||
return await this.context.session.getMsgService().getMsgsBySeqList(peer, msgSeqList);
|
||
}
|
||
async getMsgBySeqExFirstMsg(peer: Peer, rootMsgId: string, replyMsgId: string) {
|
||
let reply = await this.context.session.getMsgService().getSourceOfReplyMsgV2(peer, rootMsgId, replyMsgId);
|
||
console.log(reply);
|
||
}
|
||
async getMsgExBySeq(peer: Peer, msgSeq: string) {
|
||
const DateNow = Math.floor(Date.now() / 1000);
|
||
const filterMsgFromTime = (DateNow - 300).toString();
|
||
const filterMsgToTime = DateNow.toString();
|
||
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
|
||
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
|
||
filterMsgType: [],
|
||
filterSendersUid: [],
|
||
filterMsgToTime: filterMsgToTime,
|
||
filterMsgFromTime: filterMsgFromTime,
|
||
isReverseOrder: false,
|
||
isIncludeCurrent: true,
|
||
pageLimit: 100,
|
||
});
|
||
}
|
||
|
||
async setMsgRead(peer: Peer) {
|
||
return this.context.session.getMsgService().setMsgRead(peer);
|
||
}
|
||
|
||
async getGroupFileList(GroupCode: string, params: GetFileListParam) {
|
||
const [, groupFileListResult] = await this.core.eventWrapper.callNormalEventV2(
|
||
'NodeIKernelRichMediaService/getGroupFileList',
|
||
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
|
||
[
|
||
GroupCode,
|
||
params,
|
||
],
|
||
() => true,
|
||
() => true, // Todo: 应当通过 groupFileListResult 判断
|
||
1,
|
||
5000,
|
||
);
|
||
return groupFileListResult.item;
|
||
}
|
||
|
||
async getMsgHistory(peer: Peer, msgId: string, count: number, isReverseOrder: boolean = false) {
|
||
// 消息时间从旧到新
|
||
return this.context.session.getMsgService().getMsgsIncludeSelf(peer, msgId, count, isReverseOrder);
|
||
}
|
||
|
||
async recallMsg(peer: Peer, msgIds: string[]) {
|
||
await this.context.session.getMsgService().recallMsg({
|
||
chatType: peer.chatType,
|
||
peerUid: peer.peerUid,
|
||
}, msgIds);
|
||
}
|
||
|
||
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
|
||
return this.context.session.getMsgService().prepareTempChat({
|
||
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,
|
||
peerUid: toUserUid,
|
||
peerNickname: nickname,
|
||
fromGroupCode: GroupCode,
|
||
sig: '',
|
||
selfPhone: '',
|
||
selfUid: this.core.selfInfo.uid,
|
||
gameSession: {
|
||
nickname: '',
|
||
gameAppId: '',
|
||
selfTinyId: '',
|
||
peerRoleId: '',
|
||
peerOpenId: '',
|
||
},
|
||
});
|
||
}
|
||
|
||
async getTempChatInfo(chatType: ChatType, peerUid: string) {
|
||
return this.context.session.getMsgService().getTempChatInfo(chatType, peerUid);
|
||
}
|
||
|
||
async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
|
||
//唉?!我有个想法
|
||
if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') {
|
||
const member = await this.core.apis.GroupApi.getGroupMember(peer.guildId, peer.peerUid!);
|
||
if (member) {
|
||
await this.PrepareTempChat(peer.peerUid, peer.guildId, member.nick);
|
||
}
|
||
}
|
||
const msgId = await this.generateMsgUniqueId(peer.chatType, await this.getServerTime());
|
||
peer.guildId = msgId;
|
||
const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
|
||
'NodeIKernelMsgService/sendMsg',
|
||
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
||
[
|
||
'0',
|
||
peer,
|
||
msgElements,
|
||
new Map(),
|
||
],
|
||
(ret) => ret.result === 0,
|
||
msgRecords => {
|
||
for (const msgRecord of msgRecords) {
|
||
if (msgRecord.guildId === msgId && msgRecord.sendStatus === SendStatusType.KSEND_STATUS_SUCCESS) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
},
|
||
1,
|
||
timeout,
|
||
);
|
||
return msgList.find(msgRecord => msgRecord.guildId === msgId);
|
||
}
|
||
|
||
async generateMsgUniqueId(chatType: number, time: string) {
|
||
return this.context.session.getMsgService().generateMsgUniqueId(chatType, time);
|
||
}
|
||
|
||
async getServerTime() {
|
||
return this.context.session.getMSFService().getServerTime();
|
||
}
|
||
|
||
async forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]) {
|
||
return this.context.session.getMsgService().forwardMsg(msgIds, srcPeer, [destPeer], new Map());
|
||
}
|
||
|
||
async multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<RawMessage> {
|
||
const msgInfos = msgIds.map(id => {
|
||
return { msgId: id, senderShowName: this.core.selfInfo.nick };
|
||
});
|
||
const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
|
||
'NodeIKernelMsgService/multiForwardMsgWithComment',
|
||
'NodeIKernelMsgListener/onMsgInfoListUpdate',
|
||
[
|
||
msgInfos,
|
||
srcPeer,
|
||
destPeer,
|
||
[],
|
||
new Map(),
|
||
],
|
||
() => true,
|
||
(msgRecords) => msgRecords.some(
|
||
msgRecord => msgRecord.peerUid === destPeer.peerUid
|
||
&& msgRecord.senderUid === this.core.selfInfo.uid
|
||
),
|
||
);
|
||
for (const msg of msgList) {
|
||
const arkElement = msg.elements.find(ele => ele.arkElement);
|
||
if (!arkElement) {
|
||
continue;
|
||
}
|
||
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData ?? '');
|
||
if (forwardData.app != 'com.tencent.multimsg') {
|
||
continue;
|
||
}
|
||
if (msg.peerUid == destPeer.peerUid && msg.senderUid == this.core.selfInfo.uid) {
|
||
return msg;
|
||
}
|
||
}
|
||
throw new Error('转发消息超时');
|
||
}
|
||
|
||
async markAllMsgAsRead() {
|
||
return this.context.session.getMsgService().setAllC2CAndGroupMsgRead();
|
||
}
|
||
}
|