Compare commits

...

37 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
139 changed files with 1399 additions and 1193 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,6 +13,7 @@ export function isGIF(path: string) {
fs.closeSync(fd); fs.closeSync(fd);
return buffer.toString() === 'GIF8'; return buffer.toString() === 'GIF8';
} }
// 定义一个异步函数来检查文件是否存在 // 定义一个异步函数来检查文件是否存在
export function checkFileReceived(path: string, timeout: number = 3000): Promise<void> { export function checkFileReceived(path: string, timeout: number = 3000): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -123,15 +124,14 @@ export interface HttpDownloadOptions {
} }
export async function httpDownload(options: string | HttpDownloadOptions): Promise<Buffer> { export async function httpDownload(options: string | HttpDownloadOptions): Promise<Buffer> {
const chunks: Buffer[] = []; // const chunks: Buffer[] = [];
let url: string; let url: string;
let headers: Record<string, 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', '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') { if (typeof options === 'string') {
url = options; url = options;
const host = new URL(url).hostname; headers['Host'] = new URL(url).hostname;
headers['Host'] = host;
} else { } else {
url = options.url; url = options.url;
if (options.headers) { 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: true, errMsg: '', fileName: filename, ext: fileExt, path: filePath, isLocal: true };
} }
return { success: false, errMsg: '未知文件类型', fileName: '', ext: '', path: '', isLocal: false }; 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) => { return new Promise<Awaited<ReturnType<T>> | undefined>((resolve) => {
func(...args).then((result) => { func(...args).then((result) => {
resolve(result); resolve(result);
}).catch((e) => { }).catch(() => {
resolve(undefined); resolve(undefined);
}); });
}); });
} }
//下面这个类是用于将uid+msgid合并的类 //下面这个类是用于将uid+msgid合并的类
export class UUIDConverter { export class UUIDConverter {
static encode(highStr: string, lowStr: string): string { static encode(highStr: string, lowStr: string): string {
@@ -31,11 +32,10 @@ export class UUIDConverter {
const highHex = high.toString(16).padStart(16, '0'); const highHex = high.toString(16).padStart(16, '0');
const lowHex = low.toString(16).padStart(16, '0'); const lowHex = low.toString(16).padStart(16, '0');
const combinedHex = highHex + lowHex; 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, 12,
16, 16,
)}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`; )}-${combinedHex.substring(16, 20)}-${combinedHex.substring(20)}`;
return uuid;
} }
static decode(uuid: string): { high: string; low: string } { static decode(uuid: string): { high: string; low: string } {
@@ -122,11 +122,11 @@ export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
}; };
} }
return { return {
baseVersion: '9.9.15-27254', baseVersion: '9.9.15-27391',
curVersion: '9.9.15-27254', curVersion: '9.9.15-27391',
prevVersion: '', prevVersion: '',
onErrorVersions: [], onErrorVersions: [],
buildId: '27254', buildId: '27391',
}; };
} }

View File

@@ -177,12 +177,12 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
if (element.replyElement) { if (element.replyElement) {
const recordMsgOrNull = msg.records.find( const recordMsgOrNull = msg.records.find(
record => element.replyElement!.sourceMsgIdInRecords === record.msgId record => element.replyElement!.sourceMsgIdInRecords === record.msgId,
); );
return `[回复消息 ${ return `[回复消息 ${
recordMsgOrNull && recordMsgOrNull &&
recordMsgOrNull.peerUin != '284840486' // 非转发消息; 否则定位不到 recordMsgOrNull.peerUin != '284840486' // 非转发消息; 否则定位不到
? ?
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) : rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})` `未找到消息记录 (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 path from 'path';
import fs from 'fs'; import fs from 'fs';
import fsPromises from 'fs/promises'; import fsPromises from 'fs/promises';
import { InstanceContext, NapCatCore, OnRichMediaDownloadCompleteParams } from '@/core'; import { InstanceContext, NapCatCore } from '@/core';
import * as fileType from 'file-type'; import * as fileType from 'file-type';
import imageSize from 'image-size'; import imageSize from 'image-size';
import { ISizeCalculationResult } from 'image-size/dist/types/interface'; import { ISizeCalculationResult } from 'image-size/dist/types/interface';
@@ -97,9 +97,13 @@ export class NTQQFileApi {
async createValidSendFileElement( async createValidSendFileElement(
filePath: string, filePath: string,
fileName: string = '', fileName: string = '',
folderId: string = '' folderId: string = '',
): Promise<SendFileElement> { ): 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) { if (fileSize === 0) {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
@@ -118,9 +122,14 @@ export class NTQQFileApi {
async createValidSendPicElement( async createValidSendPicElement(
picPath: string, picPath: string,
summary: string = '', summary: string = '',
subType: 0 | 1 = 0 subType: 0 | 1 = 0,
): Promise<SendPicElement> { ): 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) { if (fileSize === 0) {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
@@ -153,7 +162,12 @@ export class NTQQFileApi {
diyThumbPath: string = '', diyThumbPath: string = '',
): Promise<SendVideoElement> { ): Promise<SendVideoElement> {
const logger = this.core.context.logger; 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) { if (fileSize === 0) {
throw new Error('文件异常大小为0'); throw new Error('文件异常大小为0');
} }
@@ -200,7 +214,7 @@ export class NTQQFileApi {
const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0; const thumbSize = _thumbPath ? (await fsPromises.stat(_thumbPath)).size : 0;
// log("生成缩略图", _thumbPath) // log("生成缩略图", _thumbPath)
thumbPath.set(0, _thumbPath); thumbPath.set(0, _thumbPath);
const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : ""; const thumbMd5 = _thumbPath ? await calculateFileMD5(_thumbPath) : '';
// "fileElement": { // "fileElement": {
// "fileMd5": "", // "fileMd5": "",
// "fileName": "1.mp4", // "fileName": "1.mp4",
@@ -304,66 +318,45 @@ export class NTQQFileApi {
return sourcePath; return sourcePath;
} }
} }
const data = await this.core.eventWrapper.CallNormalEvent< const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
( 'NodeIKernelMsgService/downloadRichMedia',
params: { 'NodeIKernelMsgListener/onRichMediaDownloadComplete',
fileModelId: string, [{
downloadSourceType: number, fileModelId: '0',
triggerType: number, downloadSourceType: 0,
msgId: string, triggerType: 1,
chatType: ChatType, msgId: msgId,
peerUid: string, chatType: chatType,
elementId: string, peerUid: peerUid,
thumbSize: number, elementId: elementId,
downloadType: number, thumbSize: 0,
filePath: string downloadType: 1,
}) => Promise<unknown>, filePath: thumbPath,
(fileTransNotifyInfo: OnRichMediaDownloadCompleteParams) => void }],
>( () => true,
'NodeIKernelMsgService/downloadRichMedia', (arg) => arg.msgId === msgId,
'NodeIKernelMsgListener/onRichMediaDownloadComplete', 1,
1, timeout,
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 msg = await this.core.apis.MsgApi.getMsgsByMsgId({ const msg = await this.core.apis.MsgApi.getMsgsByMsgId({
guildId: '', guildId: '',
chatType: chatType, chatType: chatType,
peerUid: peerUid, peerUid: peerUid,
}, [msgId]); }, [msgId]);
if (msg.msgList.length === 0) { if (msg.msgList.length === 0) {
return data[1].filePath; return fileTransNotifyInfo.filePath;
} }
//获取原始消息 //获取原始消息
const FileElements = msg?.msgList[0]?.elements?.find(e => e.elementId === elementId); const FileElements = msg?.msgList[0]?.elements?.find(e => e.elementId === elementId);
if (!FileElements) { if (!FileElements) {
//失败则就乱来 Todo //失败则就乱来 Todo
return data[1].filePath; return fileTransNotifyInfo.filePath;
} }
//从原始消息获取文件路径 //从原始消息获取文件路径
const filePath = return FileElements?.fileElement?.filePath ??
FileElements?.fileElement?.filePath ??
FileElements?.pttElement?.filePath ?? FileElements?.pttElement?.filePath ??
FileElements?.videoElement?.filePath ?? FileElements?.videoElement?.filePath ??
FileElements?.picElement?.sourcePath; FileElements?.picElement?.sourcePath;
return filePath;
} }
async getImageSize(filePath: string): Promise<ISizeCalculationResult | undefined> { async getImageSize(filePath: string): Promise<ISizeCalculationResult | undefined> {
@@ -438,56 +431,14 @@ export class NTQQFileApi {
} }
async searchfile(keys: string[]) { async searchfile(keys: string[]) {
type EventType = NodeIKernelSearchService['searchFileWithKeywords']; const Event = this.core.eventWrapper.createEventFunction('NodeIKernelSearchService/searchFileWithKeywords');
const id = await Event!(keys, 12);
interface OnListener { const Listener = this.core.eventWrapper.registerListen(
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>
(
'NodeIKernelSearchListener/onSearchFileKeywordsResult', 'NodeIKernelSearchListener/onSearchFileKeywordsResult',
1, 1,
20000, 20000,
(params) => id !== '' && params.searchId == id, (params) => id !== '' && params.searchId == id,
); );
id = await Event!(keys, 12);
const [ret] = (await Listener); const [ret] = (await Listener);
return ret; return ret;
} }
@@ -499,7 +450,7 @@ export class NTQQFileApi {
const url: string = element.originImageUrl!; // 没有域名 const url: string = element.originImageUrl!; // 没有域名
const md5HexStr = element.md5HexStr; const md5HexStr = element.md5HexStr;
const fileMd5 = element.md5HexStr; const fileMd5 = element.md5HexStr;
const fileUuid = element.fileUuid; // const fileUuid = element.fileUuid;
if (url) { if (url) {
const UrlParse = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接 const UrlParse = new URL(IMAGE_HTTP_HOST + url);//临时解析拼接
@@ -571,9 +522,9 @@ export class NTQQFileCacheApi {
} }
getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) { getFileCacheInfo(fileType: CacheFileType, pageSize: number = 1000, lastRecord?: CacheFileListItem) {
const _lastRecord = lastRecord ? lastRecord : { fileType: fileType }; // const _lastRecord = lastRecord ? lastRecord : { fileType: fileType };
//需要五个参数 // 需要五个参数
//return napCatCore.session.getStorageCleanService().getFileCacheInfo(); // return napCatCore.session.getStorageCleanService().getFileCacheInfo();
} }
async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) { async clearChatCache(chats: ChatCacheListItemBasic[] = [], fileKeys: string[] = []) {

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,6 @@
import type { ModifyProfileParams, User, UserDetailInfoByUin, UserDetailInfoByUinV2 } from '@/core/entities'; import type { ModifyProfileParams, User, UserDetailInfoByUinV2 } from '@/core/entities';
import { NodeIKernelProfileListener } from '@/core/listeners';
import { RequestUtil } from '@/common/utils/request'; import { RequestUtil } from '@/common/utils/request';
import { NodeIKernelProfileService, ProfileBizType, UserDetailSource } from '@/core/services'; import { ProfileBizType, UserDetailSource } from '@/core/services';
import { InstanceContext, NapCatCore } from '..'; import { InstanceContext, NapCatCore } from '..';
import { solveAsyncProblem } from '@/common/utils/helper'; import { solveAsyncProblem } from '@/common/utils/helper';
@@ -65,17 +64,18 @@ export class NTQQUserApi {
} }
async fetchUserDetailInfos(uids: string[]) { async fetchUserDetailInfos(uids: string[]) {
//26702 以上使用新接口 .Dev Mlikiowa // TODO: 26702 以上使用新接口 .Dev MliKiowa
type EventService = NodeIKernelProfileService['fetchUserDetailInfo'];
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
const retData: User[] = []; const retData: User[] = [];
const [_retData, _retListener] = await this.core.eventWrapper.CallNormalEvent< const [_retData, _retListener] = await this.core.eventWrapper.callNormalEventV2(
EventService, EventListener
>(
'NodeIKernelProfileService/fetchUserDetailInfo', 'NodeIKernelProfileService/fetchUserDetailInfo',
'NodeIKernelProfileListener/onUserDetailInfoChanged', 'NodeIKernelProfileListener/onUserDetailInfoChanged',
uids.length, [
5000, 'BuddyProfileStore',
uids,
UserDetailSource.KSERVER,
[ProfileBizType.KALL],
],
() => true,
(profile) => { (profile) => {
if (uids.includes(profile.uid)) { if (uids.includes(profile.uid)) {
const RetUser: User = { const RetUser: User = {
@@ -92,28 +92,24 @@ export class NTQQUserApi {
} }
return false; return false;
}, },
'BuddyProfileStore', uids.length,
uids,
UserDetailSource.KSERVER,
[ProfileBizType.KALL],
); );
return retData; return retData;
} }
async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) { async fetchUserDetailInfo(uid: string, mode: UserDetailSource = UserDetailSource.KDB) {
type EventService = NodeIKernelProfileService['fetchUserDetailInfo']; const [_retData, profile] = await this.core.eventWrapper.callNormalEventV2(
type EventListener = NodeIKernelProfileListener['onUserDetailInfoChanged'];
const [_retData, profile] = await this.core.eventWrapper.CallNormalEvent<EventService, EventListener>(
'NodeIKernelProfileService/fetchUserDetailInfo', 'NodeIKernelProfileService/fetchUserDetailInfo',
'NodeIKernelProfileListener/onUserDetailInfoChanged', 'NodeIKernelProfileListener/onUserDetailInfoChanged',
1, [
5000, 'BuddyProfileStore',
[uid],
mode,
[ProfileBizType.KALL],
],
() => true,
(profile) => profile.uid === uid, (profile) => profile.uid === uid,
'BuddyProfileStore',
[uid],
mode,
[ProfileBizType.KALL],
); );
const RetUser: User = { const RetUser: User = {
...profile.simpleInfo.coreInfo, ...profile.simpleInfo.coreInfo,
@@ -146,8 +142,7 @@ export class NTQQUserApi {
const ClientKeyData = await this.forceFetchClientKey(); const ClientKeyData = await this.forceFetchClientKey();
const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + this.core.selfInfo.uin + 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'; '&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 await RequestUtil.HttpsGetCookies(requestUrl);
return cookies;
} }
async getPSkey(domainList: string[]) { async getPSkey(domainList: string[]) {
@@ -170,8 +165,7 @@ export class NTQQUserApi {
async getQzoneCookies() { async getQzoneCookies() {
const ClientKeyData = await this.forceFetchClientKey(); 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 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 await RequestUtil.HttpsGetCookies(requestUrl);
return cookies;
} }
//需要异常处理 //需要异常处理
@@ -182,7 +176,7 @@ export class NTQQUserApi {
throw new Error('getClientKey Error'); throw new Error('getClientKey Error');
} }
const clientKey = ClientKeyData.clientKey; 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 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 cookies: { [key: string]: string; } = await RequestUtil.HttpsGetCookies(requestUrl);
const skey = cookies['skey']; const skey = cookies['skey'];
@@ -237,8 +231,7 @@ export class NTQQUserApi {
} }
async getUserDetailInfoByUinV2(Uin: string) { async getUserDetailInfoByUinV2(Uin: string) {
return await this.core.eventWrapper.callNoListenerEvent<(Uin: string) => Promise<UserDetailInfoByUinV2>> return await this.core.eventWrapper.callNoListenerEvent('NodeIKernelProfileService/getUserDetailInfoByUin', Uin);
('NodeIKernelProfileService/getUserDetailInfoByUin', Uin);
} }
async forceFetchClientKey() { 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 path from 'node:path';
import fs from 'node:fs'; import fs from 'node:fs';
import { InstanceContext } from './wrapper'; import { InstanceContext } from './wrapper';
import { proxiedListenerOf } from '@/common/utils/proxy-handler'; 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 { DataSource, GroupMember, SelfInfo } from './entities';
import { LegacyNTEventWrapper } from '@/common/framework/event-legacy'; import { LegacyNTEventWrapper } from '@/common/framework/event-legacy';
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis'; import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from './apis';
@@ -30,7 +30,7 @@ export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
export class NapCatCore { export class NapCatCore {
readonly context: InstanceContext; readonly context: InstanceContext;
readonly apis: NTApiContext; readonly apis: StableNTApiWrapper;
readonly eventWrapper: LegacyNTEventWrapper; readonly eventWrapper: LegacyNTEventWrapper;
// readonly eventChannel: NTEventChannel; // readonly eventChannel: NTEventChannel;
NapCatDataPath: string; NapCatDataPath: string;
@@ -98,7 +98,7 @@ export class NapCatCore {
}; };
//await sleep(2500); //await sleep(2500);
this.context.session.getMsgService().addKernelMsgListener( this.context.session.getMsgService().addKernelMsgListener(
proxiedListenerOf(msgListener, this.context.logger) as any proxiedListenerOf(msgListener, this.context.logger) as any,
); );
const profileListener = new NodeIKernelProfileListener(); const profileListener = new NodeIKernelProfileListener();
@@ -125,8 +125,7 @@ export class NapCatCore {
//群成员数量变化 应该刷新缓存 //群成员数量变化 应该刷新缓存
if (existGroup && g.memberCount === existGroup.memberCount) { if (existGroup && g.memberCount === existGroup.memberCount) {
Object.assign(existGroup, g); Object.assign(existGroup, g);
} } else {
else {
this.apis.GroupApi.groupCache.set(g.groupCode, g); this.apis.GroupApi.groupCache.set(g.groupCode, g);
// 获取群成员 // 获取群成员
} }
@@ -149,8 +148,7 @@ export class NapCatCore {
const existMember = existMembers.get(uid); const existMember = existMembers.get(uid);
if (existMember) { if (existMember) {
Object.assign(existMember, member); Object.assign(existMember, member);
} } else {
else {
existMembers!.set(uid, member); existMembers!.set(uid, member);
} }
//移除成员 //移除成员
@@ -158,8 +156,7 @@ export class NapCatCore {
existMembers.delete(uid); existMembers.delete(uid);
} }
}); });
} } else {
else {
this.apis.GroupApi.groupMemberCache.set(groupCode, arg.infos); this.apis.GroupApi.groupMemberCache.set(groupCode, arg.infos);
} }
// console.log('onMemberListChange', groupCode, arg); // console.log('onMemberListChange', groupCode, arg);
@@ -182,8 +179,7 @@ export class NapCatCore {
member.isChangeRole = this.checkAdminEvent(groupCode, member, existMember); member.isChangeRole = this.checkAdminEvent(groupCode, member, existMember);
// 更新成员信息 // 更新成员信息
Object.assign(existMember, member); Object.assign(existMember, member);
} } else {
else {
existMembers.set(uid, member); existMembers.set(uid, member);
} }
//移除成员 //移除成员
@@ -191,15 +187,15 @@ export class NapCatCore {
existMembers.delete(uid); existMembers.delete(uid);
} }
}); });
} } else {
else {
this.apis.GroupApi.groupMemberCache.set(groupCode, members); this.apis.GroupApi.groupMemberCache.set(groupCode, members);
} }
}; };
this.context.session.getGroupService().addKernelGroupListener( 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 { checkAdminEvent(groupCode: string, memberNew: GroupMember, memberOld: GroupMember | undefined): boolean {
if (memberNew.role !== memberOld?.role) { if (memberNew.role !== memberOld?.role) {
this.context.logger.logDebug(`${groupCode} ${memberNew.nick} 角色变更为 ${memberNew.role === 3 ? '管理员' : '群员'}`); 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 { export interface KickMemberInfo {
optFlag: number, optFlag: number,
optOperate: number, optOperate: number,
optMemberUid: string, optMemberUid: string,
optBytesMsg: 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, groupCode: string,
kickFlag: number, kickFlag: number,
kickList: Array<KickMemberInfo>, kickList: Array<KickMemberInfo>,
kickListUids: Array<string>, kickListUids: Array<string>,
kickMsg: string kickMsg: string
} }
export enum DataSource { export enum DataSource {
LOCAL, LOCAL,
REMOTE REMOTE
} }
export enum GroupListUpdateType { export enum GroupListUpdateType {
REFRESHALL, REFRESHALL,
GETALL, GETALL,
MODIFIED, MODIFIED,
REMOVE REMOVE
} }
export interface GroupMemberCache { export interface GroupMemberCache {
group: { group: {
data: GroupMember[]; data: GroupMember[];
isExpired: boolean; isExpired: boolean;
} };
isExpired: boolean; isExpired: boolean;
} }
export interface Group { export interface Group {
groupCode: string, groupCode: string,
createTime?: string,//高版本才有 createTime?: string,//高版本才有

View File

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

View File

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

View File

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

View File

@@ -7,24 +7,28 @@
"appid": 537240645, "appid": 537240645,
"qua": "V1_LNX_NQ_3.2.12_27206_GW_B" "qua": "V1_LNX_NQ_3.2.12_27206_GW_B"
}, },
"3.2.12-27254":{ "3.2.12-27254": {
"appid": 537240795, "appid": 537240795,
"qua": "V1_LNX_NQ_3.2.12_27254_GW_B" "qua": "V1_LNX_NQ_3.2.12_27254_GW_B"
}, },
"9.9.15-27187":{ "9.9.15-27187": {
"appid": 537240610, "appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27187_GW_B" "qua": "V1_WIN_NQ_9.9.15_27187_GW_B"
}, },
"9.9.15-27206":{ "9.9.15-27206": {
"appid": 537240610, "appid": 537240610,
"qua": "V1_WIN_NQ_9.9.15_27206_GW_B" "qua": "V1_WIN_NQ_9.9.15_27206_GW_B"
}, },
"9.9.15-27254":{ "9.9.15-27254": {
"appid": 537240709, "appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27254_GW_B" "qua": "V1_WIN_NQ_9.9.15_27254_GW_B"
}, },
"9.9.15-27333": { "9.9.15-27333": {
"appid": 537240709, "appid": 537240709,
"qua": "V1_WIN_NQ_9.9.15_27333_GW_B" "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 napCatDefaultConfig from '@/core/external/napcat.json';
import { NapCatCore } from '@/core'; import { NapCatCore } from '@/core';
@@ -7,7 +7,7 @@ export type NapCatConfig = typeof napCatDefaultConfig;
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
export class NapCatConfigLoader extends ConfigBase<NapCatConfig> { export class NapCatConfigLoader extends ConfigBase<NapCatConfig> {
constructor(coreContext: NapCatCore, configPath: string) { constructor(core: NapCatCore, configPath: string) {
super('napcat', coreContext, configPath); super('napcat', core, configPath);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,3 +14,45 @@ export * from './NodeIKernelRobotService';
export * from './NodeIKernelRichMediaService'; export * from './NodeIKernelRichMediaService';
export * from './NodeIKernelDbToolsService'; export * from './NodeIKernelDbToolsService';
export * from './NodeIKernelTipOffService'; 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 { 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 { NapCatCoreWorkingEnv, NodeIKernelLoginService, NodeIQQNTWrapperSession, WrapperNodeApi } from '@/core';
import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from '../apis'; import { NTQQFileApi, NTQQFriendApi, NTQQGroupApi, NTQQMsgApi, NTQQSystemApi, NTQQUserApi, NTQQWebApi } from '../apis';
import { NTQQCollectionApi } from '../apis/collection'; import { NTQQCollectionApi } from '../apis/collection';
@@ -15,7 +15,7 @@ export interface InstanceContext {
readonly pathWrapper: NapCatPathWrapper; readonly pathWrapper: NapCatPathWrapper;
} }
export interface NTApiContext { export interface StableNTApiWrapper {
FileApi: NTQQFileApi, FileApi: NTQQFileApi,
SystemApi: NTQQSystemApi, SystemApi: NTQQSystemApi,
CollectionApi: NTQQCollectionApi, CollectionApi: NTQQCollectionApi,

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
import { NapCatPathWrapper } from '@/common/framework/napcat'; import { NapCatPathWrapper } from '@/common/framework/napcat';
import { LogWrapper } from '@/common/utils/log'; import { LogWrapper } from '@/common/utils/log';
import { proxiedListenerOf } from '@/common/utils/proxy-handler'; 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 { loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core/core';
import { InstanceContext } from '@/core'; import { InstanceContext } from '@/core';
import { SelfInfo } from '@/core/entities'; import { SelfInfo } from '@/core/entities';
@@ -14,8 +14,9 @@ import { NapCatOneBot11Adapter } from '@/onebot';
//Framework ES入口文件 //Framework ES入口文件
export async function getWebUiUrl() { export async function getWebUiUrl() {
const WebUiConfigData = (await WebUiConfig.GetWebUIConfig()); 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( export async function NCoreInitFramework(
session: NodeIQQNTWrapperSession, session: NodeIQQNTWrapperSession,
loginService: NodeIKernelLoginService, loginService: NodeIKernelLoginService,

View File

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

View File

@@ -1,6 +1,5 @@
export const onSettingWindowCreated = async (view) => { export const onSettingWindowCreated = async (view) => {
// view.style.width = "100%"; // view.style.width = "100%";
// view.style.height = "100%"; // view.style.height = "100%";
// //添加iframe // //添加iframe
@@ -14,7 +13,7 @@ export const onSettingWindowCreated = async (view) => {
// //有滚动条何尝不是一种美 // //有滚动条何尝不是一种美
// view.appendChild(iframe); // view.appendChild(iframe);
let webui = await window.napcat.getWebUiUrl(); let webui = await window.napcat.getWebUiUrl();
let panel = ` view.innerHTML = `
<setting-section data-title=""> <setting-section data-title="">
<setting-panel> <setting-panel>
<setting-list data-direction="column"> <setting-list data-direction="column">
@@ -30,9 +29,8 @@ export const onSettingWindowCreated = async (view) => {
</setting-panel> </setting-panel>
</setting-section> </setting-section>
`; `;
view.innerHTML = panel; view.querySelector('.nc_openwebui').addEventListener('click', () => {
view.querySelector(".nc_openwebui").addEventListener("click", () => { window.open(webui, '_blank');
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> { abstract class BaseAction<PayloadType, ReturnDataType> {
actionName: ActionName = ActionName.Unknown; actionName: ActionName = ActionName.Unknown;
CoreContext: NapCatCore; core: NapCatCore;
private validate: undefined | ValidateFunction<any> = undefined; private validate: undefined | ValidateFunction<any> = undefined;
PayloadSchema: any = undefined; payloadSchema: any = undefined;
OneBotContext: NapCatOneBot11Adapter; obContext: NapCatOneBot11Adapter;
constructor(onebotContext: NapCatOneBot11Adapter, coreContext: NapCatCore) { constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
this.OneBotContext = onebotContext; this.obContext = obContext;
this.CoreContext = coreContext; this.core = core;
} }
protected async check(payload: PayloadType): Promise<BaseCheckResult> { protected async check(payload: PayloadType): Promise<BaseCheckResult> {
if (this.PayloadSchema) { if (this.payloadSchema) {
this.validate = new Ajv({ allowUnionTypes: true }).compile(this.PayloadSchema); this.validate = new Ajv({ allowUnionTypes: true }).compile(this.payloadSchema);
} }
if (this.validate && !this.validate(payload)) { if (this.validate && !this.validate(payload)) {
const errors = this.validate.errors as ErrorObject[]; const errors = this.validate.errors as ErrorObject[];
@@ -46,7 +46,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
const resData = await this._handle(payload); const resData = await this._handle(payload);
return OB11Response.ok(resData); return OB11Response.ok(resData);
} catch (e: any) { } catch (e: any) {
this.CoreContext.context.logger.logError('发生错误', e); this.core.context.logger.logError('发生错误', e);
return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200); return OB11Response.error(e?.toString() || e?.stack?.toString() || '未知错误,可能操作超时', 200);
} }
} }
@@ -60,7 +60,7 @@ abstract class BaseAction<PayloadType, ReturnDataType> {
const resData = await this._handle(payload); const resData = await this._handle(payload);
return OB11Response.ok(resData, echo); return OB11Response.ok(resData, echo);
} catch (e: any) { } 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); 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> { export class CreateCollection extends BaseAction<Payload, any> {
actionName = ActionName.CreateCollection; actionName = ActionName.CreateCollection;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
return await this.CoreContext.apis.CollectionApi.createCollection( return await this.core.apis.CollectionApi.createCollection(
this.CoreContext.selfInfo.uin, this.core.selfInfo.uin,
this.CoreContext.selfInfo.uid, this.core.selfInfo.uid,
this.CoreContext.selfInfo.nick, this.core.selfInfo.nick,
payload.brief, payload.rawData, payload.brief, payload.rawData,
); );
} }

View File

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

View File

@@ -2,7 +2,7 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { MessageUnique } from '@/common/utils/MessageUnique'; import { MessageUnique } from '@/common/utils/message-unique';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@@ -21,9 +21,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class FetchEmojiLike extends BaseAction<Payload, any> { export class FetchEmojiLike extends BaseAction<Payload, any> {
actionName = ActionName.FetchEmojiLike; actionName = ActionName.FetchEmojiLike;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { 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())); const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(parseInt(payload.message_id.toString()));
if (!msgIdPeer) throw new Error('消息不存在'); if (!msgIdPeer) throw new Error('消息不存在');
const msg = (await NTQQMsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0]; 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> { export class GetCollectionList extends BaseAction<Payload, any> {
actionName = ActionName.GetCollectionList; actionName = ActionName.GetCollectionList;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { 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)); 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 BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
export class GetFriendWithCategory extends BaseAction<void, any> { export class GetFriendWithCategory extends BaseAction<void, any> {
actionName = ActionName.GetFriendsWithCategory; actionName = ActionName.GetFriendsWithCategory;
async _handle(payload: void) { 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, ...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; actionName = ActionName.GetGroupIgnoreAddRequest;
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> { 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); // log(data);
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE); // const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE);
// const returnData: OB11GroupRequestNotify[] = []; // const returnData: OB11GroupRequestNotify[] = [];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,11 +16,11 @@ type Payload = FromSchema<typeof SchemaData>;
export class SharePeer extends BaseAction<Payload, any> { export class SharePeer extends BaseAction<Payload, any> {
actionName = ActionName.SharePeer; actionName = ActionName.SharePeer;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQUserApi = this.CoreContext.apis.UserApi; const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.CoreContext.apis.GroupApi; const NTQQGroupApi = this.core.apis.GroupApi;
if (payload.group_id) { if (payload.group_id) {
return await NTQQGroupApi.getGroupRecommendContactArkJson(payload.group_id); return await NTQQGroupApi.getGroupRecommendContactArkJson(payload.group_id);
} else if (payload.user_id) { } else if (payload.user_id) {
@@ -41,10 +41,10 @@ type PayloadGroupEx = FromSchema<typeof SchemaDataGroupEx>;
export class ShareGroupEx extends BaseAction<PayloadGroupEx, any> { export class ShareGroupEx extends BaseAction<PayloadGroupEx, any> {
actionName = ActionName.ShareGroupEx; actionName = ActionName.ShareGroupEx;
PayloadSchema = SchemaDataGroupEx; payloadSchema = SchemaDataGroupEx;
async _handle(payload: PayloadGroupEx) { async _handle(payload: PayloadGroupEx) {
const NTQQGroupApi = this.CoreContext.apis.GroupApi; const NTQQGroupApi = this.core.apis.GroupApi;
return await NTQQGroupApi.getArkJsonGroupShare(payload.group_id); 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> { export class TranslateEnWordToZn extends BaseAction<Payload, Array<any> | null> {
actionName = ActionName.TranslateEnWordToZn; actionName = ActionName.TranslateEnWordToZn;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQSystemApi = this.CoreContext.apis.SystemApi; const NTQQSystemApi = this.core.apis.SystemApi;
const ret = await NTQQSystemApi.translateEnWordToZn(payload.words); const ret = await NTQQSystemApi.translateEnWordToZn(payload.words);
if (ret.result !== 0) { if (ret.result !== 0) {
throw new Error('翻译失败'); throw new Error('翻译失败');

View File

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

View File

@@ -14,10 +14,10 @@ type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileCount extends BaseAction<Payload, { count: number }> { export class GetGroupFileCount extends BaseAction<Payload, { count: number }> {
actionName = ActionName.GetGroupFileCount; actionName = ActionName.GetGroupFileCount;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { 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()]); const ret = await NTQQGroupApi.GetGroupFileCount([payload.group_id?.toString()]);
return { count: ret.groupFileCounts[0] }; 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> }> { export class GetGroupFileList extends BaseAction<Payload, { FileList: Array<any> }> {
actionName = ActionName.GetGroupFileList; actionName = ActionName.GetGroupFileList;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { 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(), { const ret = await NTQQMsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1, sortType: 1,
fileCount: payload.file_count, fileCount: payload.file_count,

View File

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

View File

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

View File

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

View File

@@ -16,13 +16,13 @@ type Payload = FromSchema<typeof SchemaData>;
export class GetGroupHonorInfo extends BaseAction<Payload, Array<any>> { export class GetGroupHonorInfo extends BaseAction<Payload, Array<any>> {
actionName = ActionName.GetGroupHonorInfo; actionName = ActionName.GetGroupHonorInfo;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
if (!payload.type) { if (!payload.type) {
payload.type = WebHonorType.ALL; 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); 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 { ActionName } from '../types';
import { ChatType, Peer, RawMessage } from '@/core/entities'; import { ChatType, Peer, RawMessage } from '@/core/entities';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { MessageUnique } from '@/common/utils/MessageUnique'; import { MessageUnique } from '@/common/utils/message-unique';
interface Response { interface Response {
messages: OB11Message[]; messages: OB11Message[];
@@ -15,7 +15,7 @@ const SchemaData = {
group_id: { type: ['number', 'string'] }, group_id: { type: ['number', 'string'] },
message_seq: { type: 'number' }, message_seq: { type: 'number' },
count: { type: ['number', 'string'] }, count: { type: ['number', 'string'] },
reverseOrder: { type: 'boolean' }, reverseOrder: { type: ['boolean', 'string'] },
}, },
required: ['group_id'], required: ['group_id'],
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
@@ -24,12 +24,12 @@ type Payload = FromSchema<typeof SchemaData>;
export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Response> { export default class GoCQHTTPGetGroupMsgHistory extends BaseAction<Payload, Response> {
actionName = ActionName.GoCQHTTP_GetGroupMsgHistory; actionName = ActionName.GoCQHTTP_GetGroupMsgHistory;
PayloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload): Promise<Response> { 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 MsgCount = +(payload.count ?? 20);
const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() }; 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( 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); ).filter(msg => msg !== undefined);
return { 'messages': ob11MsgList }; return { 'messages': ob11MsgList };
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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