Compare commits

...

18 Commits

Author SHA1 Message Date
手瓜一十雪
6024cabb69 Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2024-08-25 22:36:53 +08:00
手瓜一十雪
08446e648e release: 2.2.8 2024-08-25 22:36:42 +08:00
Alen
14af7a3572 Merge pull request #302 from cnxysoft/upmain
fix: 多个问题
2024-08-25 22:23:58 +08:00
Alen
cdc4275f81 fix: 多个问题
修复group_increase事件上报
修复启动时加载群员信息失败
修复文件发送失败
2024-08-25 22:23:06 +08:00
手瓜一十雪
a9ade98315 style: remove unless 2024-08-25 22:12:38 +08:00
手瓜一十雪
f3ae6fa70f style: fix 2024-08-25 22:09:30 +08:00
手瓜一十雪
8f465e376e style: type 2024-08-25 21:59:07 +08:00
手瓜一十雪
adc366a959 style: 清理不规范代码 2024-08-25 21:54:20 +08:00
手瓜一十雪
b176fa66d4 style: 样式处理 2024-08-25 21:47:55 +08:00
手瓜一十雪
7b7609a068 style: 标准化样式 2024-08-25 21:37:36 +08:00
手瓜一十雪
136e27d655 fix: 消息组合 2024-08-25 19:38:19 +08:00
手瓜一十雪
e3ca5df713 Delete .github/workflows/codacy.yml 2024-08-25 12:52:31 +08:00
手瓜一十雪
bda32f3e8f chore:update 2024-08-25 12:08:36 +08:00
手瓜一十雪
a7c6e45a92 chore: codacy 2024-08-25 12:02:03 +08:00
手瓜一十雪
7c20ca9b64 style:lint 2024-08-25 11:45:50 +08:00
手瓜一十雪
a201461eff chore: lint 2024-08-25 11:18:11 +08:00
Seijo Cecilia
e5d9df37c5 Merge remote-tracking branch 'origin/main' 2024-08-25 10:14:42 +08:00
Seijo Cecilia
106fbaf086 refactor: make parseMessage an instance method 2024-08-25 10:14:11 +08:00
41 changed files with 317 additions and 394 deletions

View File

@@ -4,7 +4,7 @@
"name": "NapCatQQ", "name": "NapCatQQ",
"slug": "NapCat.Framework", "slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现", "description": "高性能的 OneBot 11 协议实现",
"version": "2.2.7", "version": "2.2.8",
"icon": "./logo.png", "icon": "./logo.png",
"authors": [ "authors": [
{ {

View File

@@ -2,7 +2,7 @@
"name": "napcat", "name": "napcat",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "2.2.7", "version": "2.2.8",
"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",

View File

@@ -1,7 +1,7 @@
import { NodeIQQNTWrapperSession } from '@/core/wrapper/wrapper'; import { NodeIQQNTWrapperSession } from '@/core/wrapper/wrapper';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
interface Internal_MapKey { interface InternalMapKey {
timeout: number; timeout: number;
createtime: number; createtime: number;
func: (...arg: any[]) => any; func: (...arg: any[]) => any;
@@ -11,14 +11,14 @@ interface Internal_MapKey {
export type ListenerClassBase = Record<string, string>; export type ListenerClassBase = Record<string, string>;
export interface ListenerIBase { export interface ListenerIBase {
// eslint-disable-next-line @typescript-eslint/no-misused-new
new(listener: any): ListenerClassBase; new(listener: any): ListenerClassBase;
[key: string]: any;
} }
export class LegacyNTEventWrapper { export class LegacyNTEventWrapper {
private WrapperSession: NodeIQQNTWrapperSession | undefined; //WrapperSession private WrapperSession: NodeIQQNTWrapperSession | undefined; //WrapperSession
private listenerManager: Map<string, ListenerClassBase> = new Map<string, ListenerClassBase>(); //ListenerName-Unique -> Listener实例 private listenerManager: Map<string, ListenerClassBase> = new Map<string, ListenerClassBase>(); //ListenerName-Unique -> Listener实例
private EventTask = new Map<string, Map<string, Map<string, Internal_MapKey>>>(); //tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func} private EventTask = new Map<string, Map<string, Map<string, InternalMapKey>>>(); //tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func}
constructor( constructor(
wrapperSession: NodeIQQNTWrapperSession wrapperSession: NodeIQQNTWrapperSession
@@ -27,17 +27,15 @@ export class LegacyNTEventWrapper {
} }
createProxyDispatch(ListenerMainName: string) { createProxyDispatch(ListenerMainName: string) {
// eslint-disable-next-line @typescript-eslint/no-this-alias const dispatcherListenerFunc = this.dispatcherListener.bind(this);
const current = this;
return new Proxy( return new Proxy(
{}, {},
{ {
get(target: any, prop: any, receiver: any) { get(target: any, prop: any, receiver: any) {
// console.log('get', prop, typeof target[prop]);
if (typeof target[prop] === 'undefined') { if (typeof target[prop] === 'undefined') {
// 如果方法不存在返回一个函数这个函数调用existentMethod // 如果方法不存在返回一个函数这个函数调用existentMethod
return (...args: any[]) => { return (...args: any[]) => {
current.dispatcherListener.apply(current, [ListenerMainName, prop, ...args]).then(); dispatcherListenerFunc(ListenerMainName, prop, ...args).then();
}; };
} }
// 如果方法存在,正常返回 // 如果方法存在,正常返回
@@ -55,8 +53,6 @@ export class LegacyNTEventWrapper {
if (eventNameArr.length > 1) { if (eventNameArr.length > 1) {
const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', ''); const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', '');
const eventName = eventNameArr[1]; const eventName = eventNameArr[1];
//getNodeIKernelGroupListener,GroupService
//console.log('2', eventName);
const services = (this.WrapperSession as unknown as eventType)[serviceName](); const services = (this.WrapperSession as unknown as eventType)[serviceName]();
let event = services[eventName]; let event = services[eventName];
//重新绑定this //重新绑定this
@@ -84,16 +80,14 @@ export class LegacyNTEventWrapper {
//统一回调清理事件 //统一回调清理事件
async dispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) { async dispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) {
//console.log("[EventDispatcher]",ListenerMainName, ListenerSubName, ...args);
this.EventTask.get(ListenerMainName) this.EventTask.get(ListenerMainName)
?.get(ListenerSubName) ?.get(ListenerSubName)
?.forEach((task, uuid) => { ?.forEach((task, uuid) => {
//console.log(task.func, uuid, task.createtime, task.timeout);
if (task.createtime + task.timeout < Date.now()) { if (task.createtime + task.timeout < Date.now()) {
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.delete(uuid); this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.delete(uuid);
return; return;
} }
if (task.checker && task.checker(...args)) { if (task?.checker?.(...args)) {
task.func(...args); task.func(...args);
} }
}); });
@@ -210,7 +204,6 @@ export class LegacyNTEventWrapper {
checker: checkerListener, checker: checkerListener,
func: (...args: any[]) => { func: (...args: any[]) => {
complete++; complete++;
//console.log('func', ...args);
retData = args as Parameters<ListenerType>; retData = args as Parameters<ListenerType>;
if (complete >= waitTimes) { if (complete >= waitTimes) {
clearTimeout(Timeouter); clearTimeout(Timeouter);
@@ -228,7 +221,7 @@ export class LegacyNTEventWrapper {
this.createListenerFunction(ListenerMainName); this.createListenerFunction(ListenerMainName);
const EventFunc = this.createEventFunction<EventType>(EventName); const EventFunc = this.createEventFunction<EventType>(EventName);
retEvent = await EventFunc!(...(args as any[])); retEvent = await EventFunc!(...(args as any[]));
if(!checkerEvent(retEvent)){ if (!checkerEvent(retEvent)) {
clearTimeout(Timeouter); clearTimeout(Timeouter);
reject( reject(
new Error( new Error(
@@ -314,28 +307,3 @@ export class LegacyNTEventWrapper {
); );
} }
} }
// 示例代码 快速创建事件
// let NTEvent = new NTEventWrapper();
// let TestEvent = NTEvent.CreatEventFunction<(force: boolean) => Promise<Number>>('NodeIKernelProfileLikeService/GetTest');
// if (TestEvent) {
// TestEvent(true);
// }
// 示例代码 快速创建监听Listener类
// let NTEvent = new NTEventWrapper();
// NTEvent.CreatListenerFunction<NodeIKernelMsgListener>('NodeIKernelMsgListener', 'core')
// 调用接口
//let NTEvent = new NTEventWrapper();
//let ret = await NTEvent.CallNormalEvent<(force: boolean) => Promise<Number>, (data1: string, data2: number) => void>('NodeIKernelProfileLikeService/GetTest', 'NodeIKernelMsgListener/onAddSendMsg', 1, 3000, true);
// 注册监听 解除监听
// NTEventDispatch.RigisterListener('NodeIKernelMsgListener/onAddSendMsg','core',cb);
// NTEventDispatch.UnRigisterListener('NodeIKernelMsgListener/onAddSendMsg','core');
// let GetTest = NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode);
// GetTest('test');
// always模式
// NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode,(...args:any[])=>{ console.log(args) });

View File

@@ -124,14 +124,7 @@ export class NTEventChannel extends EventEmitter {
EventName = '', timeout: number = 3000, ...args: Parameters<EventType>) { EventName = '', timeout: number = 3000, ...args: Parameters<EventType>) {
return new Promise<Awaited<ReturnType<EventType>>>(async (resolve, reject) => { return new Promise<Awaited<ReturnType<EventType>>>(async (resolve, reject) => {
const EventFunc = this.createEventFunction<EventType>(EventName); const EventFunc = this.createEventFunction<EventType>(EventName);
let complete = false;
const Timeouter = setTimeout(() => {
if (!complete) {
reject(new Error('NTEvent EventName:' + EventName + ' timeout'));
}
}, timeout);
const retData = await EventFunc!(...args); const retData = await EventFunc!(...args);
complete = true;
resolve(retData); resolve(retData);
}); });
} }

View File

@@ -2,7 +2,7 @@ import path, { dirname } from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import fs from 'fs'; import fs from 'fs';
export const napcat_version = '2.2.7'; export const napcat_version = '2.2.8';
export class NapCatPathWrapper { export class NapCatPathWrapper {
binaryPath: string; binaryPath: string;

View File

@@ -53,7 +53,7 @@ export abstract class ConfigBase<T> {
} }
save(newConfigData: T = this.configData as T) { save(newConfigData: T = this.configData) {
const logger = this.coreContext.context.logger; const logger = this.coreContext.context.logger;
const selfInfo = this.coreContext.selfInfo; const selfInfo = this.coreContext.selfInfo;
this.configData = newConfigData; this.configData = newConfigData;

View File

@@ -46,7 +46,7 @@ export class QQBasicInfoWrapper {
} }
requireMinNTQQBuild(buildStr: string) { requireMinNTQQBuild(buildStr: string) {
const currentBuild = parseInt(this.getQQBuildStr() || '0'); const currentBuild = +(this.getQQBuildStr() ?? '0');
if (currentBuild == 0) throw new Error('QQBuildStr获取失败'); if (currentBuild == 0) throw new Error('QQBuildStr获取失败');
return currentBuild >= parseInt(buildStr); return currentBuild >= parseInt(buildStr);
} }
@@ -77,5 +77,3 @@ export class QQBasicInfoWrapper {
return { appid: systemPlatform === 'linux' ? '537240795' : '537240709', qua: this.getQUAInternal() }; return { appid: systemPlatform === 'linux' ? '537240795' : '537240709', qua: this.getQUAInternal() };
} }
} }
export let QQBasicInfo: QQBasicInfoWrapper | undefined;

View File

@@ -4,6 +4,7 @@ import crypto, { randomUUID } from 'crypto';
import util from 'util'; import util from 'util';
import path from 'node:path'; import path from 'node:path';
import * as fileType from 'file-type'; import * as fileType from 'file-type';
import { solveAsyncProblem, solveProblem } from './helper';
export function isGIF(path: string) { export function isGIF(path: string) {
const buffer = Buffer.alloc(4); const buffer = Buffer.alloc(4);
@@ -185,25 +186,28 @@ export enum FileUriType {
} }
export async function checkUriType(Uri: string) { export async function checkUriType(Uri: string) {
//先判断是否是本地文件
try { const LocalFileRet = await solveProblem((uri: string) => {
if (fs.existsSync(Uri)) return { Uri: Uri, Type: FileUriType.Local }; if (fs.existsSync(uri)) {
} catch (error) { return { Uri: uri, Type: FileUriType.Local };
} }
try { return undefined;
}, Uri);
if (LocalFileRet) return LocalFileRet;
const OtherFileRet = await solveProblem((uri: string) => {
//再判断是否是Http //再判断是否是Http
if (Uri.startsWith('http://') || Uri.startsWith('https://')) { if (uri.startsWith('http://') || uri.startsWith('https://')) {
return { Uri: Uri, Type: FileUriType.Remote }; return { Uri: uri, Type: FileUriType.Remote };
} }
//再判断是否是Base64 //再判断是否是Base64
if (Uri.startsWith('base64://')) { if (uri.startsWith('base64://')) {
return { Uri: Uri, Type: FileUriType.Base64 }; return { Uri: uri, Type: FileUriType.Base64 };
} }
if (Uri.startsWith('file://')) { if (uri.startsWith('file://')) {
let pathname: string;
let filePath: string; let filePath: string;
// await fs.copyFile(url.pathname, filePath); // await fs.copyFile(url.pathname, filePath);
pathname = decodeURIComponent(new URL(Uri).pathname); const pathname = decodeURIComponent(new URL(uri).pathname);
if (process.platform === 'win32') { if (process.platform === 'win32') {
filePath = pathname.slice(1); filePath = pathname.slice(1);
} else { } else {
@@ -211,8 +215,9 @@ export async function checkUriType(Uri: string) {
} }
return { Uri: filePath, Type: FileUriType.Local }; return { Uri: filePath, Type: FileUriType.Local };
} }
} catch (error) { }, Uri);
} if (OtherFileRet) return OtherFileRet;
return { Uri: Uri, Type: FileUriType.Unknown }; return { Uri: Uri, Type: FileUriType.Unknown };
} }

View File

@@ -3,8 +3,28 @@ import fs from 'fs';
import os from 'node:os'; import os from 'node:os';
import { QQLevel } from '@/core'; import { QQLevel } from '@/core';
//下面这个类是用于将uid+msgid合并的类 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) => {
try {
const result = func(...args);
resolve(result);
} catch (e) {
resolve(undefined);
}
});
}
export async function solveAsyncProblem<T extends (...args: any[]) => Promise<any>>(func: T, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>> | undefined> {
return new Promise<Awaited<ReturnType<T>> | undefined>(async (resolve) => {
try {
const result = await func(...args);
resolve(result);
} catch (e) {
resolve(undefined);
}
});
}
//下面这个类是用于将uid+msgid合并的类
export class UUIDConverter { export class UUIDConverter {
static encode(highStr: string, lowStr: string): string { static encode(highStr: string, lowStr: string): string {
const high = BigInt(highStr); const high = BigInt(highStr);

View File

@@ -3,7 +3,6 @@ import { LogWrapper } from './log';
export function proxyHandlerOf(logger: LogWrapper) { export function proxyHandlerOf(logger: LogWrapper) {
return { return {
get(target: any, prop: any, receiver: any) { get(target: any, prop: any, receiver: any) {
// console.log('get', prop, typeof target[prop]);
if (typeof target[prop] === 'undefined') { if (typeof target[prop] === 'undefined') {
// 如果方法不存在返回一个函数这个函数调用existentMethod // 如果方法不存在返回一个函数这个函数调用existentMethod
return (..._args: unknown[]) => { return (..._args: unknown[]) => {

View File

@@ -74,9 +74,14 @@ export class NTQQFriendApi {
return this.context.session.getBuddyService().clearBuddyReqUnreadCnt(); return this.context.session.getBuddyService().clearBuddyReqUnreadCnt();
} }
async getBuddyReq() { async getBuddyReq() {
const [, ret] = await this.core.eventWrapper.CallNormalEventV2 const [, ret] = await this.core.eventWrapper.CallNormalEventV2<
<NodeIKernelBuddyService['getBuddyReq'], NodeIKernelBuddyListener['onBuddyReqChange']> NodeIKernelBuddyService['getBuddyReq'],
('NodeIKernelBuddyService/getBuddyReq', 'NodeIKernelBuddyListener/onBuddyReqChange', 1, 5000); NodeIKernelBuddyListener['onBuddyReqChange']
>(
'NodeIKernelBuddyService/getBuddyReq',
'NodeIKernelBuddyListener/onBuddyReqChange',
1,
5000);
return ret; return ret;
} }

View File

@@ -14,7 +14,7 @@ import {
NodeIKernelGroupListener, NodeIKernelGroupListener,
NodeIKernelGroupService, NodeIKernelGroupService,
} from '@/core'; } from '@/core';
import { isNumeric, runAllWithTimeout } from '@/common/utils/helper'; import { isNumeric, runAllWithTimeout, sleep } from '@/common/utils/helper';
export class NTQQGroupApi { export class NTQQGroupApi {
context: InstanceContext; context: InstanceContext;
@@ -25,7 +25,9 @@ export class NTQQGroupApi {
constructor(context: InstanceContext, core: NapCatCore) { constructor(context: InstanceContext, core: NapCatCore) {
this.context = context; this.context = context;
this.core = core; this.core = core;
this.initCache().then().catch(context.logger.logError); sleep(1000).then(() => {
this.initCache().then().catch(context.logger.logError);
});
} }
async initCache() { async initCache() {
this.groups = await this.getGroups(); this.groups = await this.getGroups();
@@ -44,12 +46,12 @@ export class NTQQGroupApi {
type ListenerType = NodeIKernelGroupListener['onGroupListUpdate']; type ListenerType = NodeIKernelGroupListener['onGroupListUpdate'];
const [_retData, _updateType, groupList] = await this.core.eventWrapper.CallNormalEvent<(force: boolean) => Promise<any>, ListenerType> const [_retData, _updateType, groupList] = await this.core.eventWrapper.CallNormalEvent<(force: boolean) => Promise<any>, ListenerType>
( (
'NodeIKernelGroupService/getGroupList', 'NodeIKernelGroupService/getGroupList',
'NodeIKernelGroupListener/onGroupListUpdate', 'NodeIKernelGroupListener/onGroupListUpdate',
1, 1,
5000, 5000,
() => true, () => true,
forced, forced,
); );
return groupList; return groupList;
} }
@@ -229,7 +231,7 @@ export class NTQQGroupApi {
return this.context.session.getGroupService().deleteGroupBulletin(GroupCode, _Pskey, feedId); return this.context.session.getGroupService().deleteGroupBulletin(GroupCode, _Pskey, feedId);
} }
async quitGroupV2(GroupCode: string, needDeleteLocalMsg: boolean) { async quitGroupV2(GroupCode: string, needDeleteLocalMsg: boolean) {
let param = { const param = {
groupCode: GroupCode, groupCode: GroupCode,
needDeleteLocalMsg: needDeleteLocalMsg needDeleteLocalMsg: needDeleteLocalMsg
}; };
@@ -256,31 +258,28 @@ export class NTQQGroupApi {
async getSingleScreenNotifies(num: number) { async getSingleScreenNotifies(num: number) {
const [_retData, _doubt, _seq, notifies] = await this.core.eventWrapper.CallNormalEvent<(arg1: boolean, arg2: string, arg3: number) => Promise<any>, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void> const [_retData, _doubt, _seq, notifies] = await this.core.eventWrapper.CallNormalEvent<(arg1: boolean, arg2: string, arg3: number) => Promise<any>, (doubt: boolean, seq: string, notifies: GroupNotify[]) => void>
( (
'NodeIKernelGroupService/getSingleScreenNotifies', 'NodeIKernelGroupService/getSingleScreenNotifies',
'NodeIKernelGroupListener/onGroupSingleScreenNotifies', 'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
1, 1,
5000, 5000,
() => true, () => true,
false, false,
'', '',
num, num,
); );
return notifies; return notifies;
} }
async getGroupMemberV2(GroupCode: string, uid: string, forced = false) { async getGroupMemberV2(GroupCode: string, uid: string, forced = false) {
//type ListenerType = NodeIKernelGroupListener['onMemberInfoChange'];
type EventType = NodeIKernelGroupService['getMemberInfo']; type EventType = NodeIKernelGroupService['getMemberInfo'];
// NTEventDispatch.CreatListenerFunction('NodeIKernelGroupListener/onGroupMemberInfoUpdate',
//return napCatCore.session.getGroupService().getMemberInfo(GroupCode, [uid], forced);
const Listener = this.core.eventWrapper.RegisterListen<(params: any) => void> const Listener = this.core.eventWrapper.RegisterListen<(params: any) => void>
( (
'NodeIKernelGroupListener/onMemberInfoChange', 'NodeIKernelGroupListener/onMemberInfoChange',
1, 1,
forced ? 5000 : 250, forced ? 5000 : 250,
(params) => { (params) => {
return params === GroupCode; return params === GroupCode;
}, },
); );
const EventFunc = this.core.eventWrapper.createEventFunction<EventType>('NodeIKernelGroupService/getMemberInfo'); const EventFunc = this.core.eventWrapper.createEventFunction<EventType>('NodeIKernelGroupService/getMemberInfo');
const retData = await EventFunc!(GroupCode, [uid], forced); const retData = await EventFunc!(GroupCode, [uid], forced);
@@ -294,20 +293,6 @@ export class NTQQGroupApi {
member = members.get(uid); member = members.get(uid);
} }
return member; return member;
// 原本的方法: (no_cache 下效率很高, cache 下效率一致)
// const [, , , _members] = await this.core.eventWrapper.CallNormalEvent<EventType, ListenerType>
// (
// 'NodeIKernelGroupService/getMemberInfo',
// 'NodeIKernelGroupListener/onMemberInfoChange',
// 1,
// 5000,
// (groupCode: string, changeType: number, members: Map<string, GroupMember>) => {
// return groupCode == GroupCode && members.has(uid);
// },
// GroupCode, [uid], forced,
// );
// return _members.get(uid);
} }
async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> { async getGroupMembers(groupQQ: string, num = 3000): Promise<Map<string, GroupMember>> {
@@ -315,7 +300,7 @@ export class NTQQGroupApi {
const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow'); const sceneId = groupService.createMemberListScene(groupQQ, 'groupMemberList_MainWindow');
const result = await groupService.getNextMemberList(sceneId!, undefined, num); const result = await groupService.getNextMemberList(sceneId!, undefined, num);
if (result.errCode !== 0) { if (result.errCode !== 0) {
throw ('获取群成员列表出错,' + result.errMsg); throw new Error('获取群成员列表出错,' + result.errMsg);
} }
this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values())); this.context.logger.logDebug(`获取群(${groupQQ})成员列表结果:`, `members: ${result.result.infos.size}`); //, Array.from(result.result.infos.values()));
@@ -349,7 +334,7 @@ export class NTQQGroupApi {
'NodeIKernelGroupService/getGroupRecommendContactArkJson', 'NodeIKernelGroupService/getGroupRecommendContactArkJson',
5000, 5000,
GroupCode, GroupCode,
); );
return ret.arkJson; return ret.arkJson;
} }

View File

@@ -3,6 +3,7 @@ import { NodeIKernelProfileListener } from '@/core/listeners';
import { RequestUtil } from '@/common/utils/request'; import { RequestUtil } from '@/common/utils/request';
import { NodeIKernelProfileService, ProfileBizType, UserDetailSource } from '@/core/services'; import { NodeIKernelProfileService, ProfileBizType, UserDetailSource } from '@/core/services';
import { InstanceContext, NapCatCore } from '..'; import { InstanceContext, NapCatCore } from '..';
import { solveAsyncProblem } from '@/common/utils/helper';
export class NTQQUserApi { export class NTQQUserApi {
context: InstanceContext; context: InstanceContext;
@@ -128,12 +129,9 @@ export class NTQQUserApi {
} }
async getUserDetailInfo(uid: string): Promise<User> { async getUserDetailInfo(uid: string): Promise<User> {
try { const retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB));
const retUser = await this.fetchUserDetailInfo(uid, UserDetailSource.KDB); if (retUser && retUser.uin !== '0') {
if (retUser.uin !== '0') { return retUser;
return retUser;
}
} catch (e) {
} }
this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.'); this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.');
return this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER); return this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER);

View File

@@ -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) {
@@ -43,11 +43,11 @@ export class NTQQWebApi {
page_start, page_start,
page_limit: '20', 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 +63,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 +83,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 +123,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 +162,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) });

View File

@@ -848,41 +848,6 @@ export interface MultiForwardMsgElement {
resId: string; resId: string;
fileName: string; fileName: string;
} }
export enum NTSubMsgType {
KMSGSUBTYPEARKGROUPANNOUNCE = 3,
KMSGSUBTYPEARKGROUPANNOUNCECONFIRMREQUIRED = 4,
KMSGSUBTYPEARKGROUPGIFTATME = 5,
KMSGSUBTYPEARKGROUPTASKATALL = 6,
KMSGSUBTYPEARKMULTIMSG = 7,
KMSGSUBTYPEARKNORMAL = 0,
KMSGSUBTYPEARKTENCENTDOCFROMMINIAPP = 1,
KMSGSUBTYPEARKTENCENTDOCFROMPLUSPANEL = 2,
KMSGSUBTYPEEMOTICON = 15,
KMSGSUBTYPEFILEAPP = 11,
KMSGSUBTYPEFILEAUDIO = 3,
KMSGSUBTYPEFILEDOC = 4,
KMSGSUBTYPEFILEEXCEL = 6,
KMSGSUBTYPEFILEFOLDER = 13,
KMSGSUBTYPEFILEHTML = 10,
KMSGSUBTYPEFILEIPA = 14,
KMSGSUBTYPEFILENORMAL = 0,
KMSGSUBTYPEFILEPDF = 7,
KMSGSUBTYPEFILEPIC = 1,
KMSGSUBTYPEFILEPPT = 5,
KMSGSUBTYPEFILEPSD = 12,
KMSGSUBTYPEFILETXT = 8,
KMSGSUBTYPEFILEVIDEO = 2,
KMSGSUBTYPEFILEZIP = 9,
KMSGSUBTYPELINK = 5,
KMSGSUBTYPEMARKETFACE = 1,
KMSGSUBTYPEMIXEMOTICON = 7,
KMSGSUBTYPEMIXFACE = 3,
KMSGSUBTYPEMIXMARKETFACE = 2,
KMSGSUBTYPEMIXPIC = 1,
KMSGSUBTYPEMIXREPLY = 4,
KMSGSUBTYPEMIXTEXT = 0,
KMSGSUBTYPETENCENTDOC = 6
}
export enum SendStatusType { export enum SendStatusType {
KSEND_STATUS_FAILED = 0, KSEND_STATUS_FAILED = 0,
KSEND_STATUS_SENDING = 1, KSEND_STATUS_SENDING = 1,
@@ -914,7 +879,7 @@ export interface RawMessage {
msgType: NTMsgType; msgType: NTMsgType;
subMsgType: NTSubMsgType; subMsgType: number;
senderUid: string; senderUid: string;

View File

@@ -100,7 +100,7 @@ export interface NodeIKernelGroupService {
uid: string, uid: string,
index: number//0 index: number//0
}>, }>,
infos: {}, infos: unknown,
finish: true, finish: true,
hasRobot: false hasRobot: false
} }

View File

@@ -37,7 +37,7 @@ export interface NodeIKernelMsgService {
recallMsg(peer: Peer, msgIds: string[]): Promise<GeneralCallResult>; recallMsg(peer: Peer, msgIds: string[]): Promise<GeneralCallResult>;
addKernelMsgImportToolListener(arg: Object): unknown; addKernelMsgImportToolListener(arg: unknown): unknown;
removeKernelMsgListener(args: unknown): unknown; removeKernelMsgListener(args: unknown): unknown;
@@ -51,7 +51,7 @@ export interface NodeIKernelMsgService {
getOnLineDev(): void; getOnLineDev(): void;
kickOffLine(DevInfo: Object): unknown; kickOffLine(DevInfo: unknown): unknown;
setStatus(args: { status: number, extStatus: number, batteryStatus: number }): Promise<GeneralCallResult>; setStatus(args: { status: number, extStatus: number, batteryStatus: number }): Promise<GeneralCallResult>;
@@ -80,11 +80,11 @@ export interface NodeIKernelMsgService {
// this.voipToken = bArr2; // this.voipToken = bArr2;
// this.profileId = str; // this.profileId = str;
setToken(arg: Object): unknown; setToken(arg: unknown): unknown;
switchForeGround(): unknown; switchForeGround(): unknown;
switchBackGround(arg: Object): unknown; switchBackGround(arg: unknown): unknown;
//hex //hex
setTokenForMqq(token: string): unknown; setTokenForMqq(token: string): unknown;
@@ -384,7 +384,7 @@ export interface NodeIKernelMsgService {
getFileThumbSavePath(...args: unknown[]): unknown; getFileThumbSavePath(...args: unknown[]): unknown;
//猜测居多 //猜测居多
translatePtt2Text(MsgId: string, Peer: {}, MsgElement: {}): unknown; translatePtt2Text(MsgId: string, Peer: Peer, MsgElement: unknown): unknown;
setPttPlayedState(...args: unknown[]): unknown; setPttPlayedState(...args: unknown[]): unknown;
@@ -668,7 +668,7 @@ export interface NodeIKernelMsgService {
recordEmoji(...args: unknown[]): unknown; recordEmoji(...args: unknown[]): unknown;
fetchGetHitEmotionsByWord(args: Object): Promise<unknown>;//表情推荐? fetchGetHitEmotionsByWord(args: unknown): Promise<unknown>;//表情推荐?
deleteAllRoamMsgs(...args: unknown[]): unknown;//漫游消息? deleteAllRoamMsgs(...args: unknown[]): unknown;//漫游消息?

View File

@@ -1,4 +1,4 @@
import { forceFetchClientKeyRetType } from './common'; import { ForceFetchClientKeyRetType } from './common';
export interface NodeIKernelTicketService { export interface NodeIKernelTicketService {
@@ -6,7 +6,7 @@ export interface NodeIKernelTicketService {
removeKernelTicketListener(listenerId: unknown): void; removeKernelTicketListener(listenerId: unknown): void;
forceFetchClientKey(arg: string): Promise<forceFetchClientKeyRetType>; forceFetchClientKey(arg: string): Promise<ForceFetchClientKeyRetType>;
isNull(): boolean; isNull(): boolean;
} }

View File

@@ -8,7 +8,7 @@ export interface GeneralCallResult {
errMsg: string errMsg: string
} }
export interface forceFetchClientKeyRetType extends GeneralCallResult { export interface ForceFetchClientKeyRetType extends GeneralCallResult {
url: string; url: string;
keyIndex: string; keyIndex: string;
clientKey: string; clientKey: string;

View File

@@ -69,9 +69,9 @@ export interface NodeQQNTWrapperUtil {
genFileShaAndMd5Hex(path: string, unknown: number): unknown; //可能是错的 genFileShaAndMd5Hex(path: string, unknown: number): unknown; //可能是错的
setTraceInfo(unknown: Object): unknown; setTraceInfo(unknown: unknown): unknown;
encodeOffLine(unknown: Object): unknown; encodeOffLine(unknown: unknown): unknown;
decodeOffLine(arg: string): unknown; //可能是错的 传递hex decodeOffLine(arg: string): unknown; //可能是错的 传递hex
@@ -89,7 +89,7 @@ export interface NodeQQNTWrapperUtil {
runProcessArgs(arg0: string, arg1: { [key: string]: string }, arg2: boolean): unknown; runProcessArgs(arg0: string, arg1: { [key: string]: string }, arg2: boolean): unknown;
calcThumbSize(arg0: number, arg1: number, arg2: Object): unknown; calcThumbSize(arg0: number, arg1: number, arg2: unknown): unknown;
fullWordToHalfWord(arg0: string): unknown; fullWordToHalfWord(arg0: string): unknown;

View File

@@ -90,7 +90,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
return res; return res;
} }
} catch { } catch {
this.CoreContext.context.logger.logDebug('GetFileBase Mode - 1 Error');
} }
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems; const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;

View File

@@ -1,10 +1,8 @@
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { OB11ForwardMessage, OB11Message, OB11MessageData } from '../../types'; import { OB11ForwardMessage, OB11Message, OB11MessageData } from '@/onebot';
import { OB11Constructor } from '@/onebot/helper/converter';
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/utils/MessageUnique'; import { MessageUnique } from '@/common/utils/MessageUnique';
import { RawNTMsg2Onebot } from '@/onebot/helper';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -41,7 +39,8 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
} }
const msgList = data.msgList; const msgList = data.msgList;
const messages = (await Promise.all(msgList.map(async msg => { const messages = (await Promise.all(msgList.map(async msg => {
const resMsg = await RawNTMsg2Onebot(this.CoreContext, this.OneBotContext, msg); const resMsg = await this.OneBotContext.apiContext.MsgApi
.parseMessage(msg);
if (!resMsg) return; if (!resMsg) return;
resMsg.message_id = MessageUnique.createMsg({ resMsg.message_id = MessageUnique.createMsg({
guildId: '', guildId: '',

View File

@@ -1,11 +1,9 @@
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { OB11Message } from '../../types'; import { OB11Message } from '@/onebot';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { ChatType, RawMessage } from '@/core/entities'; import { ChatType, RawMessage } from '@/core/entities';
import { OB11Constructor } from '@/onebot/helper/converter';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique'; import { MessageUnique } from '@/common/utils/MessageUnique';
import { RawNTMsg2Onebot } from '@/onebot/helper';
interface Response { interface Response {
messages: OB11Message[]; messages: OB11Message[];
@@ -54,7 +52,9 @@ export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId); msg.id = MessageUnique.createMsg({ guildId: '', chatType: msg.chatType, peerUid: msg.peerUid }, msg.msgId);
})); }));
//转换消息 //转换消息
const ob11MsgList = (await Promise.all(msgList.map(msg => RawNTMsg2Onebot(this.CoreContext, this.OneBotContext, msg)))).filter(msg => !!msg); const ob11MsgList = (await Promise.all(
msgList.map(msg => this.OneBotContext.apiContext.MsgApi.parseMessage(msg)))
).filter(msg => msg !== undefined);
return { 'messages': ob11MsgList }; return { 'messages': ob11MsgList };
} }
} }

View File

@@ -1,11 +1,9 @@
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { OB11Message } from '../../types'; import { OB11Message } from '@/onebot';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { ChatType, Peer, RawMessage } from '@/core/entities'; import { ChatType, Peer, RawMessage } from '@/core/entities';
import { OB11Constructor } from '@/onebot/helper/converter';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique'; import { MessageUnique } from '@/common/utils/MessageUnique';
import { RawNTMsg2Onebot } from '@/onebot/helper';
interface Response { interface Response {
messages: OB11Message[]; messages: OB11Message[];
@@ -49,7 +47,9 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
})); }));
//转换消息 //转换消息
const ob11MsgList = (await Promise.all(msgList.map(msg => RawNTMsg2Onebot(this.CoreContext, this.OneBotContext, msg)))).filter(msg => !!msg); const ob11MsgList = (await Promise.all(
msgList.map(msg => this.OneBotContext.apiContext.MsgApi.parseMessage(msg)))
).filter(msg => msg !== undefined);
return { 'messages': ob11MsgList }; return { 'messages': ob11MsgList };
} }
} }

View File

@@ -24,7 +24,7 @@ export class SetQQProfile extends BaseAction<Payload, any | null> {
const OldProfile = await NTQQUserApi.getUserDetailInfo(self.uid); const OldProfile = await NTQQUserApi.getUserDetailInfo(self.uid);
const ret = await NTQQUserApi.modifySelfProfile({ const ret = await NTQQUserApi.modifySelfProfile({
nick: payload.nickname, nick: payload.nickname,
longNick: payload?.personal_note ?? OldProfile?.longNick!, longNick: (payload?.personal_note ?? OldProfile?.longNick) || '',
sex: parseInt(payload?.sex ? payload?.sex.toString() : OldProfile?.sex!.toString()), sex: parseInt(payload?.sex ? payload?.sex.toString() : OldProfile?.sex!.toString()),
birthday: { birthday_year: OldProfile?.birthday_year!.toString(), birthday_month: OldProfile?.birthday_month!.toString(), birthday_day: OldProfile?.birthday_day!.toString() }, birthday: { birthday_year: OldProfile?.birthday_year!.toString(), birthday_month: OldProfile?.birthday_month!.toString(), birthday_day: OldProfile?.birthday_day!.toString() },
location: undefined, location: undefined,

View File

@@ -26,12 +26,12 @@ class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi; const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const isNocache = typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache; const isNocache = typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache;
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw (`Uin2Uid Error ${payload.user_id}不存在`); if (!uid) throw new Error (`Uin2Uid Error ${payload.user_id}不存在`);
const [member, info] = await Promise.allSettled([ const [member, info] = await Promise.allSettled([
NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache), NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache),
NTQQUserApi.getUserDetailInfo(uid), NTQQUserApi.getUserDetailInfo(uid),
]); ]);
if (member.status !== 'fulfilled') throw (`群(${payload.group_id})成员${payload.user_id}不存在 ${member.reason}`); if (member.status !== 'fulfilled') throw new Error (`群(${payload.group_id})成员${payload.user_id}不存在 ${member.reason}`);
if (info.status === 'fulfilled') { if (info.status === 'fulfilled') {
this.CoreContext.context.logger.logDebug("群成员详细信息结果", info.value); this.CoreContext.context.logger.logDebug("群成员详细信息结果", info.value);
Object.assign(member, info.value); Object.assign(member, info.value);

View File

@@ -1,10 +1,8 @@
import { OB11Message } from '../../types'; import { OB11Message } from '@/onebot';
import { OB11Constructor } from '@/onebot/helper/converter';
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/utils/MessageUnique'; import { MessageUnique } from '@/common/utils/MessageUnique';
import { RawNTMsg2Onebot } from '@/onebot/helper';
export type ReturnDataType = OB11Message export type ReturnDataType = OB11Message
@@ -32,19 +30,20 @@ class GetMsg extends BaseAction<Payload, OB11Message> {
const MsgShortId = MessageUnique.getShortIdByMsgId(payload.message_id.toString()); const MsgShortId = MessageUnique.getShortIdByMsgId(payload.message_id.toString());
const msgIdWithPeer = MessageUnique.getMsgIdAndPeerByShortId(MsgShortId || parseInt(payload.message_id.toString())); const msgIdWithPeer = MessageUnique.getMsgIdAndPeerByShortId(MsgShortId || parseInt(payload.message_id.toString()));
if (!msgIdWithPeer) { if (!msgIdWithPeer) {
throw ('消息不存在'); throw new Error('消息不存在');
} }
const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType }; const peer = { guildId: '', peerUid: msgIdWithPeer?.Peer.peerUid, chatType: msgIdWithPeer.Peer.chatType };
const msg = await NTQQMsgApi.getMsgsByMsgId( const msg = await NTQQMsgApi.getMsgsByMsgId(
peer, peer,
[msgIdWithPeer?.MsgId || payload.message_id.toString()]); [msgIdWithPeer?.MsgId || payload.message_id.toString()]);
const retMsg = await RawNTMsg2Onebot(this.CoreContext, this.OneBotContext, msg.msgList[0], 'array'); const retMsg = await this.OneBotContext.apiContext.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.createMsg(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) {
// ignored
} }
return retMsg; return retMsg;
} }

View File

@@ -36,7 +36,7 @@ class MarkMsgAsRead extends BaseAction<PlayloadType, null> {
// 调用API // 调用API
const ret = await NTQQMsgApi.setMsgRead(await this.getPeer(payload)); const ret = await NTQQMsgApi.setMsgRead(await this.getPeer(payload));
if (ret.result != 0) { if (ret.result != 0) {
throw ('设置已读失败,' + ret.errMsg); throw new Error('设置已读失败,' + ret.errMsg);
} }
return null; return null;
} }

View File

@@ -68,7 +68,7 @@ const _handlers: {
} }
const uid = await NTQQUserApi.getUidByUinV2(`${atQQ}`); const uid = await NTQQUserApi.getUidByUinV2(`${atQQ}`);
if (!uid) throw new Error('Get Uid Error'); if (!uid) throw new Error('Get Uid Error');
let info = await NTQQUserApi.getUserDetailInfo(uid); const info = await NTQQUserApi.getUserDetailInfo(uid);
return SendMsgElementConstructor.at(coreContext, atQQ, uid, AtType.atUser, info.nick || ''); return SendMsgElementConstructor.at(coreContext, atQQ, uid, AtType.atUser, info.nick || '');
}, },
[OB11MessageDataType.reply]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { id } }) => { [OB11MessageDataType.reply]: async (coreContext, obContext: NapCatOneBot11Adapter, { data: { id } }) => {
@@ -171,7 +171,7 @@ const _handlers: {
} else { } else {
postData = data; postData = data;
} }
// Mlikiowa V2.2.7 Refactor Todo // Mlikiowa V2.2.8 Refactor Todo
const signUrl = obContext.configLoader.configData.musicSignUrl; const signUrl = obContext.configLoader.configData.musicSignUrl;
if (!signUrl) { if (!signUrl) {
if (data.type === 'qq') { if (data.type === 'qq') {

View File

@@ -110,18 +110,21 @@ export async function handleForwardNode(coreContext: NapCatCore, obContext: NapC
nodeMsgIds = nodeMsgArray.map(msg => msg.msgId); nodeMsgIds = nodeMsgArray.map(msg => msg.msgId);
let retMsgIds: string[] = []; let retMsgIds: string[] = [];
if (needSendSelf) { if (needSendSelf) {
for (const [index, msg] of nodeMsgArray.entries()) { for (const [, msg] of nodeMsgArray.entries()) {
if (msg.peerUid === coreContext.selfInfo.uid) continue; if (msg.peerUid === coreContext.selfInfo.uid){
retMsgIds.push(msg.msgId);
continue;
}
const ClonedMsg = await cloneMsg(coreContext, msg); const ClonedMsg = await cloneMsg(coreContext, msg);
if (ClonedMsg) retMsgIds.push(ClonedMsg.msgId); if (ClonedMsg) retMsgIds.push(ClonedMsg.msgId);
} }
} else { } else {
retMsgIds = nodeMsgIds; retMsgIds = nodeMsgIds;
} }
if (nodeMsgIds.length === 0) throw Error('转发消息失败,生成节点为空'); if (retMsgIds.length === 0) throw Error('转发消息失败,生成节点为空');
try { try {
logger.logDebug('开发转发', srcPeer, destPeer, nodeMsgIds); logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, nodeMsgIds); return await NTQQMsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
} catch (e) { } catch (e) {
logger.logError('forward failed', e); logger.logError('forward failed', e);
return null; return null;

View File

@@ -40,7 +40,7 @@ export async function sendMsg(coreContext: NapCatCore, peer: Peer, sendElements:
const NTQQMsgApi = coreContext.apis.MsgApi; const NTQQMsgApi = coreContext.apis.MsgApi;
const logger = coreContext.context.logger; const logger = coreContext.context.logger;
if (!sendElements.length) { if (!sendElements.length) {
throw ('消息体无法解析, 请检查是否发送了不支持的消息类型'); throw new Error ('消息体无法解析, 请检查是否发送了不支持的消息类型');
} }
let totalSize = 0; let totalSize = 0;
let timeout = 10000; let timeout = 10000;
@@ -158,7 +158,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (payload.user_id && payload.message_type !== 'group') { if (payload.user_id && payload.message_type !== 'group') {
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString()); const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
const isBuddy = await NTQQFriendApi.isBuddy(uid!); const isBuddy = await NTQQFriendApi.isBuddy(uid!);
if (!isBuddy) { } //if (!isBuddy) { }
} }
return { valid: true }; return { valid: true };
} }

View File

@@ -1,8 +1,6 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { OB11Constructor } from '@/onebot/helper/converter';
import { RawNTMsg2Onebot } from '@/onebot/helper';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -21,11 +19,11 @@ export default class GetRecentContact extends BaseAction<Payload, any> {
const NTQQUserApi = this.CoreContext.apis.UserApi; const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQMsgApi = this.CoreContext.apis.MsgApi; const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const ret = await NTQQUserApi.getRecentContactListSnapShot(parseInt((payload.count || 10).toString())); const ret = await NTQQUserApi.getRecentContactListSnapShot(parseInt((payload.count || 10).toString()));
const data = await Promise.all(ret.info.changedList.map(async (t) => { return await Promise.all(ret.info.changedList.map(async (t) => {
const FastMsg = await NTQQMsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]); const FastMsg = await NTQQMsgApi.getMsgsByMsgId({ chatType: t.chatType, peerUid: t.peerUid }, [t.msgId]);
if (FastMsg.msgList.length > 0) { if (FastMsg.msgList.length > 0) {
//扩展ret.info.changedList //扩展ret.info.changedList
const lastestMsg = await RawNTMsg2Onebot(this.CoreContext, this.OneBotContext,FastMsg.msgList[0], 'array'); const lastestMsg = await this.OneBotContext.apiContext.MsgApi.parseMessage(FastMsg.msgList[0], 'array');
return { return {
lastestMsg: lastestMsg, lastestMsg: lastestMsg,
peerUin: t.peerUin, peerUin: t.peerUin,
@@ -49,6 +47,5 @@ export default class GetRecentContact extends BaseAction<Payload, any> {
peerName: t.peerName, peerName: t.peerName,
}; };
})); }));
return data;
} }
} }

View File

@@ -75,7 +75,7 @@ export class OneBotGroupApi {
const NTQQGroupApi = this.coreContext.apis.GroupApi; const NTQQGroupApi = this.coreContext.apis.GroupApi;
const groupElement = grayTipElement?.groupElement; const groupElement = grayTipElement?.groupElement;
if (!groupElement) return undefined; if (!groupElement) return undefined;
const member = await NTQQGroupApi.getGroupMember(GroupCode, groupElement.memberUid); const member = await NTQQGroupApi.getGroupMemberV2(GroupCode, groupElement.memberUid);
const memberUin = member?.uin; const memberUin = member?.uin;
const adminMember = await NTQQGroupApi.getGroupMember(GroupCode, groupElement.adminUid); const adminMember = await NTQQGroupApi.getGroupMember(GroupCode, groupElement.adminUid);
if (memberUin) { if (memberUin) {

View File

@@ -1,8 +1,10 @@
import { UUIDConverter } from '@/common/utils/helper'; import { UUIDConverter } from '@/common/utils/helper';
import { MessageUnique } from '@/common/utils/MessageUnique'; import { MessageUnique } from '@/common/utils/MessageUnique';
import { AtType, FaceIndex, MessageElement, NapCatCore, RawMessage } from '@/core'; import { AtType, ChatType, FaceIndex, MessageElement, NapCatCore, RawMessage } from '@/core';
import { NapCatOneBot11Adapter, OB11MessageData, OB11MessageDataType } from '@/onebot'; import { NapCatOneBot11Adapter, OB11Message, OB11MessageData, OB11MessageDataType } from '@/onebot';
import { RawNTMsg2Onebot } from '../helper'; import { OB11Constructor } from '../helper';
import { EventType } from '@/onebot/event/OB11BaseEvent';
import { encodeCQCode } from '@/onebot/helper/cqcode';
export class OneBotMsgApi { export class OneBotMsgApi {
obContext: NapCatOneBot11Adapter; obContext: NapCatOneBot11Adapter;
@@ -12,11 +14,121 @@ export class OneBotMsgApi {
this.obContext = obContext; this.obContext = obContext;
this.coreContext = coreContext; this.coreContext = coreContext;
} }
async parseMessage(
msg: RawMessage,
messagePostFormat: string = this.obContext.configLoader.configData.messagePostFormat
) {
if (msg.senderUin == "0" || msg.senderUin == "") return;
if (msg.peerUin == "0" || msg.peerUin == "") return;
//跳过空消息
const NTQQGroupApi = this.coreContext.apis.GroupApi;
const NTQQUserApi = this.coreContext.apis.UserApi;
const NTQQMsgApi = this.coreContext.apis.MsgApi;
const resMsg: OB11Message = {
self_id: parseInt(this.coreContext.selfInfo.uin),
user_id: parseInt(msg.senderUin!),
time: parseInt(msg.msgTime) || Date.now(),
message_id: msg.id!,
message_seq: msg.id!,
real_id: msg.id!,
message_type: msg.chatType == ChatType.KCHATTYPEGROUP ? 'group' : 'private',
sender: {
user_id: parseInt(msg.senderUin || '0'),
nickname: msg.sendNickName,
card: msg.sendMemberName || '',
},
raw_message: '',
font: 14,
sub_type: 'friend',
message: messagePostFormat === 'string' ? '' : [],
message_format: messagePostFormat === 'string' ? 'string' : 'array',
post_type: this.coreContext.selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE,
};
if (msg.chatType == ChatType.KCHATTYPEGROUP) {
resMsg.sub_type = 'normal'; // 这里go-cqhttp是group而onebot11标准是normal, 蛋疼
resMsg.group_id = parseInt(msg.peerUin);
let member = await NTQQGroupApi.getGroupMember(msg.peerUin, msg.senderUin);
if (!member) member = await NTQQGroupApi.getGroupMember(msg.peerUin, msg.senderUin);
if (member) {
resMsg.sender.role = OB11Constructor.groupMemberRole(member.role);
resMsg.sender.nickname = member.nick;
}
} else if (msg.chatType == ChatType.KCHATTYPEC2C) {
resMsg.sub_type = 'friend';
resMsg.sender.nickname = (await NTQQUserApi.getUserDetailInfo(msg.senderUid)).nick;
} else if (msg.chatType == ChatType.KCHATTYPETEMPC2CFROMGROUP) {
resMsg.sub_type = 'group';
const ret = await NTQQMsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, msg.senderUid);
if (ret.result === 0) {
resMsg.group_id = parseInt(ret.tmpChatInfo!.groupCode);
resMsg.sender.nickname = ret.tmpChatInfo!.fromNick;
} else {
resMsg.group_id = 284840486; //兜底数据
resMsg.sender.nickname = "临时会话";
}
}
for (const element of msg.elements) {
let message_data: OB11MessageData = {
data: {} as any,
type: 'unknown' as any,
};
if (element.textElement && element.textElement?.atType !== AtType.notAt) {
const textAtMsgData = await this.obContext.apiContext.MsgApi.parseTextElemntWithAt(msg, element);
if (textAtMsgData) message_data = textAtMsgData;
} else if (element.textElement) {
const textMsgData = await this.obContext.apiContext.MsgApi.parseTextElement(msg, element);
if (textMsgData) message_data = textMsgData;
} else if (element.replyElement) {
const replyMsgData = await this.obContext.apiContext.MsgApi.parseReplyElement(msg, element);
if (replyMsgData) message_data = replyMsgData;
} else if (element.picElement) {
const PicMsgData = await this.obContext.apiContext.MsgApi.parsePicElement(msg, element);
if (PicMsgData) message_data = PicMsgData;
} else if (element.fileElement) {
const FileMsgData = await this.obContext.apiContext.MsgApi.parseFileElement(msg, element);
if (FileMsgData) message_data = FileMsgData;
} else if (element.videoElement) {
const videoMsgData = await this.obContext.apiContext.MsgApi.parseVideoElement(msg, element);
if (videoMsgData) message_data = videoMsgData;
} else if (element.pttElement) {
const pttMsgData = await this.obContext.apiContext.MsgApi.parsePTTElement(msg, element);
if (pttMsgData) message_data = pttMsgData;
} else if (element.arkElement) {
const arkMsgData = await this.obContext.apiContext.MsgApi.parseArkElement(msg, element);
if (arkMsgData) message_data = arkMsgData;
} else if (element.faceElement) {
const faceMsgData = await this.obContext.apiContext.MsgApi.parseFaceElement(msg, element);
if (faceMsgData) message_data = faceMsgData;
} else if (element.marketFaceElement) {
const marketFaceMsgData = await this.obContext.apiContext.MsgApi.parseMarketFaceElement(msg, element);
if (marketFaceMsgData) message_data = marketFaceMsgData;
} else if (element.markdownElement) {
message_data['type'] = OB11MessageDataType.markdown;
message_data['data']['data'] = element.markdownElement.content;
} else if (element.multiForwardMsgElement) {
const multiForwardMsgData = await this.obContext.apiContext.MsgApi.parseMultForwardElement(msg, element, messagePostFormat);
if (multiForwardMsgData) message_data = multiForwardMsgData;
}
if ((message_data.type as string) !== 'unknown' && message_data.data) {
const cqCode = encodeCQCode(message_data);
if (messagePostFormat === 'string') {
(resMsg.message as string) += cqCode;
} else (resMsg.message as OB11MessageData[]).push(message_data);
resMsg.raw_message += cqCode;
}
}
resMsg.raw_message = resMsg.raw_message.trim();
return resMsg;
}
async parseFileElement(msg: RawMessage, element: MessageElement) { async parseFileElement(msg: RawMessage, element: MessageElement) {
const fileElement = element.fileElement; const fileElement = element.fileElement;
if (!fileElement) return undefined; if (!fileElement) return undefined;
const NTQQFileApi = this.coreContext.apis.FileApi; const NTQQFileApi = this.coreContext.apis.FileApi;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -46,12 +158,8 @@ export class OneBotMsgApi {
const textElement = element.textElement; const textElement = element.textElement;
if (!textElement) return undefined; if (!textElement) return undefined;
const NTQQUserApi = this.coreContext.apis.UserApi; const NTQQUserApi = this.coreContext.apis.UserApi;
let message_data: OB11MessageData = {
data: {} as any,
type: 'unknown' as any,
};
let qq: `${number}` | 'all'; let qq: `${number}` | 'all';
let name: string | undefined; // let name: string | undefined;
if (textElement.atType == AtType.atAll) { if (textElement.atType == AtType.atAll) {
qq = 'all'; qq = 'all';
} else { } else {
@@ -62,23 +170,22 @@ export class OneBotMsgApi {
} }
if (atQQ) { if (atQQ) {
qq = atQQ as `${number}`; qq = atQQ as `${number}`;
name = content.replace('@', ''); // name = content.replace('@', '');
} }
} }
message_data = { return {
type: OB11MessageDataType.at, type: OB11MessageDataType.at,
data: { data: {
qq: qq!, qq: qq!,
//name, // name,
}, },
}; };
return message_data;
} }
async parseTextElement(msg: RawMessage, element: MessageElement) { async parseTextElement(msg: RawMessage, element: MessageElement) {
const textElement = element.textElement; const textElement = element.textElement;
if (!textElement) return undefined; if (!textElement) return undefined;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -99,7 +206,7 @@ export class OneBotMsgApi {
const picElement = element.picElement; const picElement = element.picElement;
if (!picElement) return undefined; if (!picElement) return undefined;
const NTQQFileApi = this.coreContext.apis.FileApi; const NTQQFileApi = this.coreContext.apis.FileApi;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -121,7 +228,7 @@ export class OneBotMsgApi {
} }
async parseMarketFaceElement(msg: RawMessage, element: MessageElement) { async parseMarketFaceElement(msg: RawMessage, element: MessageElement) {
const NTQQFileApi = this.coreContext.apis.FileApi; const NTQQFileApi = this.coreContext.apis.FileApi;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -150,7 +257,7 @@ export class OneBotMsgApi {
const replyElement = element.replyElement; const replyElement = element.replyElement;
if (!replyElement) return undefined; if (!replyElement) return undefined;
const NTQQMsgApi = this.coreContext.apis.MsgApi; const NTQQMsgApi = this.coreContext.apis.MsgApi;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -201,7 +308,7 @@ export class OneBotMsgApi {
const videoElement = element.videoElement; const videoElement = element.videoElement;
if (!videoElement) return undefined; if (!videoElement) return undefined;
const NTQQFileApi = this.coreContext.apis.FileApi; const NTQQFileApi = this.coreContext.apis.FileApi;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -262,7 +369,7 @@ export class OneBotMsgApi {
const pttElement = element.pttElement; const pttElement = element.pttElement;
if (!pttElement) return undefined; if (!pttElement) return undefined;
const NTQQFileApi = this.coreContext.apis.FileApi; const NTQQFileApi = this.coreContext.apis.FileApi;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -278,13 +385,13 @@ export class OneBotMsgApi {
chatType: msg.chatType, chatType: msg.chatType,
guildId: '', guildId: '',
}, },
msg.msgId, msg.msgId,
msg.msgSeq, msg.msgSeq,
msg.senderUid, msg.senderUid,
element.elementId, element.elementId,
element.elementType.toString(), element.elementType.toString(),
pttElement.fileSize || '0', pttElement.fileSize || '0',
pttElement.fileUuid || '' pttElement.fileUuid || ''
); );
//以uuid作为文件名 //以uuid作为文件名
return message_data; return message_data;
@@ -292,7 +399,7 @@ export class OneBotMsgApi {
async parseFaceElement(msg: RawMessage, element: MessageElement) { async parseFaceElement(msg: RawMessage, element: MessageElement) {
const faceElement = element.faceElement; const faceElement = element.faceElement;
if (!faceElement) return undefined; if (!faceElement) return undefined;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -313,7 +420,7 @@ export class OneBotMsgApi {
const NTQQMsgApi = this.coreContext.apis.MsgApi; const NTQQMsgApi = this.coreContext.apis.MsgApi;
const faceElement = element.multiForwardMsgElement; const faceElement = element.multiForwardMsgElement;
if (!faceElement) return undefined; if (!faceElement) return undefined;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };
@@ -340,7 +447,7 @@ export class OneBotMsgApi {
MultiMsg.parentMsgPeer = ParentMsgPeer; MultiMsg.parentMsgPeer = ParentMsgPeer;
MultiMsg.parentMsgIdList = msg.parentMsgIdList; MultiMsg.parentMsgIdList = msg.parentMsgIdList;
MultiMsg.id = MessageUnique.createMsg(ParentMsgPeer, MultiMsg.msgId); //该ID仅用查看 无法调用 MultiMsg.id = MessageUnique.createMsg(ParentMsgPeer, MultiMsg.msgId); //该ID仅用查看 无法调用
const msgList = await RawNTMsg2Onebot(this.coreContext, this.obContext, MultiMsg, messagePostFormat); const msgList = await this.parseMessage(MultiMsg, messagePostFormat);
if (!msgList) continue; if (!msgList) continue;
message_data['data']['content'].push(msgList); message_data['data']['content'].push(msgList);
//console.log("合并消息", msgList); //console.log("合并消息", msgList);
@@ -350,7 +457,7 @@ export class OneBotMsgApi {
async parseArkElement(msg: RawMessage, element: MessageElement) { async parseArkElement(msg: RawMessage, element: MessageElement) {
const arkElement = element.arkElement; const arkElement = element.arkElement;
if (!arkElement) return undefined; if (!arkElement) return undefined;
let message_data: OB11MessageData = { const message_data: OB11MessageData = {
data: {} as any, data: {} as any,
type: 'unknown' as any, type: 'unknown' as any,
}; };

View File

@@ -94,7 +94,7 @@ export async function NT2GroupEvent(core: NapCatCore, obContext: NapCatOneBot11A
if (emojiLikeEvent) return emojiLikeEvent; if (emojiLikeEvent) return emojiLikeEvent;
} }
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) { if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
const GroupIncreaseEvent = await obContext.apiContext.GroupApi.parseGroupMemberIncreaseEvent(msg.peerUid, element.grayTipElement); const GroupIncreaseEvent = await obContext.apiContext.GroupApi.parseGroupIncreaseEvent(msg.peerUid, element.grayTipElement);
if (GroupIncreaseEvent) return GroupIncreaseEvent; if (GroupIncreaseEvent) return GroupIncreaseEvent;
} }

View File

@@ -1,5 +1,4 @@
export * from './config'; export * from './config';
export * from './parseMessage';
export * from './converter'; export * from './converter';
export * from './quick'; export * from './quick';
export * from './genMessage'; export * from './genMessage';

View File

@@ -1,117 +0,0 @@
import { NapCatOneBot11Adapter, OB11Message, OB11MessageData, OB11MessageDataType } from '..';
import { AtType, ChatType, NapCatCore, RawMessage } from '@/core';
import { EventType } from '../event/OB11BaseEvent';
import { OB11Constructor } from './converter';
import { encodeCQCode } from './cqcode';
export async function RawNTMsg2Onebot(
core: NapCatCore,
obcore: NapCatOneBot11Adapter,
msg: RawMessage,
messagePostFormat: string = obcore.configLoader.configData.messagePostFormat
): Promise<OB11Message | undefined> {
if (msg.senderUin == "0" || msg.senderUin == "") return;
if (msg.peerUin == "0" || msg.peerUin == "") return;
//跳过空消息
const NTQQGroupApi = core.apis.GroupApi;
const NTQQUserApi = core.apis.UserApi;
const NTQQMsgApi = core.apis.MsgApi;
const resMsg: OB11Message = {
self_id: parseInt(core.selfInfo.uin),
user_id: parseInt(msg.senderUin!),
time: parseInt(msg.msgTime) || Date.now(),
message_id: msg.id!,
message_seq: msg.id!,
real_id: msg.id!,
message_type: msg.chatType == ChatType.KCHATTYPEGROUP ? 'group' : 'private',
sender: {
user_id: parseInt(msg.senderUin || '0'),
nickname: msg.sendNickName,
card: msg.sendMemberName || '',
},
raw_message: '',
font: 14,
sub_type: 'friend',
message: messagePostFormat === 'string' ? '' : [],
message_format: messagePostFormat === 'string' ? 'string' : 'array',
post_type: core.selfInfo.uin == msg.senderUin ? EventType.MESSAGE_SENT : EventType.MESSAGE,
};
if (msg.chatType == ChatType.KCHATTYPEGROUP) {
resMsg.sub_type = 'normal'; // 这里go-cqhttp是group而onebot11标准是normal, 蛋疼
resMsg.group_id = parseInt(msg.peerUin);
let member = await NTQQGroupApi.getGroupMember(msg.peerUin, msg.senderUin);
if (!member) member = await NTQQGroupApi.getGroupMember(msg.peerUin, msg.senderUin);
if (member) {
resMsg.sender.role = OB11Constructor.groupMemberRole(member.role);
resMsg.sender.nickname = member.nick;
}
} else if (msg.chatType == ChatType.KCHATTYPEC2C) {
resMsg.sub_type = 'friend';
resMsg.sender.nickname = (await NTQQUserApi.getUserDetailInfo(msg.senderUid)).nick;
} else if (msg.chatType == ChatType.KCHATTYPETEMPC2CFROMGROUP) {
resMsg.sub_type = 'group';
const ret = await NTQQMsgApi.getTempChatInfo(ChatType.KCHATTYPETEMPC2CFROMGROUP, msg.senderUid);
if (ret.result === 0) {
resMsg.group_id = parseInt(ret.tmpChatInfo!.groupCode);
resMsg.sender.nickname = ret.tmpChatInfo!.fromNick;
} else {
resMsg.group_id = 284840486; //兜底数据
resMsg.sender.nickname = "临时会话";
}
}
for (const element of msg.elements) {
let message_data: OB11MessageData = {
data: {} as any,
type: 'unknown' as any,
};
if (element.textElement && element.textElement?.atType !== AtType.notAt) {
let textAtMsgData = await obcore.apiContext.MsgApi.parseTextElemntWithAt(msg, element);
if (textAtMsgData) message_data = textAtMsgData
} else if (element.textElement) {
let textMsgData = await obcore.apiContext.MsgApi.parseTextElement(msg, element);
if (textMsgData) message_data = textMsgData;
} else if (element.replyElement) {
let replyMsgData = await obcore.apiContext.MsgApi.parseReplyElement(msg, element);
if (replyMsgData) message_data = replyMsgData;
} else if (element.picElement) {
let PicMsgData = await obcore.apiContext.MsgApi.parsePicElement(msg, element);
if (PicMsgData) message_data = PicMsgData;
} else if (element.fileElement) {
let FileMsgData = await obcore.apiContext.MsgApi.parseFileElement(msg, element);
if (FileMsgData) message_data = FileMsgData;
} else if (element.videoElement) {
let videoMsgData = await obcore.apiContext.MsgApi.parseVideoElement(msg, element);
if (videoMsgData) message_data = videoMsgData;
} else if (element.pttElement) {
let pttMsgData = await obcore.apiContext.MsgApi.parsePTTElement(msg, element);
if (pttMsgData) message_data = pttMsgData;
} else if (element.arkElement) {
let arkMsgData = await obcore.apiContext.MsgApi.parseArkElement(msg, element);
if (arkMsgData) message_data = arkMsgData;
} else if (element.faceElement) {
let faceMsgData = await obcore.apiContext.MsgApi.parseFaceElement(msg, element);
if (faceMsgData) message_data = faceMsgData;
} else if (element.marketFaceElement) {
let marketFaceMsgData = await obcore.apiContext.MsgApi.parseMarketFaceElement(msg, element);
if (marketFaceMsgData) message_data = marketFaceMsgData;
} else if (element.markdownElement) {
message_data['type'] = OB11MessageDataType.markdown;
message_data['data']['data'] = element.markdownElement.content;
} else if (element.multiForwardMsgElement) {
let multiForwardMsgData = await obcore.apiContext.MsgApi.parseMultForwardElement(msg, element, messagePostFormat);
if (multiForwardMsgData) message_data = multiForwardMsgData;
}
if ((message_data.type as string) !== 'unknown' && message_data.data) {
const cqCode = encodeCQCode(message_data);
if (messagePostFormat === 'string') {
(resMsg.message as string) += cqCode;
} else (resMsg.message as OB11MessageData[]).push(message_data);
resMsg.raw_message += cqCode;
}
}
resMsg.raw_message = resMsg.raw_message.trim();
return resMsg;
}

View File

@@ -35,7 +35,7 @@ import { OB11GroupRequestEvent } from '@/onebot/event/request/OB11GroupRequest';
import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRecallNoticeEvent'; import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRecallNoticeEvent';
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent'; import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
import { LRUCache } from '@/common/utils/LRU'; import { LRUCache } from '@/common/utils/LRU';
import { NT2GroupEvent, NT2PrivateEvent, RawNTMsg2Onebot } from './helper'; import { NT2GroupEvent, NT2PrivateEvent } from './helper';
//OneBot实现类 //OneBot实现类
export class NapCatOneBot11Adapter { export class NapCatOneBot11Adapter {
@@ -258,7 +258,7 @@ export class NapCatOneBot11Adapter {
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && !msgIdSend.get(msg.msgId)) { if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && !msgIdSend.get(msg.msgId)) {
msgIdSend.put(msg.msgId, true); msgIdSend.put(msg.msgId, true);
// 完成后再post // 完成后再post
RawNTMsg2Onebot(this.core, this, msg) this.apiContext.MsgApi.parseMessage(msg)
.then((ob11Msg) => { .then((ob11Msg) => {
if (!ob11Msg) return; if (!ob11Msg) return;
ob11Msg.target_id = parseInt(msg.peerUin); ob11Msg.target_id = parseInt(msg.peerUin);
@@ -456,7 +456,7 @@ export class NapCatOneBot11Adapter {
private async emitMsg(message: RawMessage) { private async emitMsg(message: RawMessage) {
const { debug, reportSelfMessage, messagePostFormat } = this.configLoader.configData; const { debug, reportSelfMessage, messagePostFormat } = this.configLoader.configData;
this.context.logger.logDebug('收到新消息 RawMessage', message); this.context.logger.logDebug('收到新消息 RawMessage', message);
RawNTMsg2Onebot(this.core, this, message, messagePostFormat).then((ob11Msg) => { this.apiContext.MsgApi.parseMessage(message, messagePostFormat).then((ob11Msg) => {
if (!ob11Msg) return; if (!ob11Msg) return;
this.context.logger.logDebug('转化为 OB11Message', ob11Msg); this.context.logger.logDebug('转化为 OB11Message', ob11Msg);
if (debug) { if (debug) {
@@ -497,7 +497,7 @@ export class NapCatOneBot11Adapter {
for (const message of msgList) { for (const message of msgList) {
// log("message update", message.sendStatus, message.msgId, message.msgSeq) // log("message update", message.sendStatus, message.msgId, message.msgSeq)
if (message.recallTime != '0' && !cache.get(message.msgId)) { //todo: 这个判断方法不太好,应该使用灰色消息元素来判断? if (message.recallTime != '0' && !cache.get(message.msgId)) { //todo: 这个判断方法不太好,应该使用灰色消息元素来判断?
cache.put(message.msgId, true) cache.put(message.msgId, true);
// 撤回消息上报 // 撤回消息上报
const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId); const oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId);
if (!oriMessageId) { if (!oriMessageId) {

View File

@@ -156,7 +156,7 @@ export interface OB11MessageCustomMusic {
export interface OB11MessageJson { export interface OB11MessageJson {
type: OB11MessageDataType.json; type: OB11MessageDataType.json;
data: { config: { token: string } } & any; data: { config: { token: string }, data: string };
} }
export interface OB11MessageDice { export interface OB11MessageDice {

View File

@@ -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.7', 'napcat-update-button', 'secondary'), SettingButton('V2.2.8', 'napcat-update-button', 'secondary'),
), ),
]), ]),
SettingList([ SettingList([

View File

@@ -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.7", "napcat-update-button", "secondary") SettingButton("V2.2.8", "napcat-update-button", "secondary")
) )
]), ]),
SettingList([ SettingList([