Compare commits

...

38 Commits

Author SHA1 Message Date
手瓜一十雪
44f51a93c8 release: 2.2.13 2024-08-26 17:46:17 +08:00
手瓜一十雪
66c8537b41 feat: support->27391 2024-08-26 17:44:04 +08:00
手瓜一十雪
86ae6dd332 fix: music sign 2024-08-26 17:23:39 +08:00
Seijo Cecilia
69380c9c73 Merge remote-tracking branch 'origin/main' 2024-08-26 16:27:43 +08:00
Seijo Cecilia
3d3759137c fix: remove redundant uid in GetStrangerInfo 2024-08-26 16:27:29 +08:00
手瓜一十雪
9b9b8f6f6f fix: type 2024-08-26 16:26:10 +08:00
手瓜一十雪
8ff87a8245 feat: getGroupExtFE0Info 2024-08-26 16:12:29 +08:00
Seijo Cecilia
d1896da171 update: promise executor functions should not be async 2024-08-26 15:40:27 +08:00
Seijo Cecilia
0bc4f6fd96 refactor: enhanced type definition for other methods 2024-08-26 15:37:17 +08:00
Seijo Cecilia
b16a429686 chore: reformat code style 2024-08-26 14:58:04 +08:00
Seijo Cecilia
fa1d266696 Merge remote-tracking branch 'origin/main' 2024-08-26 14:36:41 +08:00
Seijo Cecilia
d5dd2e9551 update: optimize entity factory (formerly converter.ts) 2024-08-26 14:36:10 +08:00
手瓜一十雪
be57c312c4 Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2024-08-26 14:30:29 +08:00
手瓜一十雪
f180687ba3 refactor: action param handle 2024-08-26 14:30:11 +08:00
Seijo Cecilia
3f3d9cc6f1 refactor: move calls & clean code 2024-08-26 14:22:08 +08:00
Seijo Cecilia
4f98c0d045 refactor: make quick action apis instance methods 2024-08-26 14:14:49 +08:00
Seijo Cecilia
c254441d40 Merge remote-tracking branch 'origin/main' 2024-08-26 14:01:21 +08:00
手瓜一十雪
17cbe74fa3 Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2024-08-26 14:01:06 +08:00
Seijo Cecilia
7aa0bd9b79 refactor: move all callNormalEvent calls to V2 substitutes 2024-08-26 14:00:48 +08:00
手瓜一十雪
2553cf6b72 style: lint 2024-08-26 13:58:28 +08:00
linyuchen
fe9050aeda Update README.md 2024-08-26 13:52:00 +08:00
Wesley F. Young
7092894d22 refactor: normalize file names in common/utils 2024-08-26 12:48:45 +08:00
Wesley F. Young
af6ac26664 chore: lint & style 2024-08-26 12:44:44 +08:00
Wesley F. Young
a22ef67486 fix: type definition for json data 2024-08-26 12:39:32 +08:00
Wesley F. Young
7bb57cd78a fix: use allSettled instead of all when parsing raw message 2024-08-26 12:38:39 +08:00
Wesley F. Young
89b69bbdf8 Merge remote-tracking branch 'origin/main' 2024-08-26 12:02:47 +08:00
Wesley F. Young
e21c779d06 refactor: enhanced type definition for callNormalEvent
类型体操,伟大,无需多言!
2024-08-26 12:02:41 +08:00
手瓜一十雪
dfa3553b71 chore: 谁打的不规范日志 2024-08-26 11:35:18 +08:00
手瓜一十雪
19097388d0 chore: onRecvSysMsg 2024-08-26 11:33:17 +08:00
Wesley F. Young
a71eddbed2 fix: reference error 2024-08-26 11:25:37 +08:00
手瓜一十雪
65bbed0c26 Merge pull request #304 from intling-luo/main
修改群公告的参数名 feed_id 为 notice_id
2024-08-26 11:11:32 +08:00
ling
871cc61dfc 修改群公告的参数名 feed_id 为 notice_id 2024-08-26 10:37:11 +08:00
Wesley F. Young
bc62feb71b refactor: normalize naming 2024-08-26 10:04:31 +08:00
Wesley F. Young
0bba329999 refactor: make sendMsg(WithOb11UniqueId) an instance method 2024-08-26 09:34:51 +08:00
Wesley F. Young
b1a1fdbeee refactor: rename all coreContext -> core 2024-08-26 09:19:50 +08:00
Wesley F. Young
542c5beb1b chore: suppress type check 2024-08-26 09:09:33 +08:00
手瓜一十雪
7b87b0919b release: 2.2.12 2024-08-26 02:57:08 +08:00
手瓜一十雪
9c34f558d3 release: 2.2.11 2024-08-26 02:16:24 +08:00
139 changed files with 1399 additions and 1194 deletions

View File

@@ -31,5 +31,7 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
---
## 约法三章
> [!CAUTION]\
> **请不要在 QQ 官方群聊和任何影响力较大的简中互联网平台(包括但不限于: 哔哩哔哩,微博,知乎,抖音等)发布和讨论*任何*与本项目存在相关性的信息**
任何使用本仓库代码的地方,都应当严格遵守[本仓库开源许可](./LICENSE)。**此外,禁止任何项目未经授权二次分发或基于 NapCat 代码开发。**

View File

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

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "2.2.10",
"version": "2.2.13",
"scripts": {
"build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell",

View File

@@ -1,5 +1,6 @@
import { NodeIQQNTWrapperSession } from '@/core/wrapper/wrapper';
import { randomUUID } from 'crypto';
import { ListenerNamingMapping, ServiceNamingMapping } from '@/core';
interface InternalMapKey {
timeout: number;
@@ -10,18 +11,13 @@ interface InternalMapKey {
export type ListenerClassBase = Record<string, string>;
export interface ListenerIBase {
new(listener: any): ListenerClassBase;
[key: string]: any;
}
export class LegacyNTEventWrapper {
private WrapperSession: NodeIQQNTWrapperSession | undefined; //WrapperSession
private listenerManager: Map<string, ListenerClassBase> = new Map<string, ListenerClassBase>(); //ListenerName-Unique -> Listener实例
private EventTask = new Map<string, Map<string, Map<string, InternalMapKey>>>(); //tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func}
constructor(
wrapperSession: NodeIQQNTWrapperSession
wrapperSession: NodeIQQNTWrapperSession,
) {
this.WrapperSession = wrapperSession;
}
@@ -45,7 +41,13 @@ export class LegacyNTEventWrapper {
);
}
createEventFunction<T extends (...args: any) => any>(eventName: string): T | undefined {
createEventFunction<
Service extends keyof ServiceNamingMapping,
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
// eslint-disable-next-line
// @ts-ignore
T extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
>(eventName: `${Service}/${ServiceMethod}`): T | undefined {
const eventNameArr = eventName.split('/');
type eventType = {
[key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> };
@@ -69,9 +71,10 @@ export class LegacyNTEventWrapper {
if (!existListener) {
const Listener = this.createProxyDispatch(listenerMainName);
const ServiceSubName = /^NodeIKernel(.*?)Listener$/.exec(listenerMainName)![1];
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
const addfunc = this.createEventFunction<(listener: T) => number>(Service);
addfunc!(Listener as T);
const Service = `NodeIKernel${ServiceSubName}Service/addKernel${ServiceSubName}Listener`;
// eslint-disable-next-line
// @ts-ignore
this.createEventFunction(Service)(Listener as T);
this.listenerManager.set(listenerMainName + uniqueCode, Listener);
return Listener as T;
}
@@ -93,36 +96,49 @@ export class LegacyNTEventWrapper {
});
}
async callNoListenerEvent<EventType extends (...args: any[]) => Promise<any> | any>(
EventName = '',
async callNoListenerEvent<
Service extends keyof ServiceNamingMapping,
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
// eslint-disable-next-line
// @ts-ignore
EventType extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
>(
serviceAndMethod: `${Service}/${ServiceMethod}`,
...args: Parameters<EventType>
): Promise<Awaited<ReturnType<EventType>>> {
const EventFunc = this.createEventFunction<EventType>(EventName);
return EventFunc!(...args);
return (this.createEventFunction(serviceAndMethod))!(...args);
}
async RegisterListen<ListenerType extends (...args: any[]) => void>(
ListenerName = '',
async registerListen<
Listener extends keyof ListenerNamingMapping,
ListenerMethod extends Exclude<keyof ListenerNamingMapping[Listener], symbol>,
// eslint-disable-next-line
// @ts-ignore
ListenerType extends (...args: any) => any = ListenerNamingMapping[Listener][ListenerMethod],
>(
listenerAndMethod: `${Listener}/${ListenerMethod}`,
waitTimes = 1,
timeout = 5000,
checker: (...args: Parameters<ListenerType>) => boolean,
) {
return new Promise<Parameters<ListenerType>>((resolve, reject) => {
const ListenerNameList = ListenerName.split('/');
const ListenerNameList = listenerAndMethod.split('/');
const ListenerMainName = ListenerNameList[0];
const ListenerSubName = ListenerNameList[1];
const id = randomUUID();
let complete = 0;
let retData: Parameters<ListenerType> | undefined = undefined;
const databack = () => {
function sendDataCallback() {
if (complete == 0) {
reject(new Error(' ListenerName:' + ListenerName + ' timeout'));
reject(new Error(' ListenerName:' + listenerAndMethod + ' timeout'));
} else {
resolve(retData!);
}
};
const timeoutRef = setTimeout(databack, timeout);
const eventCallbak = {
}
const timeoutRef = setTimeout(sendDataCallback, timeout);
const eventCallback = {
timeout: timeout,
createtime: Date.now(),
checker: checker,
@@ -131,7 +147,7 @@ export class LegacyNTEventWrapper {
retData = args;
if (complete >= waitTimes) {
clearTimeout(timeoutRef);
databack();
sendDataCallback();
}
},
};
@@ -141,21 +157,30 @@ export class LegacyNTEventWrapper {
if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) {
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
}
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
this.createListenerFunction(ListenerMainName);
});
}
async CallNormalEventV2<
EventType extends (...args: any[]) => Promise<any>,
ListenerType extends (...args: any[]) => void
async callNormalEventV2<
Service extends keyof ServiceNamingMapping,
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
Listener extends keyof ListenerNamingMapping,
ListenerMethod extends Exclude<keyof ListenerNamingMapping[Listener], symbol>,
// eslint-disable-next-line
// @ts-ignore
EventType extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
// eslint-disable-next-line
// @ts-ignore
ListenerType extends (...args: any) => any = ListenerNamingMapping[Listener][ListenerMethod]
>(
EventName = '',
ListenerName = '',
waitTimes = 1,
timeout: number = 3000,
serviceAndMethod: `${Service}/${ServiceMethod}`,
listenerAndMethod: `${Listener}/${ListenerMethod}`,
args: Parameters<EventType>,
checkerEvent: (ret: Awaited<ReturnType<EventType>>) => boolean = () => true,
checkerListener: (...args: Parameters<ListenerType>) => boolean = () => true,
...args: Parameters<EventType>
callbackTimesToWait = 1,
timeout = 5000,
) {
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
async (resolve, reject) => {
@@ -163,14 +188,15 @@ export class LegacyNTEventWrapper {
let complete = 0;
let retData: Parameters<ListenerType> | undefined = undefined;
let retEvent: any = {};
const databack = () => {
function sendDataCallback() {
if (complete == 0) {
reject(
new Error(
'Timeout: NTEvent EventName:' +
EventName +
'Timeout: NTEvent serviceAndMethod:' +
serviceAndMethod +
' ListenerName:' +
ListenerName +
listenerAndMethod +
' EventRet:\n' +
JSON.stringify(retEvent, null, 4) +
'\n',
@@ -179,24 +205,24 @@ export class LegacyNTEventWrapper {
} else {
resolve([retEvent as Awaited<ReturnType<EventType>>, ...retData!]);
}
};
}
const ListenerNameList = ListenerName.split('/');
const ListenerNameList = listenerAndMethod.split('/');
const ListenerMainName = ListenerNameList[0];
const ListenerSubName = ListenerNameList[1];
const Timeouter = setTimeout(databack, timeout);
const timeoutRef = setTimeout(sendDataCallback, timeout);
const eventCallbak = {
const eventCallback = {
timeout: timeout,
createtime: Date.now(),
checker: checkerListener,
func: (...args: any[]) => {
complete++;
retData = args as Parameters<ListenerType>;
if (complete >= waitTimes) {
clearTimeout(Timeouter);
databack();
if (complete >= callbackTimesToWait) {
clearTimeout(timeoutRef);
sendDataCallback();
}
},
};
@@ -206,18 +232,18 @@ export class LegacyNTEventWrapper {
if (!this.EventTask.get(ListenerMainName)?.get(ListenerSubName)) {
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
}
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
this.createListenerFunction(ListenerMainName);
const EventFunc = this.createEventFunction<EventType>(EventName);
retEvent = await EventFunc!(...(args as any[]));
const eventFunction = this.createEventFunction(serviceAndMethod);
retEvent = await eventFunction!(...(args));
if (!checkerEvent(retEvent)) {
clearTimeout(Timeouter);
clearTimeout(timeoutRef);
reject(
new Error(
'EventChecker Failed: NTEvent EventName:' +
EventName +
'EventChecker Failed: NTEvent serviceAndMethod:' +
serviceAndMethod +
' ListenerName:' +
ListenerName +
listenerAndMethod +
' EventRet:\n' +
JSON.stringify(retEvent, null, 4) +
'\n',
@@ -227,12 +253,22 @@ export class LegacyNTEventWrapper {
},
);
}
async CallNormalEvent<
EventType extends (...args: any[]) => Promise<any>,
ListenerType extends (...args: any[]) => void
/*
async callNormalEvent<
Service extends keyof ServiceNamingMapping,
ServiceMethod extends Exclude<keyof ServiceNamingMapping[Service], symbol>,
Listener extends keyof ListenerNamingMapping,
ListenerMethod extends Exclude<keyof ListenerNamingMapping[Listener], symbol>,
// eslint-disable-next-line
// @ts-ignore
EventType extends (...args: any) => any = ServiceNamingMapping[Service][ServiceMethod],
// eslint-disable-next-line
// @ts-ignore
ListenerType extends (...args: any) => any = ListenerNamingMapping[Listener][ListenerMethod]
>(
EventName = '',
ListenerName = '',
serviceAndMethod: `${Service}/${ServiceMethod}`,
listenerAndMethod: `${Listener}/${ListenerMethod}`,
waitTimes = 1,
timeout: number = 3000,
checker: (...args: Parameters<ListenerType>) => boolean,
@@ -249,9 +285,9 @@ export class LegacyNTEventWrapper {
reject(
new Error(
'Timeout: NTEvent EventName:' +
EventName +
serviceAndMethod +
' ListenerName:' +
ListenerName +
listenerAndMethod +
' EventRet:\n' +
JSON.stringify(retEvent, null, 4) +
'\n',
@@ -262,7 +298,7 @@ export class LegacyNTEventWrapper {
}
};
const ListenerNameList = ListenerName.split('/');
const ListenerNameList = listenerAndMethod.split('/');
const ListenerMainName = ListenerNameList[0];
const ListenerSubName = ListenerNameList[1];
@@ -290,9 +326,10 @@ export class LegacyNTEventWrapper {
}
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
this.createListenerFunction(ListenerMainName);
const EventFunc = this.createEventFunction<EventType>(EventName);
const EventFunc = this.createEventFunction<EventType>(serviceAndMethod);
retEvent = await EventFunc!(...(args as any[]));
},
);
}
*/
}

View File

@@ -6,6 +6,7 @@ export type ListenerClassBase = Record<string, string>;
export interface ListenerIBase {
// eslint-disable-next-line @typescript-eslint/no-misused-new
new(listener: any): ListenerClassBase;
[key: string]: any;
}
@@ -122,10 +123,9 @@ export class NTEventChannel extends EventEmitter {
async callEvent<EventType extends (...args: any[]) => Promise<any> | any>(
EventName = '', timeout: number = 3000, ...args: Parameters<EventType>) {
return new Promise<Awaited<ReturnType<EventType>>>(async (resolve, reject) => {
return new Promise<Awaited<ReturnType<EventType>>>((resolve) => {
const EventFunc = this.createEventFunction<EventType>(EventName);
const retData = await EventFunc!(...args);
resolve(retData);
EventFunc!(...args).then((retData: Awaited<ReturnType<EventType>> | PromiseLike<Awaited<ReturnType<EventType>>>) => resolve(retData));
});
}
}

View File

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

View File

@@ -4,13 +4,13 @@ import type { NapCatCore } from '@/core';
export abstract class ConfigBase<T> {
name: string;
coreContext: NapCatCore;
core: NapCatCore;
configPath: string;
configData: T = {} as T;
protected constructor(name: string, coreContext: NapCatCore, configPath: string) {
protected constructor(name: string, core: NapCatCore, configPath: string) {
this.name = name;
this.coreContext = coreContext;
this.core = core;
this.configPath = configPath;
fs.mkdirSync(this.configPath, { recursive: true });
this.read();
@@ -28,8 +28,8 @@ export abstract class ConfigBase<T> {
}
read(): T {
const logger = this.coreContext.context.logger;
const configPath = this.getConfigPath(this.coreContext.selfInfo.uin);
const logger = this.core.context.logger;
const configPath = this.getConfigPath(this.core.selfInfo.uin);
if (!fs.existsSync(configPath)) {
try {
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
@@ -54,8 +54,8 @@ export abstract class ConfigBase<T> {
save(newConfigData: T = this.configData) {
const logger = this.coreContext.context.logger;
const selfInfo = this.coreContext.selfInfo;
const logger = this.core.context.logger;
const selfInfo = this.core.selfInfo;
this.configData = newConfigData;
const configPath = this.getConfigPath(selfInfo.uin);
try {

View File

@@ -13,6 +13,7 @@ export function isGIF(path: string) {
fs.closeSync(fd);
return buffer.toString() === 'GIF8';
}
// 定义一个异步函数来检查文件是否存在
export function checkFileReceived(path: string, timeout: number = 3000): Promise<void> {
return new Promise((resolve, reject) => {
@@ -123,15 +124,14 @@ export interface HttpDownloadOptions {
}
export async function httpDownload(options: string | HttpDownloadOptions): Promise<Buffer> {
const chunks: Buffer[] = [];
// const chunks: Buffer[] = [];
let url: string;
let headers: Record<string, string> = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36',
};
if (typeof options === 'string') {
url = options;
const host = new URL(url).hostname;
headers['Host'] = host;
headers['Host'] = new URL(url).hostname;
} else {
url = options.url;
if (options.headers) {
@@ -269,4 +269,4 @@ export async function uri2local(dir: string, uri: string, filename: string | und
return { success: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true };
}
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false };
}
}

View File

@@ -18,11 +18,12 @@ export async function solveAsyncProblem<T extends (...args: any[]) => Promise<an
return new Promise<Awaited<ReturnType<T>> | undefined>((resolve) => {
func(...args).then((result) => {
resolve(result);
}).catch((e) => {
}).catch(() => {
resolve(undefined);
});
});
}
//下面这个类是用于将uid+msgid合并的类
export class UUIDConverter {
static encode(highStr: string, lowStr: string): string {
@@ -31,11 +32,10 @@ export class UUIDConverter {
const highHex = high.toString(16).padStart(16, '0');
const lowHex = low.toString(16).padStart(16, '0');
const combinedHex = highHex + lowHex;
const uuid = `${combinedHex.substring(0, 8)}-${combinedHex.substring(8, 12)}-${combinedHex.substring(
return `${combinedHex.substring(0, 8)}-${combinedHex.substring(8, 12)}-${combinedHex.substring(
12,
16,
)}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`;
return uuid;
}
static decode(uuid: string): { high: string; low: string } {
@@ -122,11 +122,11 @@ export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
};
}
return {
baseVersion: '9.9.15-27254',
curVersion: '9.9.15-27254',
baseVersion: '9.9.15-27391',
curVersion: '9.9.15-27391',
prevVersion: '',
onErrorVersions: [],
buildId: '27254',
buildId: '27391',
};
}

View File

@@ -177,12 +177,12 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
if (element.replyElement) {
const recordMsgOrNull = msg.records.find(
record => element.replyElement!.sourceMsgIdInRecords === record.msgId
record => element.replyElement!.sourceMsgIdInRecords === record.msgId,
);
return `[回复消息 ${
recordMsgOrNull &&
recordMsgOrNull.peerUin != '284840486' // 非转发消息; 否则定位不到
?
?
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})`
}]`;

File diff suppressed because one or more lines are too long

View File

@@ -17,7 +17,7 @@ import {
import path from 'path';
import fs from 'fs';
import fsPromises from 'fs/promises';
import { InstanceContext, NapCatCore, OnRichMediaDownloadCompleteParams } from '@/core';
import { InstanceContext, NapCatCore } from '@/core';
import * as fileType from 'file-type';
import imageSize from 'image-size';
import { ISizeCalculationResult } from 'image-size/dist/types/interface';
@@ -97,9 +97,13 @@ export class NTQQFileApi {
async createValidSendFileElement(
filePath: string,
fileName: string = '',
folderId: string = ''
folderId: string = '',
): Promise<SendFileElement> {
const { fileName: _fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.FILE);
const {
fileName: _fileName,
path,
fileSize,
} = await this.core.apis.FileApi.uploadFile(filePath, ElementType.FILE);
if (fileSize === 0) {
throw new Error('文件异常大小为0');
}
@@ -118,9 +122,14 @@ export class NTQQFileApi {
async createValidSendPicElement(
picPath: string,
summary: string = '',
subType: 0 | 1 = 0
subType: 0 | 1 = 0,
): Promise<SendPicElement> {
const { md5, fileName, path, fileSize } = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
const {
md5,
fileName,
path,
fileSize,
} = await this.core.apis.FileApi.uploadFile(picPath, ElementType.PIC, subType);
if (fileSize === 0) {
throw new Error('文件异常大小为0');
}
@@ -153,7 +162,12 @@ export class NTQQFileApi {
diyThumbPath: string = '',
): Promise<SendVideoElement> {
const logger = this.core.context.logger;
const { fileName: _fileName, path, fileSize, md5 } = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
const {
fileName: _fileName,
path,
fileSize,
md5,
} = await this.core.apis.FileApi.uploadFile(filePath, ElementType.VIDEO);
if (fileSize === 0) {
throw new Error('文件异常大小为0');
}
@@ -200,7 +214,7 @@ export class NTQQFileApi {
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
// log("生成缩略图", _thumbPath)
thumbPath.set(0, _thumbPath);
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : "";
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
// "fileElement": {
// "fileMd5": "",
// "fileName": "1.mp4",
@@ -304,66 +318,45 @@ export class NTQQFileApi {
return sourcePath;
}
}
const data = await this.core.eventWrapper.CallNormalEvent<
(
params: {
fileModelId: string,
downloadSourceType: number,
triggerType: number,
msgId: string,
chatType: ChatType,
peerUid: string,
elementId: string,
thumbSize: number,
downloadType: number,
filePath: string
}) => Promise<unknown>,
(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams) => void
>(
'NodeIKernelMsgService/downloadRichMedia',
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
1,
timeout,
(arg: OnRichMediaDownloadCompleteParams) => {
if (arg.msgId === msgId) {
return true;
}
return false;
},
{
fileModelId: '0',
downloadSourceType: 0,
triggerType: 1,
msgId: msgId,
chatType: chatType,
peerUid: peerUid,
elementId: elementId,
thumbSize: 0,
downloadType: 1,
filePath: thumbPath,
},
);
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelMsgService/downloadRichMedia',
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
[{
fileModelId: '0',
downloadSourceType: 0,
triggerType: 1,
msgId: msgId,
chatType: chatType,
peerUid: peerUid,
elementId: elementId,
thumbSize: 0,
downloadType: 1,
filePath: thumbPath,
}],
() => true,
(arg) => arg.msgId === msgId,
1,
timeout,
);
const msg = await this.core.apis.MsgApi.getMsgsByMsgId({
guildId: '',
chatType: chatType,
peerUid: peerUid,
}, [msgId]);
if (msg.msgList.length === 0) {
return data[1].filePath;
return fileTransNotifyInfo.filePath;
}
//获取原始消息
const FileElements = msg?.msgList[0]?.elements?.find(e => e.elementId === elementId);
if (!FileElements) {
//失败则就乱来 Todo
return data[1].filePath;
return fileTransNotifyInfo.filePath;
}
//从原始消息获取文件路径
const filePath =
FileElements?.fileElement?.filePath ??
return FileElements?.fileElement?.filePath ??
FileElements?.pttElement?.filePath ??
FileElements?.videoElement?.filePath ??
FileElements?.picElement?.sourcePath;
return filePath;
}
async getImageSize(filePath: string): Promise<ISizeCalculationResult | undefined> {
@@ -438,56 +431,14 @@ export class NTQQFileApi {
}
async searchfile(keys: string[]) {
type EventType = NodeIKernelSearchService['searchFileWithKeywords'];
interface OnListener {
searchId: string,
hasMore: boolean,
resultItems: {
chatType: ChatType,
buddyChatInfo: any[],
discussChatInfo: any[],
groupChatInfo:
{
groupCode: string,
isConf: boolean,
hasModifyConfGroupFace: boolean,
hasModifyConfGroupName: boolean,
groupName: string,
remark: string
}[],
dataLineChatInfo: any[],
tmpChatInfo: any[],
msgId: string,
msgSeq: string,
msgTime: string,
senderUid: string,
senderNick: string,
senderRemark: string,
senderCard: string,
elemId: string,
elemType: number,
fileSize: string,
filePath: string,
fileName: string,
hits:
{
start: number,
end: number
}[]
}[]
}
const Event = this.core.eventWrapper.createEventFunction<EventType>('NodeIKernelSearchService/searchFileWithKeywords');
let id = '';
const Listener = this.core.eventWrapper.RegisterListen<(params: OnListener) => void>
(
const Event = this.core.eventWrapper.createEventFunction('NodeIKernelSearchService/searchFileWithKeywords');
const id = await Event!(keys, 12);
const Listener = this.core.eventWrapper.registerListen(
'NodeIKernelSearchListener/onSearchFileKeywordsResult',
1,
20000,
(params) => id !== '' && params.searchId == id,
);
id = await Event!(keys, 12);
);
const [ret] = (await Listener);
return ret;
}
@@ -499,7 +450,7 @@ export class NTQQFileApi {
const url: string = element.originImageUrl!; // 没有域名
const md5HexStr = element.md5HexStr;
const fileMd5 = element.md5HexStr;
const fileUuid = element.fileUuid;
// const fileUuid = element.fileUuid;
if (url) {
const UrlParse = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接
@@ -571,9 +522,9 @@ export class NTQQFileCacheApi {
}
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
//需要五个参数
//return napCatCore.session.getStorageCleanService().getFileCacheInfo();
// const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
// 需要五个参数
// return napCatCore.session.getStorageCleanService().getFileCacheInfo();
}
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {

View File

@@ -1,11 +1,12 @@
import { Friend, FriendV2, User } from '@/core/entities';
import { BuddyListReqType, InstanceContext, NapCatCore, NodeIKernelBuddyListener, NodeIKernelBuddyService, NodeIKernelProfileService, OnBuddyChangeParams } from '@/core';
import { LimitedHashTable } from '@/common/utils/MessageUnique';
import { FriendV2 } from '@/core/entities';
import { BuddyListReqType, InstanceContext, NapCatCore, NodeIKernelProfileService } from '@/core';
import { LimitedHashTable } from '@/common/utils/message-unique';
export class NTQQFriendApi {
context: InstanceContext;
core: NapCatCore;
//friends: Map<string, Friend> = new Map<string, FriendV2>();
// friends: Map<string, Friend> = new Map<string, FriendV2>();
constructor(context: InstanceContext, core: NapCatCore) {
this.context = context;
@@ -20,7 +21,7 @@ export class NTQQFriendApi {
const buddyService = this.context.session.getBuddyService();
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
const data = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids,
);
return Array.from(data.values());
@@ -32,10 +33,10 @@ export class NTQQFriendApi {
const buddyService = this.context.session.getBuddyService();
const buddyListV2 = refresh ? await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL) : await buddyService.getBuddyListV2('0', BuddyListReqType.KNOMAL);
uids.push(...buddyListV2.data.flatMap(item => item.buddyUids));
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
const data = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids,
);
data.forEach((value, key) => {
data.forEach((value) => {
retMap.set(value.uin!, value.uid!);
});
//console.log('getBuddyIdMap', retMap.getValue);
@@ -54,7 +55,7 @@ export class NTQQFriendApi {
});
return item.buddyUids;
}));
const data = await this.core.eventWrapper.callNoListenerEvent<NodeIKernelProfileService['getCoreAndBaseInfo']>(
const data = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelProfileService/getCoreAndBaseInfo', 'nodeStore', uids,
);
return buddyListV2.map(category => ({
@@ -70,18 +71,17 @@ export class NTQQFriendApi {
async isBuddy(uid: string) {
return this.context.session.getBuddyService().isBuddy(uid);
}
async clearBuddyReqUnreadCnt() {
return this.context.session.getBuddyService().clearBuddyReqUnreadCnt();
}
async getBuddyReq() {
const [, ret] = await this.core.eventWrapper.CallNormalEventV2<
NodeIKernelBuddyService['getBuddyReq'],
NodeIKernelBuddyListener['onBuddyReqChange']
>(
const [, ret] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelBuddyService/getBuddyReq',
'NodeIKernelBuddyListener/onBuddyReqChange',
1,
5000);
[],
);
return ret;
}

View File

@@ -4,13 +4,11 @@ import {
Group,
GroupMember,
GroupMemberRole,
GroupNotify,
GroupRequestOperateTypes,
InstanceContext,
KickMemberV2Req,
MemberExtSourceType,
NapCatCore,
NodeIKernelGroupListener,
NodeIKernelGroupService,
} from '@/core';
import { isNumeric, runAllWithTimeout, sleep } from '@/common/utils/helper';
@@ -21,6 +19,7 @@ export class NTQQGroupApi {
groupCache: Map<string, Group> = new Map<string, Group>();
groupMemberCache: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
groups: Group[] = [];
constructor(context: InstanceContext, core: NapCatCore) {
this.context = context;
this.core = core;
@@ -28,6 +27,7 @@ export class NTQQGroupApi {
this.initCache().then().catch(context.logger.logError);
});
}
async initCache() {
this.groups = await this.getGroups();
for (const group of this.groups) {
@@ -37,24 +37,60 @@ export class NTQQGroupApi {
}
this.context.logger.logDebug(`加载${this.groups.length}个群组缓存完成`);
}
async setGroupAvatar(gc: string, filePath: string) {
return this.context.session.getGroupService().setHeader(gc, filePath);
}
async getGroups(forced = false) {
type ListenerType = NodeIKernelGroupListener['onGroupListUpdate'];
const [_retData, _updateType, groupList] = await this.core.eventWrapper.CallNormalEvent<(force: boolean) => Promise<any>, ListenerType>
(
const [, , groupList] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getGroupList',
'NodeIKernelGroupListener/onGroupListUpdate',
1,
5000,
() => true,
forced,
);
[forced],
);
return groupList;
}
async getGroupExtFE0Info(GroupCode: string[], forced = true) {
return this.context.session.getGroupService().getGroupExt0xEF0Info(
GroupCode,
[],
{
bindGuildId: 1,
blacklistExpireTime: 1,
companyId: 1,
essentialMsgPrivilege: 1,
essentialMsgSwitch: 1,
fullGroupExpansionSeq: 1,
fullGroupExpansionSwitch: 1,
gangUpId: 1,
groupAioBindGuildId: 1,
groupBindGuildIds: 1,
groupBindGuildSwitch: 1,
groupExcludeGuildIds: 1,
groupExtFlameData: 1,
groupFlagPro1: 1,
groupInfoExtSeq: 1,
groupOwnerId: 1,
groupSquareSwitch: 1,
hasGroupCustomPortrait: 1,
inviteRobotMemberExamine: 1,
inviteRobotMemberSwitch: 1,
inviteRobotSwitch: 1,
isLimitGroupRtc: 1,
lightCharNum: 1,
luckyWord: 1,
luckyWordId: 1,
msgEventSeq: 1,
qqMusicMedalSwitch: 1,
reserve: 1,
showPlayTogetherSwitch: 1,
starId: 1,
todoSeq: 1,
viewedMsgDisappearTime: 1
},
forced
);
}
async getGroup(groupCode: string, forced = false) {
let group = this.groupCache.get(groupCode.toString());
if (!group) {
@@ -142,8 +178,7 @@ export class NTQQGroupApi {
members = await this.getGroupMembers(groupCodeStr);
// 更新群成员列表
this.groupMemberCache.set(groupCodeStr, members);
}
catch (e) {
} catch (e) {
return null;
}
}
@@ -222,21 +257,25 @@ export class NTQQGroupApi {
// GetMsgByShoretID(ShoretID); -> MsgService.getMsgs(Peer,MsgId,1,false); -> 组出参数
return this.context.session.getGroupService().addGroupEssence(param);
}
async kickMemberV2Inner(param: KickMemberV2Req) {
return this.context.session.getGroupService().kickMemberV2(param);
}
async deleteGroupBulletin(GroupCode: string, feedId: string) {
async deleteGroupBulletin(GroupCode: string, noticeId: string) {
const _Pskey = (await this.core.apis.UserApi.getPSkey(['qun.qq.com'])).domainPskeyMap.get('qun.qq.com')!;
return this.context.session.getGroupService().deleteGroupBulletin(GroupCode, _Pskey, feedId);
return this.context.session.getGroupService().deleteGroupBulletin(GroupCode, _Pskey, noticeId);
}
async quitGroupV2(GroupCode: string, needDeleteLocalMsg: boolean) {
const param = {
groupCode: GroupCode,
needDeleteLocalMsg: needDeleteLocalMsg
needDeleteLocalMsg: needDeleteLocalMsg,
};
//应该是直接返回不需要Listener的 未经测试 需测试再发布
return this.context.session.getGroupService().quitGroupV2(param);
}
async removeGroupEssence(GroupCode: string, msgId: string) {
// 代码没测过
// 需要 ob11msgid->msgId + (peer) -> msgSeq + msgRandom
@@ -255,33 +294,30 @@ export class NTQQGroupApi {
}
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 [, , , notifies] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getSingleScreenNotifies',
'NodeIKernelGroupListener/onGroupSingleScreenNotifies',
1,
5000,
() => true,
false,
'',
num,
);
[
false,
'',
num,
],
);
return notifies;
}
async getGroupMemberV2(GroupCode: string, uid: string, forced = false) {
type EventType = NodeIKernelGroupService['getMemberInfo'];
const Listener = this.core.eventWrapper.RegisterListen<(params: any) => void>
(
const Listener = this.core.eventWrapper.registerListen(
'NodeIKernelGroupListener/onMemberInfoChange',
1,
forced ? 5000 : 250,
(params) => {
return params === GroupCode;
},
);
const EventFunc = this.core.eventWrapper.createEventFunction<EventType>('NodeIKernelGroupService/getMemberInfo');
const retData = await EventFunc!(GroupCode, [uid], forced);
(params) => params === GroupCode,
);
const retData = await (
this.core.eventWrapper
.createEventFunction('NodeIKernelGroupService/getMemberInfo')
)!(GroupCode, [uid], forced);
if (retData.result !== 0) {
throw new Error(`${retData.errMsg}`);
}
@@ -327,12 +363,10 @@ export class NTQQGroupApi {
}
async getArkJsonGroupShare(GroupCode: string) {
const ret = await this.core.eventWrapper.callNoListenerEvent<(GroupId: string) => Promise<GeneralCallResult & {
arkJson: string
}>>(
const ret = await this.core.eventWrapper.callNoListenerEvent(
'NodeIKernelGroupService/getGroupRecommendContactArkJson',
GroupCode,
);
) as GeneralCallResult & { arkJson: string };
return ret.arkJson;
}

View File

@@ -1,6 +1,5 @@
import { ChatType, GetFileListParam, Peer, RawMessage, SendMessageElement, SendStatusType } from '@/core/entities';
import { InstanceContext, NapCatCore } from '@/core';
import { GroupFileInfoUpdateParamType } from '@/core/listeners';
import { GeneralCallResult } from '@/core/services/common';
export class NTQQMsgApi {
@@ -19,10 +18,11 @@ export class NTQQMsgApi {
async sendShowInputStatusReq(peer: Peer, eventType: number) {
return this.context.session.getMsgService().sendShowInputStatusReq(peer.chatType, eventType, peer.peerUid);
}
async getMsgEmojiLikesList(peer: Peer, msgSeq: string, emojiId: string, emojiType: string, count: number = 20) {
//console.log(peer, msgSeq, emojiId, emojiType, count);
//注意此处emojiType 可选值一般为1-2 2好像是unicode表情dec值 大部分情况 Taged M likiowa
return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, 20);
return this.context.session.getMsgService().getMsgEmojiLikesList(peer, msgSeq, emojiId, emojiType, '', false, count);
}
// napCatCore: NapCatCore | null = null;
@@ -40,6 +40,7 @@ export class NTQQMsgApi {
emojiId = emojiId.toString();
return this.context.session.getMsgService().setMsgEmojiLikes(peer, msgSeq, emojiId, emojiId.length > 3 ? '2' : '1', set);
}
async getMultiMsg(peer: Peer, rootMsgId: string, parentMsgId: string): Promise<GeneralCallResult & {
msgList: RawMessage[]
} | undefined> {
@@ -51,7 +52,7 @@ export class NTQQMsgApi {
}
async getLastestMsgByUids(peer: Peer, count: number = 20, isReverseOrder: boolean = false) {
const ret = await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', '0', {
chatInfo: peer,
filterMsgType: [],
filterSendersUid: [],
@@ -61,7 +62,6 @@ export class NTQQMsgApi {
isIncludeCurrent: true,
pageLimit: count,
});
return ret;
}
async getMsgsByMsgId(peer: Peer | undefined, msgIds: string[] | undefined) {
@@ -80,7 +80,7 @@ export class NTQQMsgApi {
}
async queryMsgsWithFilterExWithSeq(peer: Peer, msgSeq: string) {
const ret = await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
filterMsgType: [],
filterSendersUid: [],
@@ -90,17 +90,17 @@ export class NTQQMsgApi {
isIncludeCurrent: true,
pageLimit: 1,
});
return ret;
}
async getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, z: boolean) {
return await this.context.session.getMsgService().getMsgsBySeqAndCount(peer, seq, count, desc, z);
}
async getMsgExBySeq(peer: Peer, msgSeq: string) {
const DateNow = Math.floor(Date.now() / 1000);
const filterMsgFromTime = (DateNow - 300).toString();
const filterMsgToTime = DateNow.toString();
const ret = await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
return await this.context.session.getMsgService().queryMsgsWithFilterEx('0', '0', msgSeq, {
chatInfo: peer,//此处为Peer 为关键查询参数 没有啥也没有 by mlik iowa
filterMsgType: [],
filterSendersUid: [],
@@ -110,29 +110,29 @@ export class NTQQMsgApi {
isIncludeCurrent: true,
pageLimit: 100,
});
return ret;
}
async setMsgRead(peer: Peer) {
return this.context.session.getMsgService().setMsgRead(peer);
}
async getGroupFileList(GroupCode: string, params: GetFileListParam) {
const data = await this.core.eventWrapper.CallNormalEvent<
(GroupCode: string, params: GetFileListParam) => Promise<unknown>,
(groupFileListResult: GroupFileInfoUpdateParamType) => void
>(
'NodeIKernelRichMediaService/getGroupFileList',
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
1,
5000,
(groupFileListResult: GroupFileInfoUpdateParamType) => {
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
return true;
},
const [, groupFileListResult] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelRichMediaService/getGroupFileList',
'NodeIKernelMsgListener/onGroupFileInfoUpdate',
[
GroupCode,
params,
);
return data[1].item;
],
() => true,
( /* groupFileListResult: GroupFileInfoUpdateParamType */) => {
//Developer Mlikiowa Todo: 此处有问题 无法判断是否成功
return true;
},
1,
5000,
);
return groupFileListResult.item;
}
async getMsgHistory(peer: Peer, msgId: string, count: number, isReverseOrder: boolean = false) {
@@ -146,29 +146,32 @@ export class NTQQMsgApi {
peerUid: peer.peerUid,
}, msgIds);
}
async PrepareTempChat(toUserUid: string, GroupCode: string, nickname: string) {
//By Jadx/Ida Mlikiowa
const TempGameSession = {
nickname: "",
gameAppId: "",
selfTinyId: "",
peerRoleId: "",
peerOpenId: "",
nickname: '',
gameAppId: '',
selfTinyId: '',
peerRoleId: '',
peerOpenId: '',
};
return this.context.session.getMsgService().prepareTempChat({
chatType: ChatType.KCHATTYPETEMPC2CFROMGROUP,
peerUid: toUserUid,
peerNickname: nickname,
fromGroupCode: GroupCode,
sig: "",
selfPhone: "",
sig: '',
selfPhone: '',
selfUid: this.core.selfInfo.uid,
gameSession: TempGameSession
gameSession: TempGameSession,
});
}
async getTempChatInfo(chatType: ChatType, peerUid: string) {
return this.context.session.getMsgService().getTempChatInfo(chatType, peerUid);
}
async sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete = true, timeout = 10000) {
//唉? !我有个想法
if (peer.chatType === ChatType.KCHATTYPETEMPC2CFROMGROUP && peer.guildId && peer.guildId !== '') {
@@ -179,33 +182,32 @@ export class NTQQMsgApi {
}
const msgId = await this.generateMsgUniqueId(peer.chatType, await this.getServerTime());
peer.guildId = msgId;
const data = await this.core.eventWrapper.CallNormalEvent<
(msgId: string, peer: Peer, msgElements: SendMessageElement[], map: Map<any, any>) => Promise<unknown>,
(msgList: RawMessage[]) => void
>(
'NodeIKernelMsgService/sendMsg',
'NodeIKernelMsgListener/onMsgInfoListUpdate',
1,
timeout,
(msgRecords: RawMessage[]) => {
for (const msgRecord of msgRecords) {
if (msgRecord.guildId === msgId && msgRecord.sendStatus === SendStatusType.KSEND_STATUS_SUCCESS) {
return true;
}
}
return false;
},
const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelMsgService/sendMsg',
'NodeIKernelMsgListener/onMsgInfoListUpdate',
[
'0',
peer,
msgElements,
new Map(),
);
const retMsg = data[1].find(msgRecord => {
],
() => true,
msgRecords => {
for (const msgRecord of msgRecords) {
if (msgRecord.guildId === msgId && msgRecord.sendStatus === SendStatusType.KSEND_STATUS_SUCCESS) {
return true;
}
}
return false;
},
1,
timeout,
);
return msgList.find(msgRecord => {
if (msgRecord.guildId === msgId) {
return true;
}
});
return retMsg;
}
async generateMsgUniqueId(chatType: number, time: string) {
@@ -224,34 +226,32 @@ export class NTQQMsgApi {
const msgInfos = msgIds.map(id => {
return { msgId: id, senderShowName: this.core.selfInfo.nick };
});
const data = await this.core.eventWrapper.CallNormalEvent<
(msgInfo: typeof msgInfos, srcPeer: Peer, destPeer: Peer, comment: Array<any>, attr: Map<any, any>) => Promise<unknown>,
(msgList: RawMessage[]) => void
>(
'NodeIKernelMsgService/multiForwardMsgWithComment',
'NodeIKernelMsgListener/onMsgInfoListUpdate',
1,
5000,
(msgRecords: RawMessage[]) => {
for (const msgRecord of msgRecords) {
if (msgRecord.peerUid == destPeer.peerUid && msgRecord.senderUid == this.core.selfInfo.uid) {
return true;
}
}
return false;
},
const [, msgList] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelMsgService/multiForwardMsgWithComment',
'NodeIKernelMsgListener/onMsgInfoListUpdate',
[
msgInfos,
srcPeer,
destPeer,
[],
new Map(),
);
for (const msg of data[1]) {
],
() => true,
(msgRecords) => {
for (const msgRecord of msgRecords) {
if (msgRecord.peerUid == destPeer.peerUid && msgRecord.senderUid == this.core.selfInfo.uid) {
return true;
}
}
return false;
},
);
for (const msg of msgList) {
const arkElement = msg.elements.find(ele => ele.arkElement);
if (!arkElement) {
continue;
}
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData ?? "");
const forwardData: any = JSON.parse(arkElement.arkElement?.bytesData ?? '');
if (forwardData.app != 'com.tencent.multimsg') {
continue;
}

View File

@@ -28,18 +28,12 @@ export class NTQQSystemApi {
//1-2-162b9b42-65b9-4405-a8ed-2e256ec8aa50
async getArkJsonCollection(cid: string) {
const ret = await this.core.eventWrapper.callNoListenerEvent<(cid: string) => Promise<GeneralCallResult & {
arkJson: string
}>>(
'NodeIKernelCollectionService/collectionArkShare',
'1717662698058',
);
return ret;
return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelCollectionService/collectionArkShare', '1717662698058');
}
async BootMiniApp(appfile: string, params: string) {
await this.context.session.getNodeMiscService().setMiniAppVersion('2.16.4');
const c = await this.context.session.getNodeMiscService().getMiniAppPath();
// const c = await this.context.session.getNodeMiscService().getMiniAppPath();
return this.context.session.getNodeMiscService().startNewMiniApp(appfile, params);
}

View File

@@ -1,7 +1,6 @@
import type { ModifyProfileParams, User, UserDetailInfoByUin, UserDetailInfoByUinV2 } from '@/core/entities';
import { NodeIKernelProfileListener } from '@/core/listeners';
import type { ModifyProfileParams, User, UserDetailInfoByUinV2 } from '@/core/entities';
import { RequestUtil } from '@/common/utils/request';
import { NodeIKernelProfileService, ProfileBizType, UserDetailSource } from '@/core/services';
import { ProfileBizType, UserDetailSource } from '@/core/services';
import { InstanceContext, NapCatCore } from '..';
import { solveAsyncProblem } from '@/common/utils/helper';
@@ -65,17 +64,18 @@ export class NTQQUserApi {
}
async fetchUserDetailInfos(uids: string[]) {
//26702 以上使用新接口 .Dev Mlikiowa
type EventService = NodeIKernelProfileService['fetchUserDetailInfo'];
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
// TODO: 26702 以上使用新接口 .Dev MliKiowa
const retData: User[] = [];
const [_retData, _retListener] = await this.core.eventWrapper.CallNormalEvent<
EventService, EventListener
>(
const [_retData, _retListener] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelProfileService/fetchUserDetailInfo',
'NodeIKernelProfileListener/onUserDetailInfoChanged',
uids.length,
5000,
[
'BuddyProfileStore',
uids,
UserDetailSource.KSERVER,
[ProfileBizType.KALL],
],
() => true,
(profile) => {
if (uids.includes(profile.uid)) {
const RetUser: User = {
@@ -92,28 +92,24 @@ export class NTQQUserApi {
}
return false;
},
'BuddyProfileStore',
uids,
UserDetailSource.KSERVER,
[ProfileBizType.KALL],
uids.length,
);
return retData;
}
async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) {
type EventService = NodeIKernelProfileService['fetchUserDetailInfo'];
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
const [_retData, profile] = await this.core.eventWrapper.CallNormalEvent<EventService, EventListener>(
const [_retData, profile] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelProfileService/fetchUserDetailInfo',
'NodeIKernelProfileListener/onUserDetailInfoChanged',
1,
5000,
[
'BuddyProfileStore',
[uid],
mode,
[ProfileBizType.KALL],
],
() => true,
(profile) => profile.uid === uid,
'BuddyProfileStore',
[uid],
mode,
[ProfileBizType.KALL],
);
const RetUser: User = {
...profile.simpleInfo.coreInfo,
@@ -146,8 +142,7 @@ export class NTQQUserApi {
const ClientKeyData = await this.forceFetchClientKey();
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin +
'&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2F' + domain + '%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
return cookies;
return await RequestUtil.HttpsGetCookies(requestUrl);
}
async getPSkey(domainList: string[]) {
@@ -170,8 +165,7 @@ export class NTQQUserApi {
async getQzoneCookies() {
const ClientKeyData = await this.forceFetchClientKey();
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + ClientKeyData.clientKey + '&u1=https%3A%2F%2Fuser.qzone.qq.com%2F' + this.core.selfInfo.uin + '%2Finfocenter&keyindex=19%27';
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
return cookies;
return await RequestUtil.HttpsGetCookies(requestUrl);
}
//需要异常处理
@@ -182,7 +176,7 @@ export class NTQQUserApi {
throw new Error('getClientKey Error');
}
const clientKey = ClientKeyData.clientKey;
const keyIndex = ClientKeyData.keyIndex;
// const keyIndex = ClientKeyData.keyIndex;
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + '&clientkey=' + clientKey + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=19%27';
const cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
const skey = cookies['skey'];
@@ -237,8 +231,7 @@ export class NTQQUserApi {
}
async getUserDetailInfoByUinV2(Uin: string) {
return await this.core.eventWrapper.callNoListenerEvent<(Uin: string) => Promise<UserDetailInfoByUinV2>>
('NodeIKernelProfileService/getUserDetailInfoByUin', Uin);
return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelProfileService/getUserDetailInfoByUin', Uin);
}
async forceFetchClientKey() {

View File

@@ -1,9 +1,9 @@
import { NodeQQNTWrapperUtil, NTApiContext, WrapperNodeApi } from '@/core/wrapper';
import { NodeQQNTWrapperUtil, StableNTApiWrapper, WrapperNodeApi } from '@/core/wrapper';
import path from 'node:path';
import fs from 'node:fs';
import { InstanceContext } from './wrapper';
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
import { NodeIKernelMsgListener, NodeIKernelGroupListener, NodeIKernelProfileListener } from './listeners';
import { NodeIKernelGroupListener, NodeIKernelMsgListener, NodeIKernelProfileListener } from './listeners';
import { DataSource, GroupMember, SelfInfo } from './entities';
import { LegacyNTEventWrapper } from '@/common/framework/event-legacy';
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis';
@@ -30,7 +30,7 @@ export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
export class NapCatCore {
readonly context: InstanceContext;
readonly apis: NTApiContext;
readonly apis: StableNTApiWrapper;
readonly eventWrapper: LegacyNTEventWrapper;
// readonly eventChannel: NTEventChannel;
NapCatDataPath: string;
@@ -98,7 +98,7 @@ export class NapCatCore {
};
//await sleep(2500);
this.context.session.getMsgService().addKernelMsgListener(
proxiedListenerOf(msgListener, this.context.logger) as any
proxiedListenerOf(msgListener, this.context.logger) as any,
);
const profileListener = new NodeIKernelProfileListener();
@@ -125,8 +125,7 @@ export class NapCatCore {
//群成员数量变化 应该刷新缓存
if (existGroup && g.memberCount === existGroup.memberCount) {
Object.assign(existGroup, g);
}
else {
} else {
this.apis.GroupApi.groupCache.set(g.groupCode, g);
// 获取群成员
}
@@ -149,8 +148,7 @@ export class NapCatCore {
const existMember = existMembers.get(uid);
if (existMember) {
Object.assign(existMember, member);
}
else {
} else {
existMembers!.set(uid, member);
}
//移除成员
@@ -158,8 +156,7 @@ export class NapCatCore {
existMembers.delete(uid);
}
});
}
else {
} else {
this.apis.GroupApi.groupMemberCache.set(groupCode, arg.infos);
}
// console.log('onMemberListChange', groupCode, arg);
@@ -182,8 +179,7 @@ export class NapCatCore {
member.isChangeRole = this.checkAdminEvent(groupCode, member, existMember);
// 更新成员信息
Object.assign(existMember, member);
}
else {
} else {
existMembers.set(uid, member);
}
//移除成员
@@ -191,15 +187,15 @@ export class NapCatCore {
existMembers.delete(uid);
}
});
}
else {
} else {
this.apis.GroupApi.groupMemberCache.set(groupCode, members);
}
};
this.context.session.getGroupService().addKernelGroupListener(
proxiedListenerOf(groupListener, this.context.logger) as any
proxiedListenerOf(groupListener, this.context.logger) as any,
);
}
checkAdminEvent(groupCode: string, memberNew: GroupMember, memberOld: GroupMember | undefined): boolean {
if (memberNew.role !== memberOld?.role) {
this.context.logger.logDebug(`${groupCode} ${memberNew.nick} 角色变更为 ${memberNew.role === 3 ? '管理员' : '群员'}`);

View File

@@ -1,34 +1,84 @@
import { QQLevel, Sex, User } from './user';
import { QQLevel, Sex } from './user';
export interface KickMemberInfo {
optFlag: number,
optOperate: number,
optMemberUid: string,
optBytesMsg: string,
}
export interface KickMemberV2Req{
//getGroupDetailInfo GroupCode,GroupInfoSource
export enum GroupInfoSource {
KUNSPECIFIED,
KBIGDATACARD,
KDATACARD,
KNOTICE,
KAIO,
KRECENTCONTACT,
KMOREPANEL
}
export interface GroupExt0xEF0InfoFilter {
bindGuildId: number;
blacklistExpireTime: number;
companyId: number;
essentialMsgPrivilege: number;
essentialMsgSwitch: number;
fullGroupExpansionSeq: number;
fullGroupExpansionSwitch: number;
gangUpId: number;
groupAioBindGuildId: number;
groupBindGuildIds: number;
groupBindGuildSwitch: number;
groupExcludeGuildIds: number;
groupExtFlameData: number;
groupFlagPro1: number;
groupInfoExtSeq: number;
groupOwnerId: number;
groupSquareSwitch: number;
hasGroupCustomPortrait: number;
inviteRobotMemberExamine: number;
inviteRobotMemberSwitch: number;
inviteRobotSwitch: number;
isLimitGroupRtc: number;
lightCharNum: number;
luckyWord: number;
luckyWordId: number;
msgEventSeq: number;
qqMusicMedalSwitch: number;
reserve: number;
showPlayTogetherSwitch: number;
starId: number;
todoSeq: number;
viewedMsgDisappearTime: number;
}
export interface KickMemberV2Req {
groupCode: string,
kickFlag: number,
kickList: Array<KickMemberInfo>,
kickListUids: Array<string>,
kickMsg: string
}
export enum DataSource {
LOCAL,
REMOTE
}
export enum GroupListUpdateType {
REFRESHALL,
GETALL,
MODIFIED,
REMOVE
}
export interface GroupMemberCache {
group: {
data: GroupMember[];
isExpired: boolean;
}
};
isExpired: boolean;
}
export interface Group {
groupCode: string,
createTime?: string,//高版本才有

View File

@@ -1,4 +1,4 @@
import { GroupMemberRole } from './group';
import { GroupMemberRole } from '@/core';
export interface Peer {
chatType: ChatType;
@@ -145,6 +145,7 @@ export interface TaskTopMsgElement {
iconUrl: string;
topMsgType: number;
}
export enum NTMsgType {
KMSGTYPEARKSTRUCT = 11,
KMSGTYPEFACEBUBBLE = 24,
@@ -168,6 +169,7 @@ export enum NTMsgType {
KMSGTYPEVIDEO = 7,
KMSGTYPEWALLET = 10
}
export interface SendTaskTopMsgElement {
elementType: ElementType.TASKTOPMSG;
elementId: string;
@@ -355,6 +357,7 @@ export enum NTMsgAtType {
ATTYPESUMMONROLE = 256,
ATTYPEUNKNOWN = 0
}
export interface SendPicElement {
elementType: ElementType.PIC;
elementId: string;
@@ -511,6 +514,7 @@ export enum AtType {
atAll = 1,
atUser = 2
}
// 来自Android分析
export enum ChatType {
KCHATTYPEADELIE = 42,
@@ -626,6 +630,7 @@ export enum NTGrayTipElementSubTypeV2 {
GRAYTIP_ELEMENT_SUBTYPE_WALLET = 16,
GRAYTIP_ELEMENT_SUBTYPE_XMLMSG = 12,
}
export interface GrayTipElement {
subElementType: NTGrayTipElementSubTypeV2;
revokeElement: {
@@ -848,12 +853,14 @@ export interface MultiForwardMsgElement {
resId: string;
fileName: string;
}
export enum SendStatusType {
KSEND_STATUS_FAILED = 0,
KSEND_STATUS_SENDING = 1,
KSEND_STATUS_SUCCESS = 2,
KSEND_STATUS_SUCCESS_NOSEQ = 3
}
export interface RawMessage {
parentMsgPeer: Peer;
@@ -923,4 +930,4 @@ export interface RawMessage {
records: RawMessage[];
elements: MessageElement[];
}
}

View File

@@ -16,6 +16,7 @@ export enum GroupNotifyMsgType {
TRANSFER_GROUP_NOTIFY_OLDOWNER,
TRANSFER_GROUP_NOTIFY_ADMIN
}
export interface GroupNotifies {
doubt: boolean;
nextStartSeq: string;
@@ -29,17 +30,20 @@ export enum GroupNotifyMsgStatus {
KREFUSED,//拒绝
KIGNORED//忽略
}
export enum GroupInviteStatus {
INIT,
WAIT_TO_APPROVE,
JOINED,
REFUSED_BY_ADMINI_STRATOR
}
export enum GroupInviteType {
BYBUDDY,
BYGROUPMEMBER,
BYDISCUSSMEMBER
}
export interface GroupNotify {
seq: string; // 通知序列号
type: GroupNotifyMsgType;

View File

@@ -57,7 +57,7 @@ export interface WebApiGroupMemberRet {
export interface WebApiGroupNoticeFeed {
u: number;//发送者
fid: string;//fid
fid: string;//fid,notice_id
pubt: number;//时间
msg: {
text: string

View File

@@ -7,24 +7,28 @@
"appid": 537240645,
"qua": "V1_LNX_NQ_3.2.12_27206_GW_B"
},
"3.2.12-27254":{
"3.2.12-27254": {
"appid": 537240795,
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
},
"9.9.15-27187":{
"9.9.15-27187": {
"appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27187_GW_B"
},
"9.9.15-27206":{
"9.9.15-27206": {
"appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27206_GW_B"
},
"9.9.15-27254":{
"9.9.15-27254": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27254_GW_B"
},
"9.9.15-27333": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B"
},
"9.9.15-27391": {
"appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B"
}
}
}

View File

@@ -1,4 +1,4 @@
import { ConfigBase } from "@/common/utils/ConfigBase";
import { ConfigBase } from '@/common/utils/config-base';
import napCatDefaultConfig from '@/core/external/napcat.json';
import { NapCatCore } from '@/core';
@@ -7,7 +7,7 @@ export type NapCatConfig = typeof napCatDefaultConfig;
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export class NapCatConfigLoader extends ConfigBase<NapCatConfig> {
constructor(coreContext: NapCatCore, configPath: string) {
super('napcat', coreContext, configPath);
constructor(core: NapCatCore, configPath: string) {
super('napcat', core, configPath);
}
}

View File

@@ -1,4 +1,3 @@
export class NodeIKernelFileAssistantListener {
onFileStatusChanged(...args: unknown[]) {
}

View File

@@ -1,4 +1,3 @@
export class NodeIKernelLoginListener {
onLoginConnected(...args: any[]): void {
}

View File

@@ -259,7 +259,7 @@ export class NodeIKernelMsgListener {
}
onRecvSysMsg(arrayList: unknown) {
onRecvSysMsg(arrayList: Array<number>) {
}

View File

@@ -1,9 +1,9 @@
export class NodeIKernelRecentContactListener {
export class NodeIKernelRecentContactListener {
onDeletedContactsNotify(...args: unknown[]) {
}
onRecentContactNotification(...args: unknown[]) {
onRecentContactNotification(msgList: any, arg0: { msgListUnreadCnt: string }, arg1: number) {
}

View File

@@ -1,4 +1,4 @@
export class NodeIKernelRobotListener{
export class NodeIKernelRobotListener {
onRobotFriendListChanged(...args: unknown[]) {
}

View File

@@ -0,0 +1,39 @@
import { ChatType } from '@/core';
export interface NodeIKernelSearchListener_Polyfill {
onSearchFileKeywordsResult(params: {
searchId: string,
hasMore: boolean,
resultItems: {
chatType: ChatType,
buddyChatInfo: any[],
discussChatInfo: any[],
groupChatInfo: {
groupCode: string,
isConf: boolean,
hasModifyConfGroupFace: boolean,
hasModifyConfGroupName: boolean,
groupName: string,
remark: string
}[],
dataLineChatInfo: any[],
tmpChatInfo: any[],
msgId: string,
msgSeq: string,
msgTime: string,
senderUid: string,
senderNick: string,
senderRemark: string,
senderCard: string,
elemId: string,
elemType: number,
fileSize: string,
filePath: string,
fileName: string,
hits: {
start: number,
end: number
}[]
}[]
}): void;
}

View File

@@ -9,4 +9,32 @@ export * from './NodeIKernelProfileListener';
export * from './NodeIKernelTicketListener';
export * from './NodeIKernelStorageCleanListener';
export * from './NodeIKernelFileAssistantListener';
export * from './NodeIKernelSearchListener_Polyfill';
import type {
NodeIKernelBuddyListener,
NodeIKernelFileAssistantListener,
NodeIKernelGroupListener,
NodeIKernelLoginListener,
NodeIKernelMsgListener,
NodeIKernelProfileListener,
NodeIKernelRobotListener,
NodeIKernelSessionListener,
NodeIKernelStorageCleanListener,
NodeIKernelTicketListener,
NodeIKernelSearchListener_Polyfill,
} from '.';
export type ListenerNamingMapping = {
NodeIKernelSessionListener: NodeIKernelSessionListener;
NodeIKernelLoginListener: NodeIKernelLoginListener;
NodeIKernelMsgListener: NodeIKernelMsgListener;
NodeIKernelGroupListener: NodeIKernelGroupListener;
NodeIKernelBuddyListener: NodeIKernelBuddyListener;
NodeIKernelProfileListener: NodeIKernelProfileListener;
NodeIKernelRobotListener: NodeIKernelRobotListener;
NodeIKernelTicketListener: NodeIKernelTicketListener;
NodeIKernelStorageCleanListener: NodeIKernelStorageCleanListener;
NodeIKernelFileAssistantListener: NodeIKernelFileAssistantListener;
NodeIKernelSearchListener: NodeIKernelSearchListener_Polyfill;
};

View File

@@ -1,18 +1,23 @@
import { IGroupListener } from '@/core/listeners/NodeIKernelGroupListener';
import { NodeIKernelGroupListener } from '@/core/listeners/NodeIKernelGroupListener';
import {
GroupExt0xEF0InfoFilter,
GroupExtParam,
GroupMember,
GroupMemberRole,
GroupNotifyMsgType,
GroupRequestOperateTypes,
KickMemberV2Req
KickMemberV2Req,
} from '@/core/entities';
import { GeneralCallResult } from '@/core/services/common';
//高版本的接口不应该随意使用 使用应该严格进行pr审核 同时部分ipc中未出现的接口不要过于依赖 应该做好数据兜底
export interface NodeIKernelGroupService {
//getGroupExt0xEF0Info(this.$enableGroupCodes, this.$bannedGroupCodes, this.$filter, this.$forceFetch
getGroupExt0xEF0Info(enableGroupCodes: string[], bannedGroupCodes: string[], filter: GroupExt0xEF0InfoFilter, forceFetch: boolean):
Promise<GeneralCallResult & { result: { groupExtInfos: Map<string, any> }}>;
kickMemberV2(param: KickMemberV2Req): Promise<GeneralCallResult>;
quitGroupV2(param: { groupCode: string; needDeleteLocalMsg: boolean; }): Promise<GeneralCallResult>;
getMemberCommonInfo(Req: {
@@ -108,7 +113,7 @@ export interface NodeIKernelGroupService {
setHeader(uid: string, path: string): unknown;
addKernelGroupListener(listener: IGroupListener): number;
addKernelGroupListener(listener: NodeIKernelGroupListener): number;
removeKernelGroupListener(listenerId: unknown): void;
@@ -209,7 +214,7 @@ export interface NodeIKernelGroupService {
getGroupBulletin(groupCode: string): unknown;
deleteGroupBulletin(groupCode: string, seq: string, feedId: string): void;
deleteGroupBulletin(groupCode: string, seq: string, noticeId: string): void;
publishGroupBulletin(groupCode: string, pskey: string, data: any): Promise<GeneralCallResult>;

View File

@@ -12,6 +12,7 @@ export interface QueryMsgsParams {
isReverseOrder: boolean,
isIncludeCurrent: boolean
}
export interface TmpChatInfoApi {
errMsg: string;
result: number;
@@ -511,11 +512,11 @@ export interface NodeIKernelMsgService {
result: number,
errMsg: string,
emojiLikesList:
Array<{
tinyId: string,
nickName: string,
headUrl: string
}>,
Array<{
tinyId: string,
nickName: string,
headUrl: string
}>,
cookie: string,
isLastPage: boolean,
isFirstPage: boolean

View File

@@ -1,6 +1,6 @@
import { AnyCnameRecord } from 'node:dns';
import { BizKey, ModifyProfileParams, SimpleInfo, UserDetailInfoByUin } from '../entities';
import { NodeIKernelProfileListener } from '../listeners';
import { BizKey, ModifyProfileParams, SimpleInfo, UserDetailInfoByUin, UserDetailInfoByUinV2 } from '@/core';
import { NodeIKernelProfileListener } from '@/core';
import { GeneralCallResult } from '@/core/services/common';
export enum UserDetailSource {
@@ -86,7 +86,7 @@ export interface NodeIKernelProfileService {
getUserDetailInfoWithBizInfo(uid: string, Biz: BizKey[]): Promise<GeneralCallResult>;
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUin>;
getUserDetailInfoByUin(uin: string): Promise<UserDetailInfoByUinV2>;
getZplanAvatarInfos(args: string[]): Promise<unknown>;

View File

@@ -14,3 +14,45 @@ export * from './NodeIKernelRobotService';
export * from './NodeIKernelRichMediaService';
export * from './NodeIKernelDbToolsService';
export * from './NodeIKernelTipOffService';
export * from './NodeIKernelSearchService';
export * from './NodeIKernelCollectionService';
import type {
NodeIKernelAvatarService,
NodeIKernelBuddyService,
NodeIKernelDbToolsService,
NodeIKernelFileAssistantService,
NodeIKernelGroupService,
NodeIKernelLoginService,
NodeIKernelMsgService,
NodeIKernelOnlineStatusService,
NodeIKernelProfileLikeService,
NodeIKernelProfileService,
NodeIKernelRichMediaService,
NodeIKernelRobotService,
NodeIKernelStorageCleanService,
NodeIKernelTicketService,
NodeIKernelTipOffService,
NodeIKernelSearchService,
NodeIKernelCollectionService,
} from '.';
export type ServiceNamingMapping = {
NodeIKernelAvatarService: NodeIKernelAvatarService;
NodeIKernelBuddyService: NodeIKernelBuddyService;
NodeIKernelFileAssistantService: NodeIKernelFileAssistantService;
NodeIKernelGroupService: NodeIKernelGroupService;
NodeIKernelLoginService: NodeIKernelLoginService;
NodeIKernelMsgService: NodeIKernelMsgService;
NodeIKernelOnlineStatusService: NodeIKernelOnlineStatusService;
NodeIKernelProfileLikeService: NodeIKernelProfileLikeService;
NodeIKernelProfileService: NodeIKernelProfileService;
NodeIKernelTicketService: NodeIKernelTicketService;
NodeIKernelStorageCleanService: NodeIKernelStorageCleanService;
NodeIKernelRobotService: NodeIKernelRobotService;
NodeIKernelRichMediaService: NodeIKernelRichMediaService;
NodeIKernelDbToolsService: NodeIKernelDbToolsService;
NodeIKernelTipOffService: NodeIKernelTipOffService;
NodeIKernelSearchService: NodeIKernelSearchService,
NodeIKernelCollectionService: NodeIKernelCollectionService;
};

View File

@@ -1,5 +1,5 @@
import { LogWrapper } from '@/common/utils/log';
import { QQBasicInfoWrapper } from '@/common/utils/QQBasicInfo';
import { QQBasicInfoWrapper } from '@/common/utils/qq-basic-info';
import { NapCatCoreWorkingEnv, NodeIKernelLoginService, NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core';
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from '../apis';
import { NTQQCollectionApi } from '../apis/collection';
@@ -15,7 +15,7 @@ export interface InstanceContext {
readonly pathWrapper: NapCatPathWrapper;
}
export interface NTApiContext {
export interface StableNTApiWrapper {
FileApi: NTQQFileApi,
SystemApi: NTQQSystemApi,
CollectionApi: NTQQCollectionApi,

View File

@@ -1,7 +1,5 @@
import { NodeIDependsAdapter, NodeIDispatcherAdapter, NodeIGlobalAdapter } from '../adapters';
import {
NodeIKernelSessionListener
} from '../listeners';
import { NodeIKernelSessionListener } from '@/core';
import {
NodeIKernelAvatarService,
NodeIKernelBuddyService,
@@ -13,9 +11,9 @@ import {
NodeIKernelRichMediaService,
NodeIKernelTicketService,
NodeIKernelTipOffService,
} from '../services';
import { NodeIKernelStorageCleanService } from '../services/NodeIKernelStorageCleanService';
import { NodeIKernelRobotService } from '../services/NodeIKernelRobotService';
} from '@/core';
import { NodeIKernelStorageCleanService } from '@/core';
import { NodeIKernelRobotService } from '@/core';
import { NodeIKernelNodeMiscService } from '../services/NodeIKernelNodeMiscService';
import { NodeIKernelUixConvertService } from '../services/NodeIKernelUixConvertService';
import { NodeIKernelMsgBackupService } from '../services/NodeIKernelMsgBackupService';
@@ -31,6 +29,7 @@ import { NodeIKernelECDHService } from '../services/NodeIKernelECDHService';
export interface NodeQQNTWrapperUtil {
get(): unknown;
// eslint-disable-next-line @typescript-eslint/no-misused-new
new(): NodeQQNTWrapperUtil;

View File

@@ -1,6 +1,6 @@
//LiteLoader需要提供部分IPC接口以便于其他插件调用
const { ipcMain } = require('electron');
const napcat= require('./napcat.cjs');
ipcMain.handle("napcat_get_webtoken", async (event, arg) => {
const napcat = require('./napcat.cjs');
ipcMain.handle('napcat_get_webtoken', async (event, arg) => {
return napcat.NCgetWebUiUrl();
});

View File

@@ -1,7 +1,7 @@
import { NapCatPathWrapper } from '@/common/framework/napcat';
import { LogWrapper } from '@/common/utils/log';
import { proxiedListenerOf } from '@/common/utils/proxy-handler';
import { QQBasicInfoWrapper } from '@/common/utils/QQBasicInfo';
import { QQBasicInfoWrapper } from '@/common/utils/qq-basic-info';
import { loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core/core';
import { InstanceContext } from '@/core';
import { SelfInfo } from '@/core/entities';
@@ -14,8 +14,9 @@ import { NapCatOneBot11Adapter } from '@/onebot';
//Framework ES入口文件
export async function getWebUiUrl() {
const WebUiConfigData = (await WebUiConfig.GetWebUIConfig());
return "http://127.0.0.1:" + WebUiConfigData.port + '/webui/?token=' + WebUiConfigData.token;
return 'http://127.0.0.1:' + WebUiConfigData.port + '/webui/?token=' + WebUiConfigData.token;
}
export async function NCoreInitFramework(
session: NodeIQQNTWrapperSession,
loginService: NodeIKernelLoginService,

View File

@@ -1,11 +1,10 @@
const { contextBridge } = require('electron')
const { ipcRenderer } = require('electron')
const { contextBridge } = require('electron');
const { ipcRenderer } = require('electron');
const napcat = {
getWebUiUrl: async () => {
return ipcRenderer.invoke("napcat_get_webtoken")
}
}
return ipcRenderer.invoke('napcat_get_webtoken');
},
};
// 在window对象下导出只读对象
contextBridge.exposeInMainWorld('napcat', napcat)
contextBridge.exposeInMainWorld('napcat', napcat);

View File

@@ -1,6 +1,5 @@
export const onSettingWindowCreated = async (view) => {
// view.style.width = "100%";
// view.style.height = "100%";
// //添加iframe
@@ -14,7 +13,7 @@ export const onSettingWindowCreated = async (view) => {
// //有滚动条何尝不是一种美
// view.appendChild(iframe);
let webui = await window.napcat.getWebUiUrl();
let panel = `
view.innerHTML = `
<setting-section data-title="">
<setting-panel>
<setting-list data-direction="column">
@@ -30,9 +29,8 @@ export const onSettingWindowCreated = async (view) => {
</setting-panel>
</setting-section>
`;
view.innerHTML = panel;
view.querySelector(".nc_openwebui").addEventListener("click", () => {
window.open(webui, "_blank");
view.querySelector('.nc_openwebui').addEventListener('click', () => {
window.open(webui, '_blank');
});
view.querySelector(".nc_webui").innerText = webui;
};
view.querySelector('.nc_webui').innerText = webui;
};

View File

@@ -1,4 +0,0 @@
# NewWebui
基于Vue3实现的现代化轻量化NapCat管理面板
## 进度
画饼

View File

@@ -8,19 +8,19 @@ import { NapCatOneBot11Adapter } from '@/onebot';
abstract class BaseAction<PayloadType, ReturnDataType> {
actionName: ActionName = ActionName.Unknown;
CoreContext: NapCatCore;
core: NapCatCore;
private validate: undefined | ValidateFunction<any> = undefined;
PayloadSchema: any = undefined;
OneBotContext: NapCatOneBot11Adapter;
payloadSchema: any = undefined;
obContext: NapCatOneBot11Adapter;
constructor(onebotContext: NapCatOneBot11Adapter, coreContext: NapCatCore) {
this.OneBotContext = onebotContext;
this.CoreContext = coreContext;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
this.obContext = obContext;
this.core = core;
}
protected async check(payload: PayloadType): Promise<BaseCheckResult> {
if (this.PayloadSchema) {
this.validate = new Ajv({ allowUnionTypes: true }).compile(this.PayloadSchema);
if (this.payloadSchema) {
this.validate = new Ajv({ allowUnionTypes: true }).compile(this.payloadSchema);
}
if (this.validate && !this.validate(payload)) {
const errors = this.validate.errors as ErrorObject[];
@@ -46,7 +46,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
const resData = await this._handle(payload);
return OB11Response.ok(resData);
} catch (e: any) {
this.CoreContext.context.logger.logError('发生错误', e);
this.core.context.logger.logError('发生错误', e);
return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200);
}
}
@@ -60,7 +60,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
const resData = await this._handle(payload);
return OB11Response.ok(resData, echo);
} catch (e: any) {
this.CoreContext.context.logger.logError('发生错误', e);
this.core.context.logger.logError('发生错误', e);
return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo);
}
}

View File

@@ -15,13 +15,13 @@ type Payload = FromSchema<typeof SchemaData>;
export class CreateCollection extends BaseAction<Payload, any> {
actionName = ActionName.CreateCollection;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
return await this.CoreContext.apis.CollectionApi.createCollection(
this.CoreContext.selfInfo.uin,
this.CoreContext.selfInfo.uid,
this.CoreContext.selfInfo.nick,
return await this.core.apis.CollectionApi.createCollection(
this.core.selfInfo.uin,
this.core.selfInfo.uid,
this.core.selfInfo.nick,
payload.brief, payload.rawData,
);
}

View File

@@ -13,11 +13,11 @@ type Payload = FromSchema<typeof SchemaData>;
export class FetchCustomFace extends BaseAction<Payload, string[]> {
actionName = ActionName.FetchCustomFace;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
//48 可能正好是QQ需要的一个页面的数量 Tagged Mlikiowa
const ret = await this.CoreContext.apis.MsgApi.fetchFavEmojiList(+(payload.count ?? 48));
const ret = await this.core.apis.MsgApi.fetchFavEmojiList(+(payload.count ?? 48));
return ret.emojiInfoList.map(e => e.url);
}
}

View File

@@ -2,7 +2,7 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { MessageUnique } from '@/common/utils/MessageUnique';
import { MessageUnique } from '@/common/utils/message-unique';
const SchemaData = {
type: 'object',
@@ -21,9 +21,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class FetchEmojiLike extends BaseAction<Payload, any> {
actionName = ActionName.FetchEmojiLike;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
if (!msgIdPeer) throw new Error('消息不存在');
const msg = (await NTQQMsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];

View File

@@ -15,9 +15,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class GetCollectionList extends BaseAction<Payload, any> {
actionName = ActionName.GetCollectionList;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQCollectionApi = this.CoreContext.apis.CollectionApi;
const NTQQCollectionApi = this.core.apis.CollectionApi;
return await NTQQCollectionApi.getAllCollection(parseInt(payload.category.toString()), +(payload.count ?? 1));
}
}

View File

@@ -1,13 +1,14 @@
import { OB11Constructor } from '@/onebot/helper/converter';
import { OB11Entities } from '@/onebot/helper/entities';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
export class GetFriendWithCategory extends BaseAction<void, any> {
actionName = ActionName.GetFriendsWithCategory;
async _handle(payload: void) {
return (await this.CoreContext.apis.FriendApi.getBuddyV2ExWithCate(true)).map(category => ({
return (await this.core.apis.FriendApi.getBuddyV2ExWithCate(true)).map(category => ({
...category,
buddyList: OB11Constructor.friendsV2(category.buddyList),
buddyList: OB11Entities.friendsV2(category.buddyList),
}));
}
}

View File

@@ -11,7 +11,7 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
actionName = ActionName.GetGroupIgnoreAddRequest;
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
const data = await this.CoreContext.apis.GroupApi.getGroupIgnoreNotifies();
const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies();
// log(data);
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
// const returnData: OB11GroupRequestNotify[] = [];

View File

@@ -5,8 +5,8 @@ export class GetProfileLike extends BaseAction<void, any> {
actionName = ActionName.GetProfileLike;
async _handle(payload: void) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const ret = await NTQQUserApi.getProfileLike(this.CoreContext.selfInfo.uid);
const NTQQUserApi = this.core.apis.UserApi;
const ret = await NTQQUserApi.getProfileLike(this.core.selfInfo.uid);
const listdata: any[] = ret.info.userLikeInfos[0].favoriteInfo.userInfos;
for (let i = 0; i < listdata.length; i++) {
listdata[i].uin = parseInt((await NTQQUserApi.getUinByUidV2(listdata[i].uid)) || '');

View File

@@ -5,7 +5,7 @@ export class GetRobotUinRange extends BaseAction<void, Array<any>> {
actionName = ActionName.GetRobotUinRange;
async _handle(payload: void) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQUserApi = this.core.apis.UserApi;
return await NTQQUserApi.getRobotUinRange();
}
}

View File

@@ -3,6 +3,7 @@ import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { checkFileReceived, uri2local } from '@/common/utils/file';
import fs from 'fs';
const SchemaData = {
type: 'object',
properties: {
@@ -15,11 +16,11 @@ type Payload = FromSchema<typeof SchemaData>;
export class OCRImage extends BaseAction<Payload, any> {
actionName = ActionName.OCRImage;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQSystemApi = this.CoreContext.apis.SystemApi;
const { path, isLocal, errMsg, success } = (await uri2local(this.CoreContext.NapCatTempPath, payload.image));
const NTQQSystemApi = this.core.apis.SystemApi;
const { path, isLocal, success } = (await uri2local(this.core.NapCatTempPath, payload.image));
if (!success) {
throw `OCR ${payload.image}失败,image字段可能格式不正确`;
}

View File

@@ -8,7 +8,7 @@ const SchemaData = {
properties: {
eventType: { type: 'string' },
group_id: { type: 'string' },
user_id: { type: 'string' }
user_id: { type: 'string' },
},
required: ['eventType'],
} as const satisfies JSONSchema;
@@ -19,26 +19,25 @@ export class SetInputStatus extends BaseAction<Payload, any> {
actionName = ActionName.SetInputStatus;
async _handle(payload: Payload) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi;
let peer: Peer;
if (payload.group_id) {
peer = {
chatType: ChatType.KCHATTYPEGROUP,
peerUid: payload.group_id
peerUid: payload.group_id,
};
} else if (payload.user_id) {
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id);
if (!uid) throw new Error('uid is empty');
peer = {
chatType: ChatType.KCHATTYPEC2C,
peerUid: uid
peerUid: uid,
};
} else {
throw new Error('请指定 group_id 或 user_id');
}
const ret = await NTQQMsgApi.sendShowInputStatusReq(peer, parseInt(payload.eventType));
return ret;
return await NTQQMsgApi.sendShowInputStatusReq(peer, parseInt(payload.eventType));
}
}

View File

@@ -14,10 +14,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class SetLongNick extends BaseAction<Payload, any> {
actionName = ActionName.SetLongNick;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQUserApi = this.core.apis.UserApi;
const ret = await NTQQUserApi.setLongNick(payload.longNick);
return ret;
}

View File

@@ -17,14 +17,14 @@ type Payload = FromSchema<typeof SchemaData>;
export class SetOnlineStatus extends BaseAction<Payload, null> {
actionName = ActionName.SetOnlineStatus;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQUserApi = this.core.apis.UserApi;
const ret = await NTQQUserApi.setSelfOnlineStatus(
parseInt(payload.status.toString()),
parseInt(payload.extStatus.toString()),
parseInt(payload.batteryStatus.toString())
parseInt(payload.batteryStatus.toString()),
);
if (ret.result !== 0) {
throw new Error('设置在线状态失败');

View File

@@ -24,8 +24,8 @@ export default class SetAvatar extends BaseAction<Payload, null> {
}
async _handle(payload: Payload): Promise<null> {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const { path, isLocal, errMsg, success } = (await uri2local(this.CoreContext.NapCatTempPath, payload.file));
const NTQQUserApi = this.core.apis.UserApi;
const { path, isLocal, errMsg, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) {
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
}

View File

@@ -16,11 +16,11 @@ type Payload = FromSchema<typeof SchemaData>;
export class SharePeer extends BaseAction<Payload, any> {
actionName = ActionName.SharePeer;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
if (payload.group_id) {
return await NTQQGroupApi.getGroupRecommendContactArkJson(payload.group_id);
} else if (payload.user_id) {
@@ -41,10 +41,10 @@ type PayloadGroupEx = FromSchema<typeof SchemaDataGroupEx>;
export class ShareGroupEx extends BaseAction<PayloadGroupEx, any> {
actionName = ActionName.ShareGroupEx;
PayloadSchema = SchemaDataGroupEx;
payloadSchema = SchemaDataGroupEx;
async _handle(payload: PayloadGroupEx) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
return await NTQQGroupApi.getArkJsonGroupShare(payload.group_id);
}
}

View File

@@ -17,10 +17,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class TranslateEnWordToZn extends BaseAction<Payload, Array<any> | null> {
actionName = ActionName.TranslateEnWordToZn;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQSystemApi = this.CoreContext.apis.SystemApi;
const NTQQSystemApi = this.core.apis.SystemApi;
const ret = await NTQQSystemApi.translateEnWordToZn(payload.words);
if (ret.result !== 0) {
throw new Error('翻译失败');

View File

@@ -15,10 +15,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class DelGroupFile extends BaseAction<Payload, any> {
actionName = ActionName.DelGroupFile;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
return await NTQQGroupApi.DelGroupFile(payload.group_id.toString(), [payload.file_id]);
}
}

View File

@@ -15,10 +15,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class DelGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.DelGroupFileFolder;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
return (await NTQQGroupApi.DelGroupFileFolder(payload.group_id.toString(), payload.folder_id)).groupFileCommonResult;
}
}

View File

@@ -26,14 +26,14 @@ const GetFileBase_PayloadSchema = {
} as const satisfies JSONSchema;
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
PayloadSchema: any = GetFileBase_PayloadSchema;
payloadSchema: any = GetFileBase_PayloadSchema;
async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
const NTQQFriendApi = this.CoreContext.apis.FriendApi;
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQFileApi = this.CoreContext.apis.FileApi;
const NTQQFriendApi = this.core.apis.FriendApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQFileApi = this.core.apis.FileApi;
let UuidData: {
high: string;
low: string;
@@ -90,7 +90,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
return res;
}
} catch {
this.CoreContext.context.logger.logDebug('GetFileBase Mode - 1 Error');
this.core.context.logger.logDebug('GetFileBase Mode - 1 Error');
}
const NTSearchNameResult = (await NTQQFileApi.searchfile([payload.file])).resultItems;
@@ -210,7 +210,7 @@ interface GetFile_Payload extends GetFile_Payload_Internal {
export default class GetFile extends GetFileBase {
actionName = ActionName.GetFile;
PayloadSchema = GetFile_PayloadSchema;
payloadSchema = GetFile_PayloadSchema;
async _handle(payload: GetFile_Payload): Promise<GetFileResponse> {
payload.file = payload.file_id;

View File

@@ -14,10 +14,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileCount extends BaseAction<Payload, { count: number }> {
actionName = ActionName.GetGroupFileCount;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const ret = await NTQQGroupApi.GetGroupFileCount([payload.group_id?.toString()]);
return { count: ret.groupFileCounts[0] };
}

View File

@@ -16,10 +16,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileList extends BaseAction<Payload, { FileList: Array<any> }> {
actionName = ActionName.GetGroupFileList;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const ret = await NTQQMsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: payload.file_count,

View File

@@ -15,10 +15,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class SetGroupFileFolder extends BaseAction<Payload, any> {
actionName = ActionName.SetGroupFileFolder;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
return (await NTQQGroupApi.CreatGroupFileFolder(payload.group_id.toString(), payload.folder_name)).resultWithGroupItem;
}
}

View File

@@ -30,12 +30,12 @@ type Payload = FromSchema<typeof SchemaData>;
export default class GoCQHTTPDownloadFile extends BaseAction<Payload, FileResponse> {
actionName = ActionName.GoCQHTTP_DownloadFile;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<FileResponse> {
const isRandomName = !payload.name;
const name = payload.name || randomUUID();
const filePath = joinPath(this.CoreContext.NapCatTempPath, name);
const filePath = joinPath(this.core.NapCatTempPath, name);
if (payload.base64) {
fs.writeFileSync(filePath, payload.base64, 'base64');
@@ -51,7 +51,7 @@ export default class GoCQHTTPDownloadFile extends BaseAction<Payload, FileRespon
if (isRandomName) {
// 默认实现要名称未填写时文件名为文件 md5
const md5 = await calculateFileMD5(filePath);
const newPath = joinPath(this.CoreContext.NapCatTempPath, md5);
const newPath = joinPath(this.core.NapCatTempPath, md5);
fs.renameSync(filePath, newPath);
return { file: newPath };
}

View File

@@ -1,8 +1,8 @@
import BaseAction from '../BaseAction';
import { OB11ForwardMessage, OB11Message, OB11MessageData } from '@/onebot';
import { OB11ForwardMessage } from '@/onebot';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique';
import { MessageUnique } from '@/common/utils/message-unique';
const SchemaData = {
type: 'object',
@@ -14,16 +14,12 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>;
interface Response {
messages: (OB11Message & { content: OB11MessageData })[];
}
export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
actionName = ActionName.GoCQHTTP_GetForwardMsg;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> {
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const msgId = payload.message_id || payload.id;
if (!msgId) {
throw Error('message_id is required');
@@ -39,7 +35,7 @@ export class GoCQHTTPGetForwardMsgAction extends BaseAction<Payload, any> {
}
const msgList = data.msgList;
const messages = (await Promise.all(msgList.map(async msg => {
const resMsg = await this.OneBotContext.apiContext.MsgApi
const resMsg = await this.obContext.apis.MsgApi
.parseMessage(msg);
if (!resMsg) return;
resMsg.message_id = MessageUnique.createMsg({

View File

@@ -3,7 +3,7 @@ import { OB11Message } from '@/onebot';
import { ActionName } from '../types';
import { ChatType, RawMessage } from '@/core/entities';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique';
import { MessageUnique } from '@/common/utils/message-unique';
interface Response {
messages: OB11Message[];
@@ -15,7 +15,7 @@ const SchemaData = {
user_id: { type: ['number', 'string'] },
message_seq: { type: 'number' },
count: { type: ['number', 'string'] },
reverseOrder: { type: 'boolean' },
reverseOrder: { type: ['boolean', 'string'] },
},
required: ['user_id'],
} as const satisfies JSONSchema;
@@ -24,16 +24,16 @@ type Payload = FromSchema<typeof SchemaData>;
export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
actionName = ActionName.GetFriendMsgHistory;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<Response> {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQFriendApi = this.CoreContext.apis.FriendApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const NTQQFriendApi = this.core.apis.FriendApi;
//处理参数
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
const MsgCount = +(payload.count ?? 20);
const isReverseOrder = payload.reverseOrder || true;
const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder;
if (!uid) throw `记录${payload.user_id}不存在`;
const friend = await NTQQFriendApi.isBuddy(uid);
const peer = { chatType: friend ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid: uid };
@@ -53,7 +53,7 @@ export default class GetFriendMsgHistory extends BaseAction<Payload, Response> {
}));
//转换消息
const ob11MsgList = (await Promise.all(
msgList.map(msg => this.OneBotContext.apiContext.MsgApi.parseMessage(msg)))
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg)))
).filter(msg => msg !== undefined);
return { 'messages': ob11MsgList };
}

View File

@@ -16,13 +16,13 @@ type Payload = FromSchema<typeof SchemaData>;
export class GetGroupHonorInfo extends BaseAction<Payload, Array<any>> {
actionName = ActionName.GetGroupHonorInfo;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
if (!payload.type) {
payload.type = WebHonorType.ALL;
}
const NTQQWebApi = this.CoreContext.apis.WebApi;
const NTQQWebApi = this.core.apis.WebApi;
return await NTQQWebApi.getGroupHonorInfo(payload.group_id.toString(), payload.type);
}
}

View File

@@ -3,7 +3,7 @@ import { OB11Message } from '@/onebot';
import { ActionName } from '../types';
import { ChatType, Peer, RawMessage } from '@/core/entities';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique';
import { MessageUnique } from '@/common/utils/message-unique';
interface Response {
messages: OB11Message[];
@@ -15,7 +15,7 @@ const SchemaData = {
group_id: { type: ['number', 'string'] },
message_seq: { type: 'number' },
count: { type: ['number', 'string'] },
reverseOrder: { type: 'boolean' },
reverseOrder: { type: ['boolean', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
@@ -24,12 +24,12 @@ type Payload = FromSchema<typeof SchemaData>;
export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Response> {
actionName = ActionName.GoCQHTTP_GetGroupMsgHistory;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<Response> {
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQMsgApi = this.core.apis.MsgApi;
//处理参数
const isReverseOrder = payload.reverseOrder || true;
const isReverseOrder = typeof payload.reverseOrder === 'string' ? payload.reverseOrder === 'true' : !!payload.reverseOrder;
const MsgCount = +(payload.count ?? 20);
const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() };
//拉取消息
@@ -48,7 +48,7 @@ export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Resp
//转换消息
const ob11MsgList = (await Promise.all(
msgList.map(msg => this.OneBotContext.apiContext.MsgApi.parseMessage(msg)))
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg)))
).filter(msg => msg !== undefined);
return { 'messages': ob11MsgList };
}

View File

@@ -15,7 +15,7 @@ export class GetOnlineClient extends BaseAction<void, Array<any>> {
async _handle(payload: void) {
//注册监听
const NTQQSystemApi = this.CoreContext.apis.SystemApi;
const NTQQSystemApi = this.core.apis.SystemApi;
NTQQSystemApi.getOnlineDev();
await sleep(500);

View File

@@ -1,6 +1,6 @@
import BaseAction from '../BaseAction';
import { OB11User, OB11UserSex } from '../../types';
import { OB11Constructor } from '@/onebot/helper/converter';
import { OB11User, OB11UserSex } from '@/onebot';
import { OB11Entities } from '@/onebot/helper/entities';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { calcQQLevel } from '@/common/utils/helper';
@@ -19,12 +19,12 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
actionName = ActionName.GoCQHTTP_GetStrangerInfo;
async _handle(payload: Payload): Promise<OB11User> {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQUserApi = this.core.apis.UserApi;
const user_id = payload.user_id.toString();
const extendData = await NTQQUserApi.getUserDetailInfoByUinV2(user_id);
const uid = (await NTQQUserApi.getUidByUinV2(user_id))!;
if (!uid || uid.indexOf('*') != -1) {
const ret = {
return {
...extendData.detail.simpleInfo.coreInfo,
...extendData.detail.commonExt,
...extendData.detail.simpleInfo.baseInfo,
@@ -36,11 +36,9 @@ export default class GoCQHTTPGetStrangerInfo extends BaseAction<Payload, OB11Use
qid: extendData.detail.simpleInfo.baseInfo.qid,
level: calcQQLevel(extendData.detail.commonExt?.qqLevel ?? 0) || 0,
login_days: 0,
uid: ''
};
return ret;
}
const data = { ...extendData, ...(await NTQQUserApi.getUserDetailInfo(uid)) };
return OB11Constructor.stranger(data);
return OB11Entities.stranger(data);
}
}

View File

@@ -1,4 +1,3 @@
import { handleQuickOperation } from '@/onebot/helper/quick';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { QuickAction, QuickActionEvent } from '@/onebot/types';
@@ -12,7 +11,9 @@ export class GoCQHTTPHandleQuickAction extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_HandleQuickAction;
async _handle(payload: Payload): Promise<null> {
handleQuickOperation(this.CoreContext, this.OneBotContext, payload.context, payload.operation).then().catch(this.CoreContext.context.logger.logError);
this.obContext.apis.QuickActionApi
.handleQuickOperation(payload.context, payload.operation)
.catch(this.core.context.logger.logError);
return null;
}
}

View File

@@ -10,8 +10,8 @@ const SchemaData = {
group_id: { type: ['number', 'string'] },
content: { type: 'string' },
image: { type: 'string' },
pinned: { type: 'number' },
confirmRequired: { type: 'number' },
pinned: { type: ['number', 'string'] },
confirmRequired: { type: ['number', 'string'] },
},
required: ['group_id', 'content'],
} as const satisfies JSONSchema;
@@ -22,7 +22,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_SendGroupNotice;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
let UploadImage: { id: string, width: number, height: number } | undefined = undefined;
if (payload.image) {
//公告图逻辑
@@ -31,7 +31,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
path,
isLocal,
success,
} = (await uri2local(this.CoreContext.NapCatTempPath, payload.image));
} = (await uri2local(this.core.NapCatTempPath, payload.image));
if (!success) {
throw `群公告${payload.image}设置失败,image字段可能格式不正确`;
}
@@ -49,14 +49,8 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
}
UploadImage = ImageUploadResult.picInfo;
}
let Notice_Pinned = 0;
let Notice_confirmRequired = 0;
if (!payload.pinned) {
Notice_Pinned = 0;
}
if (!payload.confirmRequired) {
Notice_confirmRequired = 0;
}
let Notice_Pinned = +(payload.pinned ?? 0);
let Notice_confirmRequired = +(payload.confirmRequired ?? 0);
const PublishGroupBulletinResult = await NTQQGroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, Notice_Pinned, Notice_confirmRequired);
if (PublishGroupBulletinResult.result != 0) {

View File

@@ -3,8 +3,6 @@ import { ActionName, BaseCheckResult } from '../types';
import * as fs from 'node:fs';
import { checkFileReceived, uri2local } from '@/common/utils/file';
// import { log } from "../../../common/utils";
interface Payload {
file: string,
group_id: number
@@ -27,8 +25,8 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
}
async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const { path, isLocal, errMsg, success } = (await uri2local(this.CoreContext.NapCatTempPath, payload.file));
const NTQQGroupApi = this.core.apis.GroupApi;
const { path, isLocal, errMsg, success } = (await uri2local(this.core.NapCatTempPath, payload.file));
if (!success) {
throw `头像${payload.file}设置失败,file字段可能格式不正确`;
}
@@ -42,7 +40,6 @@ export default class SetGroupPortrait extends BaseAction<Payload, any> {
if (!ret) {
throw `头像${payload.file}设置失败,api无返回`;
}
// log(`头像设置返回:${JSON.stringify(ret)}`)
if (ret['result'] == 1004022) {
throw `头像${payload.file}设置失败,文件可能不是图片格式或权限不足`;
} else if (ret['result'] != 0) {

View File

@@ -16,19 +16,22 @@ type Payload = FromSchema<typeof SchemaData>;
export class SetQQProfile extends BaseAction<Payload, any | null> {
actionName = ActionName.SetQQProfile;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const self = this.CoreContext.selfInfo;
const NTQQUserApi = this.core.apis.UserApi;
const self = this.core.selfInfo;
const OldProfile = await NTQQUserApi.getUserDetailInfo(self.uid);
const ret = await NTQQUserApi.modifySelfProfile({
return await NTQQUserApi.modifySelfProfile({
nick: payload.nickname,
longNick: (payload?.personal_note ?? OldProfile?.longNick) || '',
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,
});
return ret;
}
}

View File

@@ -2,7 +2,6 @@ import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { ChatType } from '@/core/entities';
import fs from 'fs';
import { sendMsg } from '@/onebot/action/msg/SendMsg';
import { uri2local } from '@/common/utils/file';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
@@ -22,19 +21,19 @@ type Payload = FromSchema<typeof SchemaData>;
export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_UploadGroupFile;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
let file = payload.file;
if (fs.existsSync(file)) {
file = `file://${file}`;
}
const downloadResult = await uri2local(this.CoreContext.NapCatTempPath, file);
const downloadResult = await uri2local(this.core.NapCatTempPath, file);
if (!downloadResult.success) {
throw new Error(downloadResult.errMsg);
}
const sendFileEle = await this.CoreContext.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name, payload.folder_id);
await sendMsg(this.CoreContext, {
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name, payload.folder_id);
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId({
chatType: ChatType.KCHATTYPEGROUP,
peerUid: payload.group_id.toString(),
}, [sendFileEle], [], true);

View File

@@ -2,7 +2,6 @@ import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { ChatType, Peer, SendFileElement } from '@/core/entities';
import fs from 'fs';
import { sendMsg } from '@/onebot/action/msg/SendMsg';
import { uri2local } from '@/common/utils/file';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
@@ -20,11 +19,11 @@ type Payload = FromSchema<typeof SchemaData>;
export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null> {
actionName = ActionName.GOCQHTTP_UploadPrivateFile;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async getPeer(payload: Payload): Promise<Peer> {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQFriendApi = this.CoreContext.apis.FriendApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQFriendApi = this.core.apis.FriendApi;
if (payload.user_id) {
const peerUid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!peerUid) {
@@ -33,21 +32,20 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
const isBuddy = await NTQQFriendApi.isBuddy(peerUid);
return { chatType: isBuddy ? ChatType.KCHATTYPEC2C : ChatType.KCHATTYPETEMPC2CFROMGROUP, peerUid };
}
throw new Error( '缺少参数 user_id');
throw new Error('缺少参数 user_id');
}
async _handle(payload: Payload): Promise<null> {
const peer = await this.getPeer(payload);
let file = payload.file;
if (fs.existsSync(file)) {
file = `file://${file}`;
}
const downloadResult = await uri2local(this.CoreContext.NapCatTempPath, file);
const downloadResult = await uri2local(this.core.NapCatTempPath, file);
if (!downloadResult.success) {
throw new Error(downloadResult.errMsg);
}
const sendFileEle: SendFileElement = await this.CoreContext.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name);
await sendMsg(this.CoreContext, peer, [sendFileEle], [], true);
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(downloadResult.path, payload.name);
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], [], true);
return null;
}
}

View File

@@ -1,7 +1,7 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique';
import { MessageUnique } from '@/common/utils/message-unique';
const SchemaData = {
type: 'object',
@@ -15,11 +15,11 @@ type Payload = FromSchema<typeof SchemaData>;
export default class DelEssenceMsg extends BaseAction<Payload, any> {
actionName = ActionName.DelEssenceMsg;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
const NTQQGroupApi = this.core.apis.GroupApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
if (!msg) throw new Error('msg not found');
return await NTQQGroupApi.removeGroupEssence(
msg.Peer.peerUid,

View File

@@ -1,4 +1,3 @@
import { WebApiGroupNoticeFeed } from '@/core';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
@@ -8,21 +7,21 @@ const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
feed_id: { type: 'string' },
notice_id: { type: 'string' },
},
required: ['group_id','feed_id'],
required: ['group_id', 'notice_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class DelGroupNotice extends BaseAction<Payload, any> {
actionName = ActionName.DelGroupNotice;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const group = payload.group_id.toString();
const feedId = payload.feed_id;
return await NTQQGroupApi.deleteGroupBulletin(group, feedId);
const noticeId = payload.notice_id;
return await NTQQGroupApi.deleteGroupBulletin(group, noticeId);
}
}

View File

@@ -7,7 +7,7 @@ const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['number', 'string'] },
pages: { type: 'number' },
pages: { type: ['number', 'string'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
@@ -16,11 +16,11 @@ type Payload = FromSchema<typeof SchemaData>;
export class GetGroupEssence extends BaseAction<Payload, GroupEssenceMsgRet> {
actionName = ActionName.GoCQHTTP_GetEssenceMsg;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQWebApi = this.CoreContext.apis.WebApi;
const ret = await NTQQWebApi.getGroupEssenceMsg(payload.group_id.toString(), (payload.pages || "0").toString());
const NTQQWebApi = this.core.apis.WebApi;
const ret = await NTQQWebApi.getGroupEssenceMsg(payload.group_id.toString(), (+(payload.pages ?? 0)).toString());
if (!ret) {
throw new Error('获取失败');
}

View File

@@ -1,5 +1,5 @@
import { OB11Group } from '../../types';
import { OB11Constructor } from '@/onebot/helper/converter';
import { OB11Group } from '@/onebot';
import { OB11Entities } from '@/onebot/helper/entities';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
@@ -16,13 +16,13 @@ type Payload = FromSchema<typeof SchemaData>;
class GetGroupInfo extends BaseAction<Payload, OB11Group> {
actionName = ActionName.GetGroupInfo;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const group = (await NTQQGroupApi.getGroups()).find(e => e.groupCode == payload.group_id.toString());
if (!group) throw `${payload.group_id}不存在`;
return OB11Constructor.group(group);
return OB11Entities.group(group);
}
}

View File

@@ -1,5 +1,5 @@
import { OB11Group } from '../../types';
import { OB11Constructor } from '@/onebot/helper/converter';
import { OB11Group } from '@/onebot';
import { OB11Entities } from '@/onebot/helper/entities';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { Group } from '@/core/entities';
@@ -16,12 +16,12 @@ type Payload = FromSchema<typeof SchemaData>;
class GetGroupList extends BaseAction<Payload, OB11Group[]> {
actionName = ActionName.GetGroupList;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const groupList: Group[] = await NTQQGroupApi.getGroups(typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache);
return OB11Constructor.groups(groupList);
return OB11Entities.groups(groupList);
}
}

View File

@@ -1,5 +1,5 @@
import { OB11GroupMember } from '../../types';
import { OB11Constructor } from '@/onebot/helper/converter';
import { OB11GroupMember } from '@/onebot';
import { OB11Entities } from '@/onebot/helper/entities';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
@@ -19,28 +19,28 @@ type Payload = FromSchema<typeof SchemaData>;
class GetGroupMemberInfo extends BaseAction<Payload, OB11GroupMember> {
actionName = ActionName.GetGroupMemberInfo;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const isNocache = typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache;
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error (`Uin2Uid Error ${payload.user_id}不存在`);
if (!uid) throw new Error(`Uin2Uid Error ${payload.user_id}不存在`);
const [member, info] = await Promise.allSettled([
NTQQGroupApi.getGroupMemberV2(payload.group_id.toString(), uid, isNocache),
NTQQUserApi.getUserDetailInfo(uid),
]);
if (member.status !== 'fulfilled') throw new Error (`群(${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') {
this.CoreContext.context.logger.logDebug("群成员详细信息结果", info.value);
this.core.context.logger.logDebug('群成员详细信息结果', info.value);
Object.assign(member, info.value);
} else {
this.CoreContext.context.logger.logDebug(`获取群成员详细信息失败, 只能返回基础信息 ${info.reason}`);
this.core.context.logger.logDebug(`获取群成员详细信息失败, 只能返回基础信息 ${info.reason}`);
}
const date = Math.round(Date.now() / 1000);
const retMember = OB11Constructor.groupMember(payload.group_id.toString(), member.value as GroupMember);
const Member = await this.CoreContext.apis.GroupApi.getGroupMember(payload.group_id.toString(), retMember.user_id);
const retMember = OB11Entities.groupMember(payload.group_id.toString(), member.value as GroupMember);
const Member = await this.core.apis.GroupApi.getGroupMember(payload.group_id.toString(), retMember.user_id);
retMember.last_sent_time = parseInt(Member?.lastSpeakTime || date.toString());
retMember.join_time = parseInt(Member?.joinTime || date.toString());
return retMember;

View File

@@ -1,5 +1,5 @@
import { OB11GroupMember } from '../../types';
import { OB11Constructor } from '@/onebot/helper/converter';
import { OB11GroupMember } from '@/onebot';
import { OB11Entities } from '@/onebot/helper/entities';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
@@ -17,16 +17,16 @@ type Payload = FromSchema<typeof SchemaData>;
class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
actionName = ActionName.GetGroupMemberList;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQWebApi = this.CoreContext.apis.WebApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQWebApi = this.core.apis.WebApi;
const groupMembers = await NTQQGroupApi.getGroupMembers(payload.group_id.toString());
const groupMembersArr = Array.from(groupMembers.values());
let _groupMembers = groupMembersArr.map(item => {
return OB11Constructor.groupMember(payload.group_id.toString(), item);
return OB11Entities.groupMember(payload.group_id.toString(), item);
});
const MemberMap: Map<number, OB11GroupMember> = new Map<number, OB11GroupMember>();
@@ -39,7 +39,7 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
MemberMap.set(_groupMembers[i].user_id, _groupMembers[i]);
}
const selfRole = groupMembers.get(this.CoreContext.selfInfo.uid)?.role;
const selfRole = groupMembers.get(this.core.selfInfo.uid)?.role;
const isPrivilege = selfRole === 3 || selfRole === 4;
_groupMembers.forEach(item => {
@@ -63,7 +63,7 @@ class GetGroupMemberList extends BaseAction<Payload, OB11GroupMember[]> {
}
}
}
_groupMembers = Array.from(MemberMap.values());
return _groupMembers;
}

View File

@@ -6,7 +6,7 @@ import { FromSchema, JSONSchema } from 'json-schema-to-ts';
interface GroupNotice {
sender_id: number;
publish_time: number;
feed_id: string;
notice_id: string;
message: {
text: string
image: Array<{
@@ -31,10 +31,10 @@ type ApiGroupNotice = GroupNotice & WebApiGroupNoticeFeed;
export class GetGroupNotice extends BaseAction<Payload, GroupNotice[]> {
actionName = ActionName.GoCQHTTP_GetGroupNotice;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQWebApi = this.CoreContext.apis.WebApi;
const NTQQWebApi = this.core.apis.WebApi;
const group = payload.group_id.toString();
const ret = await NTQQWebApi.getGroupNotice(group);
@@ -45,8 +45,7 @@ export class GetGroupNotice extends BaseAction<Payload, GroupNotice[]> {
for (const key in ret.feeds) {
const retApiNotice: WebApiGroupNoticeFeed = ret.feeds[key];
const retNotice: GroupNotice = {
//...ret.feeds[key],
feed_id: retApiNotice.fid,
notice_id: retApiNotice.fid,
sender_id: retApiNotice.u,
publish_time: retApiNotice.pubt,
message: {

View File

@@ -16,8 +16,8 @@ export class GetGroupSystemMsg extends BaseAction<void, any> {
actionName = ActionName.GetGroupSystemMsg;
async _handle(payload: void) {
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
// 默认10条 该api未完整实现 包括响应数据规范化 类型规范化
const SingleScreenNotifies = await NTQQGroupApi.getSingleScreenNotifies(10);
const retData: any = { InvitedRequest: [], join_requests: [] };

View File

@@ -1,7 +1,7 @@
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique';
import { MessageUnique } from '@/common/utils/message-unique';
const SchemaData = {
type: 'object',
@@ -15,10 +15,10 @@ type Payload = FromSchema<typeof SchemaData>;
export default class SetEssenceMsg extends BaseAction<Payload, any> {
actionName = ActionName.SetEssenceMsg;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
if (!msg) {
throw new Error('msg not found');

View File

@@ -17,10 +17,10 @@ type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupAddRequest extends BaseAction<Payload, null> {
actionName = ActionName.SetGroupAddRequest;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const flag = payload.flag.toString();
const approve = payload.approve?.toString() !== 'false';
await NTQQGroupApi.handleGroupRequest(flag,

View File

@@ -17,12 +17,12 @@ type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupAdmin extends BaseAction<Payload, null> {
actionName = ActionName.SetGroupAdmin;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const enable = typeof payload.enable === 'string' ? payload.enable === 'true' : !!payload.enable;
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('get Uid Error');
await NTQQGroupApi.setMemberRole(payload.group_id.toString(), uid, enable ? GroupMemberRole.admin : GroupMemberRole.normal);

View File

@@ -16,11 +16,11 @@ type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupBan extends BaseAction<Payload, null> {
actionName = ActionName.SetGroupBan;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('uid error');
await NTQQGroupApi.banMember(payload.group_id.toString(),

View File

@@ -16,10 +16,10 @@ type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupCard extends BaseAction<Payload, null> {
actionName = ActionName.SetGroupCard;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const member = await NTQQGroupApi.getGroupMember(payload.group_id.toString(), payload.user_id.toString());
member && await NTQQGroupApi.setMemberCard(payload.group_id.toString(), member.uid, payload.card || '');
return null;

View File

@@ -17,11 +17,11 @@ type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupKick extends BaseAction<Payload, null> {
actionName = ActionName.SetGroupKick;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQUserApi = this.CoreContext.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const NTQQUserApi = this.core.apis.UserApi;
const rejectReq = payload.reject_add_request?.toString() == 'true';
const uid = await NTQQUserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('get Uid Error');

View File

@@ -14,10 +14,10 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupLeave extends BaseAction<Payload, any> {
actionName = ActionName.SetGroupLeave;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<any> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
await NTQQGroupApi.quitGroup(payload.group_id.toString());
}
}

View File

@@ -14,10 +14,10 @@ const SchemaData = {
type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupName extends BaseAction<Payload, null> {
actionName = ActionName.SetGroupName;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
await NTQQGroupApi.setGroupName(payload.group_id.toString(), payload.group_name);
return null;
}

View File

@@ -15,11 +15,11 @@ type Payload = FromSchema<typeof SchemaData>;
export default class SetGroupWholeBan extends BaseAction<Payload, null> {
actionName = ActionName.SetGroupWholeBan;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<null> {
const enable = payload.enable?.toString() !== 'false';
const NTQQGroupApi = this.CoreContext.apis.GroupApi;
const NTQQGroupApi = this.core.apis.GroupApi;
await NTQQGroupApi.banGroup(payload.group_id.toString(), enable);
return null;
}

View File

@@ -84,93 +84,93 @@ import { DelGroupNotice } from './group/DelGroupNotice';
export type ActionMap = Map<string, BaseAction<any, any>>;
export function createActionMap(onebotContext: NapCatOneBot11Adapter, coreContext: NapCatCore): ActionMap {
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
const actionHandlers = [
new FetchEmojiLike(onebotContext, coreContext),
new GetFile(onebotContext, coreContext),
new SetQQProfile(onebotContext, coreContext),
new ShareGroupEx(onebotContext, coreContext),
new SharePeer(onebotContext, coreContext),
new CreateCollection(onebotContext, coreContext),
new SetLongNick(onebotContext, coreContext),
new ForwardFriendSingleMsg(onebotContext, coreContext),
new ForwardGroupSingleMsg(onebotContext, coreContext),
new MarkGroupMsgAsRead(onebotContext, coreContext),
new MarkPrivateMsgAsRead(onebotContext, coreContext),
new SetQQAvatar(onebotContext, coreContext),
new TranslateEnWordToZn(onebotContext, coreContext),
new GetGroupFileCount(onebotContext, coreContext),
new GetGroupFileList(onebotContext, coreContext),
new SetGroupFileFolder(onebotContext, coreContext),
new DelGroupFile(onebotContext, coreContext),
new DelGroupFileFolder(onebotContext, coreContext),
new FetchEmojiLike(obContext, core),
new GetFile(obContext, core),
new SetQQProfile(obContext, core),
new ShareGroupEx(obContext, core),
new SharePeer(obContext, core),
new CreateCollection(obContext, core),
new SetLongNick(obContext, core),
new ForwardFriendSingleMsg(obContext, core),
new ForwardGroupSingleMsg(obContext, core),
new MarkGroupMsgAsRead(obContext, core),
new MarkPrivateMsgAsRead(obContext, core),
new SetQQAvatar(obContext, core),
new TranslateEnWordToZn(obContext, core),
new GetGroupFileCount(obContext, core),
new GetGroupFileList(obContext, core),
new SetGroupFileFolder(obContext, core),
new DelGroupFile(obContext, core),
new DelGroupFileFolder(obContext, core),
// onebot11
new SendLike(onebotContext, coreContext),
new GetMsg(onebotContext, coreContext),
new GetLoginInfo(onebotContext, coreContext),
new GetFriendList(onebotContext, coreContext),
new GetGroupList(onebotContext, coreContext),
new GetGroupInfo(onebotContext, coreContext),
new GetGroupMemberList(onebotContext, coreContext),
new GetGroupMemberInfo(onebotContext, coreContext),
new SendGroupMsg(onebotContext, coreContext),
new SendPrivateMsg(onebotContext, coreContext),
new SendMsg(onebotContext, coreContext),
new DeleteMsg(onebotContext, coreContext),
new SetGroupAddRequest(onebotContext, coreContext),
new SetFriendAddRequest(onebotContext, coreContext),
new SetGroupLeave(onebotContext, coreContext),
new GetVersionInfo(onebotContext, coreContext),
new CanSendRecord(onebotContext, coreContext),
new CanSendImage(onebotContext, coreContext),
new GetStatus(onebotContext, coreContext),
new SetGroupWholeBan(onebotContext, coreContext),
new SetGroupBan(onebotContext, coreContext),
new SetGroupKick(onebotContext, coreContext),
new SetGroupAdmin(onebotContext, coreContext),
new SetGroupName(onebotContext, coreContext),
new SetGroupCard(onebotContext, coreContext),
new GetImage(onebotContext, coreContext),
new GetRecord(onebotContext, coreContext),
new SetMsgEmojiLike(onebotContext, coreContext),
new GetCookies(onebotContext, coreContext),
new SetOnlineStatus(onebotContext, coreContext),
new GetRobotUinRange(onebotContext, coreContext),
new GetFriendWithCategory(onebotContext, coreContext),
new SendLike(obContext, core),
new GetMsg(obContext, core),
new GetLoginInfo(obContext, core),
new GetFriendList(obContext, core),
new GetGroupList(obContext, core),
new GetGroupInfo(obContext, core),
new GetGroupMemberList(obContext, core),
new GetGroupMemberInfo(obContext, core),
new SendGroupMsg(obContext, core),
new SendPrivateMsg(obContext, core),
new SendMsg(obContext, core),
new DeleteMsg(obContext, core),
new SetGroupAddRequest(obContext, core),
new SetFriendAddRequest(obContext, core),
new SetGroupLeave(obContext, core),
new GetVersionInfo(obContext, core),
new CanSendRecord(obContext, core),
new CanSendImage(obContext, core),
new GetStatus(obContext, core),
new SetGroupWholeBan(obContext, core),
new SetGroupBan(obContext, core),
new SetGroupKick(obContext, core),
new SetGroupAdmin(obContext, core),
new SetGroupName(obContext, core),
new SetGroupCard(obContext, core),
new GetImage(obContext, core),
new GetRecord(obContext, core),
new SetMsgEmojiLike(obContext, core),
new GetCookies(obContext, core),
new SetOnlineStatus(obContext, core),
new GetRobotUinRange(obContext, core),
new GetFriendWithCategory(obContext, core),
//以下为go-cqhttp api
new GetOnlineClient(onebotContext, coreContext),
new OCRImage(onebotContext, coreContext),
new IOCRImage(onebotContext, coreContext),
new GetGroupHonorInfo(onebotContext, coreContext),
new SendGroupNotice(onebotContext, coreContext),
new GetGroupNotice(onebotContext, coreContext),
new GetGroupEssence(onebotContext, coreContext),
new GoCQHTTPSendForwardMsg(onebotContext, coreContext),
new GoCQHTTPSendGroupForwardMsg(onebotContext, coreContext),
new GoCQHTTPSendPrivateForwardMsg(onebotContext, coreContext),
new GoCQHTTPGetStrangerInfo(onebotContext, coreContext),
new GoCQHTTPDownloadFile(onebotContext, coreContext),
new GetGuildList(onebotContext, coreContext),
new GoCQHTTPMarkMsgAsRead(onebotContext, coreContext),
new GoCQHTTPUploadGroupFile(onebotContext, coreContext),
new GoCQHTTPGetGroupMsgHistory(onebotContext, coreContext),
new GoCQHTTPGetForwardMsgAction(onebotContext, coreContext),
new GetFriendMsgHistory(onebotContext, coreContext),
new GoCQHTTPHandleQuickAction(onebotContext, coreContext),
new GetGroupSystemMsg(onebotContext, coreContext),
new DelEssenceMsg(onebotContext, coreContext),
new SetEssenceMsg(onebotContext, coreContext),
new GetRecentContact(onebotContext, coreContext),
new MarkAllMsgAsRead(onebotContext, coreContext),
new GetProfileLike(onebotContext, coreContext),
new SetGroupPortrait(onebotContext, coreContext),
new FetchCustomFace(onebotContext, coreContext),
new GoCQHTTPUploadPrivateFile(onebotContext, coreContext),
new GetGuildProfile(onebotContext, coreContext),
new SetModelShow(onebotContext, coreContext),
new SetInputStatus(onebotContext, coreContext),
new GetCSRF(onebotContext, coreContext),
new DelGroupNotice(onebotContext, coreContext),
new GetOnlineClient(obContext, core),
new OCRImage(obContext, core),
new IOCRImage(obContext, core),
new GetGroupHonorInfo(obContext, core),
new SendGroupNotice(obContext, core),
new GetGroupNotice(obContext, core),
new GetGroupEssence(obContext, core),
new GoCQHTTPSendForwardMsg(obContext, core),
new GoCQHTTPSendGroupForwardMsg(obContext, core),
new GoCQHTTPSendPrivateForwardMsg(obContext, core),
new GoCQHTTPGetStrangerInfo(obContext, core),
new GoCQHTTPDownloadFile(obContext, core),
new GetGuildList(obContext, core),
new GoCQHTTPMarkMsgAsRead(obContext, core),
new GoCQHTTPUploadGroupFile(obContext, core),
new GoCQHTTPGetGroupMsgHistory(obContext, core),
new GoCQHTTPGetForwardMsgAction(obContext, core),
new GetFriendMsgHistory(obContext, core),
new GoCQHTTPHandleQuickAction(obContext, core),
new GetGroupSystemMsg(obContext, core),
new DelEssenceMsg(obContext, core),
new SetEssenceMsg(obContext, core),
new GetRecentContact(obContext, core),
new MarkAllMsgAsRead(obContext, core),
new GetProfileLike(obContext, core),
new SetGroupPortrait(obContext, core),
new FetchCustomFace(obContext, core),
new GoCQHTTPUploadPrivateFile(obContext, core),
new GetGuildProfile(obContext, core),
new SetModelShow(obContext, core),
new SetInputStatus(obContext, core),
new GetCSRF(obContext, core),
new DelGroupNotice(obContext, core),
];
const actionMap = new Map();
for (const action of actionHandlers) {

View File

@@ -1,7 +1,7 @@
import { ActionName } from '../types';
import BaseAction from '../BaseAction';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique';
import { MessageUnique } from '@/common/utils/message-unique';
import { NodeIKernelMsgListener } from '@/core';
const SchemaData = {
@@ -21,24 +21,18 @@ type Payload = FromSchema<typeof SchemaData>;
class DeleteMsg extends BaseAction<Payload, void> {
actionName = ActionName.DeleteMsg;
PayloadSchema = SchemaData;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
const NTQQMsgApi = this.CoreContext.apis.MsgApi;
const NTQQMsgApi = this.core.apis.MsgApi;
const msg = MessageUnique.getMsgIdAndPeerByShortId(Number(payload.message_id));
if (msg) {
const ret = this.CoreContext.eventWrapper.RegisterListen<NodeIKernelMsgListener['onMsgInfoListUpdate']>
(
const ret = this.core.eventWrapper.registerListen(
'NodeIKernelMsgListener/onMsgInfoListUpdate',
1,
5000,
(msgs) => {
if (msgs.find(m => m.msgId === msg.MsgId && m.recallTime !== '0')) {
return true;
}
return false;
},
).catch(e => new Promise<undefined>((resolve, reject) => {
(msgs) => !!msgs.find(m => m.msgId === msg.MsgId && m.recallTime !== '0'),
).catch(() => new Promise<undefined>((resolve) => {
resolve(undefined);
}));
await NTQQMsgApi.recallMsg(msg.Peer, [msg.MsgId]);

Some files were not shown because too many files have changed in this diff Show More