mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b1ecf13f8e | ||
![]() |
e91e054f20 | ||
![]() |
130ff7517e | ||
![]() |
c7042d9684 | ||
![]() |
5752e45dd1 | ||
![]() |
1a034ecb53 | ||
![]() |
025da8fb76 | ||
![]() |
2027da1db5 | ||
![]() |
7732f28ca8 | ||
![]() |
7f9da8cc2d | ||
![]() |
c6342b80a7 | ||
![]() |
f99c82de4b | ||
![]() |
56fa57ea02 | ||
![]() |
cc85985d08 | ||
![]() |
bd1751903e | ||
![]() |
03a298a70f | ||
![]() |
2722ca2b0e | ||
![]() |
179c4b800e | ||
![]() |
6bdf14223d | ||
![]() |
1b8252aa4f | ||
![]() |
8219889154 |
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.2.19",
|
"version": "2.2.22",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.2.19",
|
"version": "2.2.22",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:framework": "vite build --mode framework",
|
"build:framework": "vite build --mode framework",
|
||||||
"build:shell": "vite build --mode shell",
|
"build:shell": "vite build --mode shell",
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
"@types/node": "^22.0.1",
|
"@types/node": "^22.0.1",
|
||||||
"@types/qrcode-terminal": "^0.12.2",
|
"@types/qrcode-terminal": "^0.12.2",
|
||||||
"@types/ws": "^8.5.12",
|
"@types/ws": "^8.5.12",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
"@typescript-eslint/eslint-plugin": "^8.3.0",
|
||||||
"@typescript-eslint/parser": "^7.4.0",
|
"@typescript-eslint/parser": "^8.3.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.1",
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import { QQLevel } from '@/core';
|
import { Peer, QQLevel } from '@/core';
|
||||||
|
|
||||||
export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ...args: Parameters<T>): Promise<ReturnType<T> | undefined> {
|
export async function solveProblem<T extends (...arg: any[]) => any>(func: T, ...args: Parameters<T>): Promise<ReturnType<T> | undefined> {
|
||||||
return new Promise<ReturnType<T> | undefined>((resolve) => {
|
return new Promise<ReturnType<T> | undefined>((resolve) => {
|
||||||
@@ -23,29 +23,48 @@ export async function solveAsyncProblem<T extends (...args: any[]) => Promise<an
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
export class FileNapCatOneBotUUID {
|
||||||
//下面这个类是用于将uid+msgid合并的类
|
static encodeModelId(peer: Peer, modelId: string): string {
|
||||||
export class UUIDConverter {
|
return `NapCatOneBot-ModeldFile-${peer.chatType}-${peer.peerUid}-${modelId}`;
|
||||||
static encode(highStr: string, lowStr: string): string {
|
|
||||||
const high = BigInt(highStr);
|
|
||||||
const low = BigInt(lowStr);
|
|
||||||
const highHex = high.toString(16).padStart(16, '0');
|
|
||||||
const lowHex = low.toString(16).padStart(16, '0');
|
|
||||||
const combinedHex = highHex + lowHex;
|
|
||||||
return `${combinedHex.substring(0, 8)}-${combinedHex.substring(8, 12)}-${combinedHex.substring(
|
|
||||||
12,
|
|
||||||
16,
|
|
||||||
)}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`;
|
|
||||||
}
|
}
|
||||||
|
static decodeModelId(uuid: string): undefined | {
|
||||||
static decode(uuid: string): { high: string; low: string } {
|
peer: Peer,
|
||||||
const hex = uuid.replace(/-/g, '');
|
modelId: string
|
||||||
const high = BigInt('0x' + hex.substring(0, 16));
|
} {
|
||||||
const low = BigInt('0x' + hex.substring(16));
|
if (!uuid.startsWith('NapCatOneBot-ModeldFile-')) return undefined;
|
||||||
return { high: high.toString(), low: low.toString() };
|
const data = uuid.split('-');
|
||||||
|
if (data.length !== 5) return undefined;
|
||||||
|
const [, , chatType, peerUid, modelId] = data;
|
||||||
|
return {
|
||||||
|
peer: {
|
||||||
|
chatType: chatType as any,
|
||||||
|
peerUid: peerUid
|
||||||
|
},
|
||||||
|
modelId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static encode(peer: Peer, msgId: string, elementId: string): string {
|
||||||
|
return `NapCatOneBot-MsgFile-${peer.chatType}-${peer.peerUid}-${msgId}-${elementId}`;
|
||||||
|
}
|
||||||
|
static decode(uuid: string): undefined | {
|
||||||
|
peer: Peer,
|
||||||
|
msgId: string,
|
||||||
|
elementId: string
|
||||||
|
} {
|
||||||
|
if (!uuid.startsWith('NapCatOneBot-File-')) return undefined;
|
||||||
|
const data = uuid.split('-');
|
||||||
|
if (data.length !== 6) return undefined;
|
||||||
|
const [, , chatType, peerUid, msgId, elementId] = data;
|
||||||
|
return {
|
||||||
|
peer: {
|
||||||
|
chatType: chatType as any,
|
||||||
|
peerUid: peerUid
|
||||||
|
},
|
||||||
|
msgId,
|
||||||
|
elementId,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sleep(ms: number): Promise<void> {
|
export function sleep(ms: number): Promise<void> {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
@@ -91,7 +91,7 @@ class MessageUniqueWrapper {
|
|||||||
return ret.map((t) => t?.MsgId).filter((t) => t !== undefined);
|
return ret.map((t) => t?.MsgId).filter((t) => t !== undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
createMsg(peer: Peer, msgId: string) {
|
createUniqueMsgId(peer: Peer, msgId: string) {
|
||||||
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
||||||
const hash = crypto.createHash('md5').update(key).digest();
|
const hash = crypto.createHash('md5').update(key).digest();
|
||||||
//设置第一个bit为0 保证shortId为正数
|
//设置第一个bit为0 保证shortId为正数
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '2.2.19';
|
export const napCatVersion = '2.2.22';
|
||||||
|
@@ -302,7 +302,18 @@ export class NTQQFileApi {
|
|||||||
async downloadMediaByUuid() {
|
async downloadMediaByUuid() {
|
||||||
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
|
||||||
}
|
}
|
||||||
|
async downloadFileForModelId(peer: Peer, modelId: string, timeout = 1000 * 60 * 2) {
|
||||||
|
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
|
||||||
|
'NodeIKernelRichMediaService/downloadFileForModelId',
|
||||||
|
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
|
||||||
|
[peer, [modelId]],
|
||||||
|
() => true,
|
||||||
|
(arg) => arg?.commonFileInfo?.fileModelId === modelId,
|
||||||
|
1,
|
||||||
|
timeout,
|
||||||
|
);
|
||||||
|
return fileTransNotifyInfo.filePath;
|
||||||
|
}
|
||||||
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
async downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout = 1000 * 60 * 2, force: boolean = false) {
|
||||||
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
//logDebug('receive downloadMedia task', msgId, chatType, peerUid, elementId, thumbPath, sourcePath, timeout, force);
|
||||||
// 用于下载收到的消息中的图片等
|
// 用于下载收到的消息中的图片等
|
||||||
|
@@ -2,6 +2,7 @@ import {
|
|||||||
ChatType,
|
ChatType,
|
||||||
GeneralCallResult,
|
GeneralCallResult,
|
||||||
Group,
|
Group,
|
||||||
|
GroupInfoSource,
|
||||||
GroupMember,
|
GroupMember,
|
||||||
GroupMemberRole,
|
GroupMemberRole,
|
||||||
GroupRequestOperateTypes,
|
GroupRequestOperateTypes,
|
||||||
@@ -11,6 +12,7 @@ import {
|
|||||||
NapCatCore,
|
NapCatCore,
|
||||||
} from '@/core';
|
} from '@/core';
|
||||||
import { isNumeric, runAllWithTimeout } from '@/common/helper';
|
import { isNumeric, runAllWithTimeout } from '@/common/helper';
|
||||||
|
import { LimitedHashTable } from '@/common/message-unique';
|
||||||
|
|
||||||
export class NTQQGroupApi {
|
export class NTQQGroupApi {
|
||||||
context: InstanceContext;
|
context: InstanceContext;
|
||||||
@@ -18,6 +20,7 @@ export class NTQQGroupApi {
|
|||||||
groupCache: Map<string, Group> = new Map<string, Group>();
|
groupCache: Map<string, Group> = new Map<string, Group>();
|
||||||
groupMemberCache: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
groupMemberCache: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
||||||
groups: Group[] = [];
|
groups: Group[] = [];
|
||||||
|
essenceLRU = new LimitedHashTable<number, string>(1000);
|
||||||
|
|
||||||
constructor(context: InstanceContext, core: NapCatCore) {
|
constructor(context: InstanceContext, core: NapCatCore) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@@ -32,7 +35,17 @@ export class NTQQGroupApi {
|
|||||||
}
|
}
|
||||||
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
|
||||||
}
|
}
|
||||||
|
async fetchGroupEssenceList(groupCode: string) {
|
||||||
|
const pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
|
||||||
|
return this.context.session.getGroupService().fetchGroupEssenceList({
|
||||||
|
groupCode: groupCode,
|
||||||
|
pageStart: 0,
|
||||||
|
pageLimit: 300
|
||||||
|
}, pskey);
|
||||||
|
}
|
||||||
|
async clearGroupNotifiesUnreadCount(unk: boolean) {
|
||||||
|
return this.context.session.getGroupService().clearGroupNotifiesUnreadCount(unk);
|
||||||
|
}
|
||||||
async setGroupAvatar(gc: string, filePath: string) {
|
async setGroupAvatar(gc: string, filePath: string) {
|
||||||
return this.context.session.getGroupService().setHeader(gc, filePath);
|
return this.context.session.getGroupService().setHeader(gc, filePath);
|
||||||
}
|
}
|
||||||
@@ -270,7 +283,15 @@ export class NTQQGroupApi {
|
|||||||
//应该是直接返回不需要Listener的 未经测试 需测试再发布
|
//应该是直接返回不需要Listener的 未经测试 需测试再发布
|
||||||
return this.context.session.getGroupService().quitGroupV2(param);
|
return this.context.session.getGroupService().quitGroupV2(param);
|
||||||
}
|
}
|
||||||
|
async removeGroupEssenceBySeq(GroupCode: string, msgRandom: string, msgSeq: string) {
|
||||||
|
const param = {
|
||||||
|
groupCode: GroupCode,
|
||||||
|
msgRandom: parseInt(msgRandom),
|
||||||
|
msgSeq: parseInt(msgSeq),
|
||||||
|
};
|
||||||
|
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
|
||||||
|
return this.context.session.getGroupService().removeGroupEssence(param);
|
||||||
|
}
|
||||||
async removeGroupEssence(GroupCode: string, msgId: string) {
|
async removeGroupEssence(GroupCode: string, msgId: string) {
|
||||||
// 代码没测过
|
// 代码没测过
|
||||||
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
|
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
|
||||||
@@ -340,7 +361,7 @@ export class NTQQGroupApi {
|
|||||||
]);
|
]);
|
||||||
if (membersFromFunc.status === 'fulfilled' && membersFromListener.status === 'fulfilled') {
|
if (membersFromFunc.status === 'fulfilled' && membersFromListener.status === 'fulfilled') {
|
||||||
return new Map([
|
return new Map([
|
||||||
...membersFromFunc.value.result.infos,
|
...membersFromFunc.value.result.infos,
|
||||||
...membersFromListener.value[0].infos
|
...membersFromListener.value[0].infos
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -355,7 +376,7 @@ export class NTQQGroupApi {
|
|||||||
groupService.destroyMemberListScene(sceneId);
|
groupService.destroyMemberListScene(sceneId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
|
||||||
const groupService = this.context.session.getGroupService();
|
const groupService = this.context.session.getGroupService();
|
||||||
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
|
||||||
|
@@ -27,7 +27,7 @@ export class NTQQWebApi {
|
|||||||
msg_random: msgRandom,
|
msg_random: msgRandom,
|
||||||
target_group_code: targetGroupCode,
|
target_group_code: targetGroupCode,
|
||||||
}).toString()
|
}).toString()
|
||||||
}`;
|
}`;
|
||||||
try {
|
try {
|
||||||
return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -35,19 +35,17 @@ export class NTQQWebApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupEssenceMsg(GroupCode: string, page_start: string) {
|
async getGroupEssenceMsg(GroupCode: string) {
|
||||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||||
const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?${new URLSearchParams({
|
const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?${new URLSearchParams({
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
group_code: GroupCode,
|
group_code: GroupCode,
|
||||||
page_start,
|
|
||||||
page_limit: '20',
|
|
||||||
}).toString()
|
}).toString()
|
||||||
}`;
|
}`;
|
||||||
let ret;
|
let ret;
|
||||||
try {
|
try {
|
||||||
ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet>
|
ret = await RequestUtil.HttpGetJson<GroupEssenceMsgRet>
|
||||||
(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
} catch {
|
} catch {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -63,14 +61,14 @@ export class NTQQWebApi {
|
|||||||
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
|
||||||
const retList: Promise<WebApiGroupMemberRet>[] = [];
|
const retList: Promise<WebApiGroupMemberRet>[] = [];
|
||||||
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>
|
const fastRet = await RequestUtil.HttpGetJson<WebApiGroupMemberRet>
|
||||||
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
||||||
st: '0',
|
st: '0',
|
||||||
end: '40',
|
end: '40',
|
||||||
sort: '1',
|
sort: '1',
|
||||||
gc: GroupCode,
|
gc: GroupCode,
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
}).toString()
|
}).toString()
|
||||||
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) });
|
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
|
if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
} else {
|
||||||
@@ -83,14 +81,14 @@ export class NTQQWebApi {
|
|||||||
//遍历批量请求
|
//遍历批量请求
|
||||||
for (let i = 2; i <= PageNum; i++) {
|
for (let i = 2; i <= PageNum; i++) {
|
||||||
const ret = RequestUtil.HttpGetJson<WebApiGroupMemberRet>
|
const ret = RequestUtil.HttpGetJson<WebApiGroupMemberRet>
|
||||||
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
(`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${new URLSearchParams({
|
||||||
st: ((i - 1) * 40).toString(),
|
st: ((i - 1) * 40).toString(),
|
||||||
end: (i * 40).toString(),
|
end: (i * 40).toString(),
|
||||||
sort: '1',
|
sort: '1',
|
||||||
gc: GroupCode,
|
gc: GroupCode,
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
}).toString()
|
}).toString()
|
||||||
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) });
|
}`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
retList.push(ret);
|
retList.push(ret);
|
||||||
}
|
}
|
||||||
//批量等待
|
//批量等待
|
||||||
@@ -123,15 +121,15 @@ export class NTQQWebApi {
|
|||||||
let ret: any = undefined;
|
let ret: any = undefined;
|
||||||
try {
|
try {
|
||||||
ret = await RequestUtil.HttpGetJson<any>
|
ret = await RequestUtil.HttpGetJson<any>
|
||||||
(`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({
|
(`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({
|
||||||
bkn: this.getBknFromCookie(cookieObject),
|
bkn: this.getBknFromCookie(cookieObject),
|
||||||
qid: GroupCode,
|
qid: GroupCode,
|
||||||
text: Content,
|
text: Content,
|
||||||
pinned: '0',
|
pinned: '0',
|
||||||
type: '1',
|
type: '1',
|
||||||
settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}',
|
settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}',
|
||||||
}).toString()
|
}).toString()
|
||||||
}`, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
}`, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
return ret;
|
return ret;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -162,7 +160,7 @@ export class NTQQWebApi {
|
|||||||
gc: Internal_groupCode,
|
gc: Internal_groupCode,
|
||||||
type: Internal_type.toString(),
|
type: Internal_type.toString(),
|
||||||
}).toString()
|
}).toString()
|
||||||
}`;
|
}`;
|
||||||
let resJson;
|
let resJson;
|
||||||
try {
|
try {
|
||||||
const res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
const res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) });
|
||||||
|
@@ -1,5 +1,25 @@
|
|||||||
import { ChatType, RawMessage } from '@/core/entities';
|
import { ChatType, RawMessage } from '@/core/entities';
|
||||||
|
export interface CommonFileInfo {
|
||||||
|
bizType: null;
|
||||||
|
chatType: number;
|
||||||
|
elemId: string;
|
||||||
|
favId: null;
|
||||||
|
fileModelId: string;
|
||||||
|
fileName: string;
|
||||||
|
fileSize: string;
|
||||||
|
md5: string;
|
||||||
|
md510m: string;
|
||||||
|
msgId: string;
|
||||||
|
msgTime: string;
|
||||||
|
parent: null;
|
||||||
|
peerUid: string;
|
||||||
|
picThumbPath: null;
|
||||||
|
sha: string;
|
||||||
|
sha3: string;
|
||||||
|
subId: string;
|
||||||
|
uuid: string;
|
||||||
|
[property: string]: any;
|
||||||
|
}
|
||||||
export interface OnRichMediaDownloadCompleteParams {
|
export interface OnRichMediaDownloadCompleteParams {
|
||||||
fileModelId: string,
|
fileModelId: string,
|
||||||
msgElementId: string,
|
msgElementId: string,
|
||||||
@@ -15,7 +35,7 @@ export interface OnRichMediaDownloadCompleteParams {
|
|||||||
totalSize: string,
|
totalSize: string,
|
||||||
trasferStatus: number,
|
trasferStatus: number,
|
||||||
step: number,
|
step: number,
|
||||||
commonFileInfo: unknown | null,
|
commonFileInfo?: CommonFileInfo,
|
||||||
fileSrvErrCode: string,
|
fileSrvErrCode: string,
|
||||||
clientMsg: string,
|
clientMsg: string,
|
||||||
businessId: number,
|
businessId: number,
|
||||||
|
@@ -2,6 +2,7 @@ import { NodeIKernelGroupListener } from '@/core/listeners/NodeIKernelGroupListe
|
|||||||
import {
|
import {
|
||||||
GroupExt0xEF0InfoFilter,
|
GroupExt0xEF0InfoFilter,
|
||||||
GroupExtParam,
|
GroupExtParam,
|
||||||
|
GroupInfoSource,
|
||||||
GroupMember,
|
GroupMember,
|
||||||
GroupMemberRole,
|
GroupMemberRole,
|
||||||
GroupNotifyMsgType,
|
GroupNotifyMsgType,
|
||||||
@@ -13,9 +14,9 @@ import { GeneralCallResult } from '@/core/services/common';
|
|||||||
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
|
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
|
||||||
|
|
||||||
export interface NodeIKernelGroupService {
|
export interface NodeIKernelGroupService {
|
||||||
//getGroupExt0xEF0Info(this.$enableGroupCodes, this.$bannedGroupCodes, this.$filter, this.$forceFetch
|
|
||||||
getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean):
|
getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean):
|
||||||
Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> }}>;
|
Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> } }>;
|
||||||
|
|
||||||
kickMemberV2(param: KickMemberV2Req): Promise<GeneralCallResult>;
|
kickMemberV2(param: KickMemberV2Req): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
quitGroupV2(param: { groupCode: string; needDeleteLocalMsg: boolean; }): Promise<GeneralCallResult>;
|
quitGroupV2(param: { groupCode: string; needDeleteLocalMsg: boolean; }): Promise<GeneralCallResult>;
|
||||||
@@ -39,11 +40,11 @@ export interface NodeIKernelGroupService {
|
|||||||
realSpecialTitleFlag: number
|
realSpecialTitleFlag: number
|
||||||
}): Promise<unknown>;
|
}): Promise<unknown>;
|
||||||
|
|
||||||
//26702
|
|
||||||
getGroupMemberLevelInfo(groupCode: string): Promise<unknown>;
|
getGroupMemberLevelInfo(groupCode: string): Promise<unknown>;
|
||||||
|
|
||||||
//26702
|
getGroupInfoForJoinGroup(groupCode: string, needPrivilegeFlag: boolean, serviceType: number): Promise<unknown>;
|
||||||
getGroupHonorList(groupCodes: Array<string>): unknown;
|
|
||||||
|
getGroupHonorList(req: { groupCodes: Array<string> }): Promise<unknown>;
|
||||||
|
|
||||||
getUinByUids(uins: string[]): Promise<{
|
getUinByUids(uins: string[]): Promise<{
|
||||||
errCode: number,
|
errCode: number,
|
||||||
@@ -57,13 +58,10 @@ export interface NodeIKernelGroupService {
|
|||||||
uids: Map<string, string>
|
uids: Map<string, string>
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
checkGroupMemberCache(arrayList: Array<string>): Promise<unknown>;
|
checkGroupMemberCache(arrayList: Array<string>): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
getGroupLatestEssenceList(groupCode: string): Promise<unknown>;
|
getGroupLatestEssenceList(groupCode: string): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
shareDigest(Req: {
|
shareDigest(Req: {
|
||||||
appId: string,
|
appId: string,
|
||||||
appType: number,
|
appType: number,
|
||||||
@@ -83,20 +81,17 @@ export interface NodeIKernelGroupService {
|
|||||||
}
|
}
|
||||||
}): Promise<unknown>;
|
}): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
isEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
queryCachedEssenceMsg(Req: { groupCode: string, msgRandom: number, msgSeq: number }): Promise<unknown>;
|
||||||
|
|
||||||
//26702(其实更早 但是我不知道)
|
|
||||||
fetchGroupEssenceList(Req: {
|
fetchGroupEssenceList(Req: {
|
||||||
groupCode: string,
|
groupCode: string,
|
||||||
pageStart: number,
|
pageStart: number,
|
||||||
pageLimit: number
|
pageLimit: number
|
||||||
}, Arg: unknown): Promise<unknown>;
|
}, Arg: unknown): Promise<unknown>;
|
||||||
|
|
||||||
//26702
|
|
||||||
getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{
|
getAllMemberList(groupCode: string, forceFetch: boolean): Promise<{
|
||||||
errCode: number,
|
errCode: number,
|
||||||
errMsg: string,
|
errMsg: string,
|
||||||
@@ -135,8 +130,6 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getMemberInfo(group_id: string, uids: string[], forceFetch: boolean): Promise<GeneralCallResult>;
|
getMemberInfo(group_id: string, uids: string[], forceFetch: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
//getMemberInfo [ '56729xxxx', [ 'u_4Nj08cwW5Hxxxxx' ], true ]
|
|
||||||
|
|
||||||
kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise<void>;
|
kickMember(groupCode: string, memberUids: string[], refuseForever: boolean, kickReason: string): Promise<void>;
|
||||||
|
|
||||||
modifyMemberRole(groupCode: string, uid: string, role: GroupMemberRole): void;
|
modifyMemberRole(groupCode: string, uid: string, role: GroupMemberRole): void;
|
||||||
@@ -151,7 +144,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getGroupExtList(force: boolean): Promise<GeneralCallResult>;
|
getGroupExtList(force: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
getGroupDetailInfo(groupCode: string): unknown;
|
getGroupDetailInfo(groupCode: string, groupInfoSource: GroupInfoSource): Promise<unknown>;
|
||||||
|
|
||||||
getMemberExtInfo(param: GroupExtParam): Promise<unknown>;//req
|
getMemberExtInfo(param: GroupExtParam): Promise<unknown>;//req
|
||||||
|
|
||||||
@@ -196,7 +189,7 @@ export interface NodeIKernelGroupService {
|
|||||||
|
|
||||||
getGroupNotifiesUnreadCount(unknown: boolean): Promise<GeneralCallResult>;
|
getGroupNotifiesUnreadCount(unknown: boolean): Promise<GeneralCallResult>;
|
||||||
|
|
||||||
clearGroupNotifiesUnreadCount(groupCode: string): void;
|
clearGroupNotifiesUnreadCount(unknown: boolean): void;
|
||||||
|
|
||||||
operateSysNotify(
|
operateSysNotify(
|
||||||
doubt: boolean,
|
doubt: boolean,
|
||||||
|
@@ -155,7 +155,7 @@ export interface NodeIKernelRichMediaService {
|
|||||||
}): unknown;
|
}): unknown;
|
||||||
|
|
||||||
//arg3为“”
|
//arg3为“”
|
||||||
downloadFileForModelId(peer: Peer, ModelId: string[], arg3: string): unknown;
|
downloadFileForModelId(peer: Peer, ModelId: string[]): Promise<unknown>;
|
||||||
|
|
||||||
//第三个参数 Array<Type>
|
//第三个参数 Array<Type>
|
||||||
// this.fileId = "";
|
// this.fileId = "";
|
||||||
|
24
src/onebot/action/extends/GetGroupInfoEx.ts
Normal file
24
src/onebot/action/extends/GetGroupInfoEx.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import BaseAction from '../BaseAction';
|
||||||
|
import { ActionName } from '../types';
|
||||||
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
|
const SchemaData = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
group_id: { type: ['number', 'string'] },
|
||||||
|
},
|
||||||
|
required: ['group_id'],
|
||||||
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
|
export class GetGroupInfoEx extends BaseAction<Payload, any> {
|
||||||
|
actionName = ActionName.GetGroupInfoEx;
|
||||||
|
payloadSchema = SchemaData;
|
||||||
|
|
||||||
|
async _handle(payload: Payload) {
|
||||||
|
const NTQQGroupApi = this.core.apis.GroupApi;
|
||||||
|
const groupInfoEx = (await NTQQGroupApi.getGroupExtFE0Info([payload.group_id.toString()])).result.groupExtInfos.get(payload.group_id.toString());
|
||||||
|
return groupInfoEx;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { UUIDConverter } from '@/common/helper';
|
import { FileNapCatOneBotUUID } from '@/common/helper';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { ChatType, ElementType, Peer, RawMessage } from '@/core/entities';
|
import { ChatType, Peer, RawMessage } from '@/core/entities';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
|
||||||
export interface GetFilePayload {
|
export interface GetFilePayload {
|
||||||
@@ -29,64 +29,64 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
payloadSchema: any = GetFileBase_PayloadSchema;
|
payloadSchema: any = GetFileBase_PayloadSchema;
|
||||||
|
|
||||||
async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
|
||||||
const NTQQFriendApi = this.core.apis.FriendApi;
|
|
||||||
const NTQQUserApi = this.core.apis.UserApi;
|
|
||||||
const NTQQMsgApi = this.core.apis.MsgApi;
|
const NTQQMsgApi = this.core.apis.MsgApi;
|
||||||
const NTQQGroupApi = this.core.apis.GroupApi;
|
|
||||||
const NTQQFileApi = this.core.apis.FileApi;
|
const NTQQFileApi = this.core.apis.FileApi;
|
||||||
try {
|
|
||||||
const uuidData = UUIDConverter.decode(payload.file);
|
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
|
||||||
const peerUin = uuidData.high;
|
|
||||||
const msgId = uuidData.low;
|
//接收消息标记模式
|
||||||
const isGroup: boolean = !!(await NTQQGroupApi.getGroups(false)).find(e => e.groupCode == peerUin);
|
if (contextMsgFile) {
|
||||||
let peer: Peer | undefined;
|
const { peer, msgId, elementId } = contextMsgFile;
|
||||||
//识别Peer
|
|
||||||
if (isGroup) {
|
const downloadPath = await NTQQFileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', '');
|
||||||
peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: peerUin };
|
|
||||||
}
|
const mixElement = (await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]))?.msgList
|
||||||
const PeerUid = await NTQQUserApi.getUidByUinV2(peerUin);
|
.find(msg => msg.msgId === msgId)?.elements.find(e => e.elementId === elementId);
|
||||||
if (PeerUid) {
|
const mixElementInner = mixElement?.videoElement ?? mixElement?.fileElement ?? mixElement?.pttElement ?? mixElement?.picElement;
|
||||||
const isBuddy = await NTQQFriendApi.isBuddy(PeerUid);
|
if (!mixElementInner) throw new Error('element not found');
|
||||||
if (isBuddy) {
|
|
||||||
peer = { chatType: ChatType.KCHATTYPEC2C, peerUid: PeerUid };
|
const fileSize = mixElementInner.fileSize?.toString() || '';
|
||||||
} else {
|
const fileName = mixElementInner.fileName || '';
|
||||||
peer = { chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid: PeerUid };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!peer) {
|
|
||||||
throw new Error('chattype not support');
|
|
||||||
}
|
|
||||||
const msgList = await NTQQMsgApi.getMsgsByMsgId(peer, [msgId]);
|
|
||||||
if (msgList.msgList.length == 0) {
|
|
||||||
throw new Error('msg not found');
|
|
||||||
}
|
|
||||||
const msg = msgList.msgList[0];
|
|
||||||
const findEle = msg.elements.find(e => e.elementType == ElementType.VIDEO || e.elementType == ElementType.FILE || e.elementType == ElementType.PTT);
|
|
||||||
if (!findEle) {
|
|
||||||
throw new Error('element not found');
|
|
||||||
}
|
|
||||||
const downloadPath = await NTQQFileApi.downloadMedia(msgId, msg.chatType, msg.peerUid, findEle.elementId, '', '');
|
|
||||||
const fileSize = findEle?.videoElement?.fileSize || findEle?.fileElement?.fileSize || findEle?.pttElement?.fileSize || '0';
|
|
||||||
const fileName = findEle?.videoElement?.fileName || findEle?.fileElement?.fileName || findEle?.pttElement?.fileName || '';
|
|
||||||
const res: GetFileResponse = {
|
const res: GetFileResponse = {
|
||||||
file: downloadPath,
|
file: downloadPath,
|
||||||
url: downloadPath,
|
url: downloadPath,
|
||||||
file_size: fileSize,
|
file_size: fileSize,
|
||||||
file_name: fileName,
|
file_name: fileName,
|
||||||
};
|
};
|
||||||
if (/* enableLocalFile2Url && */ downloadPath) {
|
|
||||||
|
if (this.obContext.configLoader.configData.enableLocalFile2Url && downloadPath) {
|
||||||
|
try {
|
||||||
|
res.base64 = await fs.readFile(downloadPath, 'base64');
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('文件下载失败. ' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
//群文件模式
|
||||||
|
const contextModelIdFile = FileNapCatOneBotUUID.decodeModelId(payload.file);
|
||||||
|
if (contextModelIdFile) {
|
||||||
|
const { peer, modelId } = contextModelIdFile;
|
||||||
|
const downloadPath = await NTQQFileApi.downloadFileForModelId(peer, modelId);
|
||||||
|
const res: GetFileResponse = {
|
||||||
|
file: downloadPath,
|
||||||
|
url: downloadPath,
|
||||||
|
file_size: '',
|
||||||
|
file_name: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.obContext.configLoader.configData.enableLocalFile2Url && downloadPath) {
|
||||||
try {
|
try {
|
||||||
res.base64 = await fs.readFile(downloadPath, 'base64');
|
res.base64 = await fs.readFile(downloadPath, 'base64');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('文件下载失败. ' + e);
|
throw new Error('文件下载失败. ' + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//不手动删除?文件持久化了
|
|
||||||
return res;
|
return res;
|
||||||
} catch {
|
|
||||||
this.core.context.logger.logDebug('GetFileBase Mode - 1 Error');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//搜索名字模式
|
||||||
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;
|
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;
|
||||||
if (NTSearchNameResult.length !== 0) {
|
if (NTSearchNameResult.length !== 0) {
|
||||||
const MsgId = NTSearchNameResult[0].msgId;
|
const MsgId = NTSearchNameResult[0].msgId;
|
||||||
@@ -94,9 +94,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
if (NTSearchNameResult[0].chatType == ChatType.KCHATTYPEGROUP) {
|
if (NTSearchNameResult[0].chatType == ChatType.KCHATTYPEGROUP) {
|
||||||
peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: NTSearchNameResult[0].groupChatInfo[0].groupCode };
|
peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: NTSearchNameResult[0].groupChatInfo[0].groupCode };
|
||||||
}
|
}
|
||||||
if (!peer) {
|
if (!peer) throw new Error('chattype not support');
|
||||||
throw new Error('chattype not support');
|
|
||||||
}
|
|
||||||
const msgList: RawMessage[] = (await NTQQMsgApi.getMsgsByMsgId(peer, [MsgId]))?.msgList;
|
const msgList: RawMessage[] = (await NTQQMsgApi.getMsgsByMsgId(peer, [MsgId]))?.msgList;
|
||||||
if (!msgList || msgList.length == 0) {
|
if (!msgList || msgList.length == 0) {
|
||||||
throw new Error('msg not found');
|
throw new Error('msg not found');
|
||||||
@@ -113,16 +111,16 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
|
|||||||
file_size: NTSearchNameResult[0].fileSize.toString(),
|
file_size: NTSearchNameResult[0].fileSize.toString(),
|
||||||
file_name: NTSearchNameResult[0].fileName,
|
file_name: NTSearchNameResult[0].fileName,
|
||||||
};
|
};
|
||||||
if (/* enableLocalFile2Url && */ downloadPath) {
|
if (this.obContext.configLoader.configData.enableLocalFile2Url && downloadPath) {
|
||||||
try {
|
try {
|
||||||
res.base64 = await fs.readFile(downloadPath, 'base64');
|
res.base64 = await fs.readFile(downloadPath, 'base64');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('文件下载失败. ' + e);
|
throw new Error('文件下载失败. ' + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//不手动删除?文件持久化了
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('file not found');
|
throw new Error('file not found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,8 +6,9 @@ const SchemaData = {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
group_id: { type: ['string', 'number'] },
|
group_id: { type: ['string', 'number'] },
|
||||||
start_index: { type: 'number' },
|
start_index: { type: ['string', 'number'] },
|
||||||
file_count: { type: 'number' },
|
file_count: { type: ['string', 'number'] },
|
||||||
|
folder_id: { type: ['string', 'number'] },
|
||||||
},
|
},
|
||||||
required: ['group_id', 'start_index', 'file_count'],
|
required: ['group_id', 'start_index', 'file_count'],
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
@@ -20,12 +21,19 @@ export class GetGroupFileList extends BaseAction<Payload, { FileList: Array<any>
|
|||||||
|
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQMsgApi = this.core.apis.MsgApi;
|
const NTQQMsgApi = this.core.apis.MsgApi;
|
||||||
|
let param = {};
|
||||||
|
if (payload.folder_id) {
|
||||||
|
param = {
|
||||||
|
folderId: payload.folder_id.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
const ret = await NTQQMsgApi.getGroupFileList(payload.group_id.toString(), {
|
const ret = await NTQQMsgApi.getGroupFileList(payload.group_id.toString(), {
|
||||||
sortType: 1,
|
sortType: 1,
|
||||||
fileCount: payload.file_count,
|
fileCount: +payload.file_count,
|
||||||
startIndex: payload.start_index,
|
startIndex: +payload.start_index,
|
||||||
sortOrder: 2,
|
sortOrder: 2,
|
||||||
showOnlinedocFolder: 0,
|
showOnlinedocFolder: 0,
|
||||||
|
...param
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
@@ -38,7 +38,7 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
|
|||||||
const resMsg = await this.obContext.apis.MsgApi
|
const resMsg = await this.obContext.apis.MsgApi
|
||||||
.parseMessage(msg);
|
.parseMessage(msg);
|
||||||
if (!resMsg) return;
|
if (!resMsg) return;
|
||||||
resMsg.message_id = MessageUnique.createMsg({
|
resMsg.message_id = MessageUnique.createUniqueMsgId({
|
||||||
guildId: '',
|
guildId: '',
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
|
@@ -47,7 +47,7 @@ export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
|
|||||||
if (isReverseOrder) msgList.reverse();
|
if (isReverseOrder) msgList.reverse();
|
||||||
//转换序号
|
//转换序号
|
||||||
await Promise.all(msgList.map(async msg => {
|
await Promise.all(msgList.map(async msg => {
|
||||||
msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
msg.id = MessageUnique.createUniqueMsgId({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||||
}));
|
}));
|
||||||
//烘焙消息
|
//烘焙消息
|
||||||
const ob11MsgList = (await Promise.all(
|
const ob11MsgList = (await Promise.all(
|
||||||
|
@@ -42,7 +42,7 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
|
|||||||
if (isReverseOrder) msgList.reverse();
|
if (isReverseOrder) msgList.reverse();
|
||||||
//转换序号
|
//转换序号
|
||||||
await Promise.all(msgList.map(async msg => {
|
await Promise.all(msgList.map(async msg => {
|
||||||
msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
msg.id = MessageUnique.createUniqueMsgId({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
|
||||||
}));
|
}));
|
||||||
//烘焙消息
|
//烘焙消息
|
||||||
const ob11MsgList = (await Promise.all(
|
const ob11MsgList = (await Promise.all(
|
||||||
|
@@ -20,7 +20,13 @@ export default class DelEssenceMsg extends BaseAction<Payload, any> {
|
|||||||
async _handle(payload: Payload): Promise<any> {
|
async _handle(payload: Payload): Promise<any> {
|
||||||
const NTQQGroupApi = this.core.apis.GroupApi;
|
const NTQQGroupApi = this.core.apis.GroupApi;
|
||||||
const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
|
const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
|
||||||
if (!msg) throw new Error('msg not found');
|
const NTQQWebApi = this.core.apis.WebApi;
|
||||||
|
if (!msg) {
|
||||||
|
const data = NTQQGroupApi.essenceLRU.getValue(+payload.message_id);
|
||||||
|
if(!data) throw new Error('消息不存在');
|
||||||
|
const { msg_seq, msg_random, group_id } = JSON.parse(data) as { msg_seq: string, msg_random: string, group_id: string };
|
||||||
|
return await NTQQGroupApi.removeGroupEssenceBySeq(group_id, msg_seq, msg_random);
|
||||||
|
}
|
||||||
return await NTQQGroupApi.removeGroupEssence(
|
return await NTQQGroupApi.removeGroupEssence(
|
||||||
msg.Peer.peerUid,
|
msg.Peer.peerUid,
|
||||||
msg.MsgId,
|
msg.MsgId,
|
||||||
|
@@ -1,29 +1,117 @@
|
|||||||
import { GroupEssenceMsgRet } from '@/core';
|
import { ChatType, GroupEssenceMsgRet, Peer } from '@/core';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
|
import { MessageUnique } from '@/common/message-unique';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
group_id: { type: ['number', 'string'] },
|
group_id: { type: ['number', 'string'] }
|
||||||
pages: { type: ['number', 'string'] },
|
|
||||||
},
|
},
|
||||||
required: ['group_id'],
|
required: ['group_id'],
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
type Payload = FromSchema<typeof SchemaData>;
|
type Payload = FromSchema<typeof SchemaData>;
|
||||||
|
|
||||||
export class GetGroupEssence extends BaseAction<Payload, GroupEssenceMsgRet> {
|
export class GetGroupEssence extends BaseAction<Payload, any> {
|
||||||
actionName = ActionName.GoCQHTTP_GetEssenceMsg;
|
actionName = ActionName.GoCQHTTP_GetEssenceMsg;
|
||||||
payloadSchema = SchemaData;
|
payloadSchema = SchemaData;
|
||||||
|
async parseEssenceMsgImage(ele: any) {
|
||||||
|
return {
|
||||||
|
type: 'image',
|
||||||
|
data: {
|
||||||
|
url: ele?.image_url,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
async parseEssenceMsgText(ele: any) {
|
||||||
|
return {
|
||||||
|
type: 'text',
|
||||||
|
data: {
|
||||||
|
text: ele?.text
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
async parseEssenceMsg(msgs: any) {
|
||||||
|
let handledMsg: any[] = [];
|
||||||
|
for (let msg of msgs) {
|
||||||
|
switch (msg.msg_type) {
|
||||||
|
case 1:
|
||||||
|
handledMsg.push(await this.parseEssenceMsgText(msg));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
handledMsg.push(await this.parseEssenceMsgImage(msg));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handledMsg;
|
||||||
|
}
|
||||||
|
async msgSeqToMsgId(peer: Peer, msgSeq: string, msgRandom: string) {
|
||||||
|
const NTQQMsgApi = this.core.apis.MsgApi;
|
||||||
|
const replyMsgList = (await NTQQMsgApi.getMsgsBySeqAndCount(peer, msgSeq, 1, true, true)).msgList.find((msg) => msg.msgSeq === msgSeq && msg.msgRandom === msgRandom);
|
||||||
|
if (!replyMsgList) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: MessageUnique.createUniqueMsgId(peer, replyMsgList.msgId),
|
||||||
|
msg: replyMsgList
|
||||||
|
}
|
||||||
|
}
|
||||||
async _handle(payload: Payload) {
|
async _handle(payload: Payload) {
|
||||||
const NTQQWebApi = this.core.apis.WebApi;
|
const NTQQWebApi = this.core.apis.WebApi;
|
||||||
const ret = await NTQQWebApi.getGroupEssenceMsg(payload.group_id.toString(), (+(payload.pages ?? 0)).toString());
|
const NTQQGroupApi = this.core.apis.GroupApi;
|
||||||
|
//await NTQQGroupApi.fetchGroupEssenceList(payload.group_id.toString());
|
||||||
|
let peer = {
|
||||||
|
chatType: ChatType.KCHATTYPEGROUP,
|
||||||
|
peerUid: payload.group_id.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const ret = await NTQQWebApi.getGroupEssenceMsg(payload.group_id.toString());
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
throw new Error('获取失败');
|
throw new Error('获取失败');
|
||||||
}
|
}
|
||||||
return ret;
|
const Ob11Ret = await Promise.all(ret.data.msg_list.map(async (msg) => {
|
||||||
|
let msgOriginData = await this.msgSeqToMsgId(peer, msg.msg_seq.toString(), msg.msg_random.toString());
|
||||||
|
if (msgOriginData) {
|
||||||
|
const { id: message_id, msg: rawMessage } = msgOriginData;
|
||||||
|
return {
|
||||||
|
msg_seq: msg.msg_seq,
|
||||||
|
msg_random: msg.msg_random,
|
||||||
|
sender_id: +msg.sender_uin,
|
||||||
|
sender_nick: msg.sender_nick,
|
||||||
|
operator_id: +msg.add_digest_uin,
|
||||||
|
operator_nick: msg.add_digest_nick,
|
||||||
|
message_id: message_id,
|
||||||
|
operator_time: msg.add_digest_time,
|
||||||
|
content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage, 'array'))?.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const msgTempData = JSON.stringify({
|
||||||
|
msg_seq: msg.msg_seq.toString(),
|
||||||
|
msg_random: msg.msg_random.toString(),
|
||||||
|
group_id: payload.group_id.toString(),
|
||||||
|
});
|
||||||
|
const hash = crypto.createHash('md5').update(msgTempData).digest();
|
||||||
|
//设置第一个bit为0 保证shortId为正数
|
||||||
|
hash[0] &= 0x7f;
|
||||||
|
const shortId = hash.readInt32BE(0);
|
||||||
|
NTQQGroupApi.essenceLRU.set(shortId, msgTempData);
|
||||||
|
return {
|
||||||
|
msg_seq: msg.msg_seq,
|
||||||
|
msg_random: msg.msg_random,
|
||||||
|
sender_id: +msg.sender_uin,
|
||||||
|
sender_nick: msg.sender_nick,
|
||||||
|
operator_id: +msg.add_digest_uin,
|
||||||
|
operator_nick: msg.add_digest_nick,
|
||||||
|
message_id: shortId,
|
||||||
|
operator_time: msg.add_digest_time,
|
||||||
|
content: await this.parseEssenceMsg(msg.msg_content)
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
return Ob11Ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -81,11 +81,13 @@ import SetModelShow from './go-cqhttp/SetModelShow';
|
|||||||
import { SetInputStatus } from './extends/SetInputStatus';
|
import { SetInputStatus } from './extends/SetInputStatus';
|
||||||
import { GetCSRF } from './system/GetCSRF';
|
import { GetCSRF } from './system/GetCSRF';
|
||||||
import { DelGroupNotice } from './group/DelGroupNotice';
|
import { DelGroupNotice } from './group/DelGroupNotice';
|
||||||
|
import { GetGroupInfoEx } from './extends/GetGroupInfoEx';
|
||||||
|
|
||||||
export type ActionMap = Map<string, BaseAction<any, any>>;
|
export type ActionMap = Map<string, BaseAction<any, any>>;
|
||||||
|
|
||||||
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
|
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
|
||||||
const actionHandlers = [
|
const actionHandlers = [
|
||||||
|
new GetGroupInfoEx(obContext, core),
|
||||||
new FetchEmojiLike(obContext, core),
|
new FetchEmojiLike(obContext, core),
|
||||||
new GetFile(obContext, core),
|
new GetFile(obContext, core),
|
||||||
new SetQQProfile(obContext, core),
|
new SetQQProfile(obContext, core),
|
||||||
|
@@ -39,7 +39,7 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
|
|||||||
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0], 'array');
|
const retMsg = await this.obContext.apis.MsgApi.parseMessage(msg.msgList[0], 'array');
|
||||||
if (!retMsg) throw Error('消息为空');
|
if (!retMsg) throw Error('消息为空');
|
||||||
try {
|
try {
|
||||||
retMsg.message_id = MessageUnique.createMsg(peer, msg.msgList[0].msgId)!;
|
retMsg.message_id = MessageUnique.createUniqueMsgId(peer, msg.msgList[0].msgId)!;
|
||||||
retMsg.message_seq = retMsg.message_id;
|
retMsg.message_seq = retMsg.message_id;
|
||||||
retMsg.real_id = retMsg.message_id;
|
retMsg.real_id = retMsg.message_id;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@@ -114,7 +114,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
if (getSpecialMsgNum(payload, OB11MessageDataType.node)) {
|
||||||
const returnMsg = await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
|
const returnMsg = await this.handleForwardedNodes(peer, messages as OB11MessageNode[]);
|
||||||
if (returnMsg) {
|
if (returnMsg) {
|
||||||
const msgShortId = MessageUnique.createMsg({
|
const msgShortId = MessageUnique.createUniqueMsgId({
|
||||||
guildId: '',
|
guildId: '',
|
||||||
peerUid: peer.peerUid,
|
peerUid: peer.peerUid,
|
||||||
chatType: peer.chatType,
|
chatType: peer.chatType,
|
||||||
@@ -170,7 +170,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
||||||
if (nodeMsg) {
|
if (nodeMsg) {
|
||||||
nodeMsgIds.push(nodeMsg.msgId);
|
nodeMsgIds.push(nodeMsg.msgId);
|
||||||
MessageUnique.createMsg(selfPeer, nodeMsg.msgId);
|
MessageUnique.createUniqueMsgId(selfPeer, nodeMsg.msgId);
|
||||||
}
|
}
|
||||||
//完成子卡片生成跳过后续
|
//完成子卡片生成跳过后续
|
||||||
continue;
|
continue;
|
||||||
@@ -188,7 +188,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
(await Promise.allSettled(MsgNodeList)).map((result) => {
|
(await Promise.allSettled(MsgNodeList)).map((result) => {
|
||||||
if (result.status === 'fulfilled' && result.value) {
|
if (result.status === 'fulfilled' && result.value) {
|
||||||
nodeMsgIds.push(result.value.msgId);
|
nodeMsgIds.push(result.value.msgId);
|
||||||
MessageUnique.createMsg(selfPeer, result.value.msgId);
|
MessageUnique.createUniqueMsgId(selfPeer, result.value.msgId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@@ -110,4 +110,5 @@ export enum ActionName {
|
|||||||
SetInputStatus = 'set_input_status',
|
SetInputStatus = 'set_input_status',
|
||||||
GetCSRF = 'get_csrf_token',
|
GetCSRF = 'get_csrf_token',
|
||||||
DelGroupNotice = '_del_group_notice',
|
DelGroupNotice = '_del_group_notice',
|
||||||
|
GetGroupInfoEx = "get_group_info_ex"
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { UUIDConverter } from '@/common/helper';
|
import { FileNapCatOneBotUUID } from '@/common/helper';
|
||||||
import { MessageUnique } from '@/common/message-unique';
|
import { MessageUnique } from '@/common/message-unique';
|
||||||
import {
|
import {
|
||||||
AtType,
|
AtType,
|
||||||
@@ -98,14 +98,19 @@ export class OneBotMsgApi {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
picElement: async (element, msg) => {
|
picElement: async (element, msg, elementWrapper) => {
|
||||||
try {
|
try {
|
||||||
|
const peer = {
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid,
|
||||||
|
guildId: '',
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
type: OB11MessageDataType.image,
|
type: OB11MessageDataType.image,
|
||||||
data: {
|
data: {
|
||||||
file: element.fileName,
|
file: element.fileName,
|
||||||
sub_type: element.picSubType,
|
sub_type: element.picSubType,
|
||||||
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||||
url: await this.core.apis.FileApi.getImageUrl(element),
|
url: await this.core.apis.FileApi.getImageUrl(element),
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
},
|
},
|
||||||
@@ -117,6 +122,11 @@ export class OneBotMsgApi {
|
|||||||
},
|
},
|
||||||
|
|
||||||
fileElement: async (element, msg, elementWrapper) => {
|
fileElement: async (element, msg, elementWrapper) => {
|
||||||
|
const peer = {
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid,
|
||||||
|
guildId: '',
|
||||||
|
};
|
||||||
await this.core.apis.FileApi.addFileCache(
|
await this.core.apis.FileApi.addFileCache(
|
||||||
{
|
{
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
@@ -137,7 +147,7 @@ export class OneBotMsgApi {
|
|||||||
file: element.fileName,
|
file: element.fileName,
|
||||||
path: element.filePath,
|
path: element.filePath,
|
||||||
url: element.filePath,
|
url: element.filePath,
|
||||||
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -184,11 +194,16 @@ export class OneBotMsgApi {
|
|||||||
'0',
|
'0',
|
||||||
'marketface',
|
'marketface',
|
||||||
);
|
);
|
||||||
|
const peer = {
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid,
|
||||||
|
guildId: '',
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
type: OB11MessageDataType.image,
|
type: OB11MessageDataType.image,
|
||||||
data: {
|
data: {
|
||||||
file: 'marketface',
|
file: 'marketface',
|
||||||
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||||
path: elementWrapper.elementId,
|
path: elementWrapper.elementId,
|
||||||
url: elementWrapper.elementId,
|
url: elementWrapper.elementId,
|
||||||
},
|
},
|
||||||
@@ -207,13 +222,21 @@ export class OneBotMsgApi {
|
|||||||
this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
|
this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createReplyData = (msgId: string): OB11MessageData => ({
|
||||||
|
type: OB11MessageDataType.reply,
|
||||||
|
data: {
|
||||||
|
id: MessageUnique.createUniqueMsgId(peer, msgId).toString(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (records.peerUin === '284840486') {
|
||||||
|
return createReplyData(records.msgId);
|
||||||
|
}
|
||||||
|
|
||||||
let replyMsg: RawMessage | undefined;
|
let replyMsg: RawMessage | undefined;
|
||||||
// Attempt 1
|
// Attempt 1
|
||||||
replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount({
|
replyMsg = (await NTQQMsgApi.getMsgsBySeqAndCount(peer,element.replayMsgSeq, 1, true, true))
|
||||||
peerUid: msg.peerUid,
|
|
||||||
guildId: '',
|
|
||||||
chatType: msg.chatType,
|
|
||||||
}, element.replayMsgSeq, 1, true, true))
|
|
||||||
.msgList
|
.msgList
|
||||||
.find(msg => msg.msgRandom === records.msgRandom);
|
.find(msg => msg.msgRandom === records.msgRandom);
|
||||||
|
|
||||||
@@ -221,7 +244,7 @@ export class OneBotMsgApi {
|
|||||||
// Attempt 2
|
// Attempt 2
|
||||||
replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replayMsgSeq)).msgList[0];
|
replyMsg = (await NTQQMsgApi.getSingleMsg(peer, element.replayMsgSeq)).msgList[0];
|
||||||
|
|
||||||
if ((!replyMsg || records.msgRandom !== replyMsg.msgRandom) && msg.peerUin !== '284840486') {
|
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
|
||||||
// Attempt 3
|
// Attempt 3
|
||||||
const replyMsgList = (await NTQQMsgApi.getMsgExBySeq(peer, records.msgSeq)).msgList;
|
const replyMsgList = (await NTQQMsgApi.getMsgExBySeq(peer, records.msgSeq)).msgList;
|
||||||
if (replyMsgList.length < 1) {
|
if (replyMsgList.length < 1) {
|
||||||
@@ -233,21 +256,16 @@ export class OneBotMsgApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return createReplyData(replyMsg.msgId);
|
||||||
type: OB11MessageDataType.reply,
|
|
||||||
data: {
|
|
||||||
id: MessageUnique.createMsg({
|
|
||||||
peerUid: msg.peerUid,
|
|
||||||
guildId: '',
|
|
||||||
chatType: msg.chatType,
|
|
||||||
}, replyMsg.msgId).toString(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
videoElement: async (element, msg, elementWrapper) => {
|
videoElement: async (element, msg, elementWrapper) => {
|
||||||
const NTQQFileApi = this.core.apis.FileApi;
|
const NTQQFileApi = this.core.apis.FileApi;
|
||||||
|
const peer = {
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid,
|
||||||
|
guildId: '',
|
||||||
|
};
|
||||||
//读取视频链接并兜底
|
//读取视频链接并兜底
|
||||||
let videoUrlWrappers: Awaited<ReturnType<typeof NTQQFileApi.getVideoUrl>> | undefined;
|
let videoUrlWrappers: Awaited<ReturnType<typeof NTQQFileApi.getVideoUrl>> | undefined;
|
||||||
|
|
||||||
@@ -302,13 +320,18 @@ export class OneBotMsgApi {
|
|||||||
file: element.fileName,
|
file: element.fileName,
|
||||||
path: videoDownUrl,
|
path: videoDownUrl,
|
||||||
url: videoDownUrl,
|
url: videoDownUrl,
|
||||||
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
pttElement: async (element, msg, elementWrapper) => {
|
pttElement: async (element, msg, elementWrapper) => {
|
||||||
|
const peer = {
|
||||||
|
chatType: msg.chatType,
|
||||||
|
peerUid: msg.peerUid,
|
||||||
|
guildId: '',
|
||||||
|
};
|
||||||
await this.core.apis.FileApi.addFileCache(
|
await this.core.apis.FileApi.addFileCache(
|
||||||
{
|
{
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
@@ -328,7 +351,7 @@ export class OneBotMsgApi {
|
|||||||
data: {
|
data: {
|
||||||
file: element.fileName,
|
file: element.fileName,
|
||||||
path: element.filePath,
|
path: element.filePath,
|
||||||
file_id: UUIDConverter.encode(msg.peerUin, msg.msgId),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId),
|
||||||
file_size: element.fileSize,
|
file_size: element.fileSize,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -365,7 +388,7 @@ export class OneBotMsgApi {
|
|||||||
async multiMsgItem => {
|
async multiMsgItem => {
|
||||||
multiMsgItem.parentMsgPeer = parentMsgPeer;
|
multiMsgItem.parentMsgPeer = parentMsgPeer;
|
||||||
multiMsgItem.parentMsgIdList = msg.parentMsgIdList;
|
multiMsgItem.parentMsgIdList = msg.parentMsgIdList;
|
||||||
multiMsgItem.id = MessageUnique.createMsg(parentMsgPeer, multiMsgItem.msgId); //该ID仅用查看 无法调用
|
multiMsgItem.id = MessageUnique.createUniqueMsgId(parentMsgPeer, multiMsgItem.msgId); //该ID仅用查看 无法调用
|
||||||
return await this.parseMessage(multiMsgItem);
|
return await this.parseMessage(multiMsgItem);
|
||||||
},
|
},
|
||||||
))).filter(item => item !== undefined),
|
))).filter(item => item !== undefined),
|
||||||
@@ -823,7 +846,7 @@ export class OneBotMsgApi {
|
|||||||
}
|
}
|
||||||
const returnMsg = await this.core.apis.MsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
const returnMsg = await this.core.apis.MsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
||||||
if (!returnMsg) throw new Error('发送消息失败');
|
if (!returnMsg) throw new Error('发送消息失败');
|
||||||
returnMsg.id = MessageUnique.createMsg({
|
returnMsg.id = MessageUnique.createUniqueMsgId({
|
||||||
chatType: peer.chatType,
|
chatType: peer.chatType,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
peerUid: peer.peerUid,
|
peerUid: peer.peerUid,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"http": {
|
"http": {
|
||||||
"enable": true,
|
"enable": false,
|
||||||
"host": "",
|
"host": "",
|
||||||
"port": 3000,
|
"port": 3000,
|
||||||
"secret": "",
|
"secret": "",
|
||||||
|
@@ -261,6 +261,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
emojiLikeToOthers.msgSpec!.msgSeq.toString(),
|
emojiLikeToOthers.msgSpec!.msgSeq.toString(),
|
||||||
emojiLikeToOthers.attributes!.emojiId,
|
emojiLikeToOthers.attributes!.emojiId,
|
||||||
);
|
);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||||
eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
|
eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,7 +284,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
this.context.logger.logDebug(`消息时间${m.msgTime}早于启动时间${this.bootTime},忽略上报`);
|
this.context.logger.logDebug(`消息时间${m.msgTime}早于启动时间${this.bootTime},忽略上报`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m.id = MessageUnique.createMsg(
|
m.id = MessageUnique.createUniqueMsgId(
|
||||||
{
|
{
|
||||||
chatType: m.chatType,
|
chatType: m.chatType,
|
||||||
peerUid: m.peerUid,
|
peerUid: m.peerUid,
|
||||||
@@ -311,7 +312,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
if (!ob11Msg) return;
|
if (!ob11Msg) return;
|
||||||
ob11Msg.target_id = parseInt(msg.peerUin);
|
ob11Msg.target_id = parseInt(msg.peerUin);
|
||||||
if (this.configLoader.configData.reportSelfMessage) {
|
if (this.configLoader.configData.reportSelfMessage) {
|
||||||
msg.id = MessageUnique.createMsg({
|
msg.id = MessageUnique.createUniqueMsgId({
|
||||||
chatType: msg.chatType,
|
chatType: msg.chatType,
|
||||||
peerUid: msg.peerUid,
|
peerUid: msg.peerUid,
|
||||||
guildId: '',
|
guildId: '',
|
||||||
@@ -344,7 +345,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) {
|
if (!!req.isInitiator || (req.isDecide && req.reqType !== BuddyReqType.KMEINITIATORWAITPEERCONFIRM)) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const requesterUin = await this.core.apis.UserApi.getUinByUidV2(req.friendUid);
|
const requesterUin = await this.core.apis.UserApi.getUinByUidV2(req.friendUid);
|
||||||
@@ -367,9 +368,10 @@ export class NapCatOneBot11Adapter {
|
|||||||
|
|
||||||
private initGroupListener() {
|
private initGroupListener() {
|
||||||
const groupListener = new NodeIKernelGroupListener();
|
const groupListener = new NodeIKernelGroupListener();
|
||||||
|
|
||||||
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
|
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
|
||||||
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
|
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
|
||||||
|
await this.core.apis.GroupApi.clearGroupNotifiesUnreadCount(false);
|
||||||
if (![
|
if (![
|
||||||
GroupNotifyMsgType.SET_ADMIN,
|
GroupNotifyMsgType.SET_ADMIN,
|
||||||
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED,
|
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED,
|
||||||
|
@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
undefined,
|
undefined,
|
||||||
SettingButton('V2.2.19', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.2.22', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
void 0,
|
void 0,
|
||||||
SettingButton("V2.2.19", "napcat-update-button", "secondary")
|
SettingButton("V2.2.22", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
Reference in New Issue
Block a user