Merge branch 'main' into laana

This commit is contained in:
Wesley F. Young 2024-09-04 23:42:09 +08:00
commit 28425587e2
30 changed files with 247 additions and 89 deletions

View File

@ -17,5 +17,8 @@ charset = utf-8
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
[*.bat]
charset = latin1
# Unfortunately, EditorConfig doesn't support space configuration inside import braces directly. # Unfortunately, EditorConfig doesn't support space configuration inside import braces directly.
# You'll need to rely on your linter/formatter like ESLint or Prettier for that. # You'll need to rely on your linter/formatter like ESLint or Prettier for that.

View File

@ -15,6 +15,8 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
## 猫猫技能 ## 猫猫技能
- [x] **高性能**1K+ 群聊数目、20 线程并行发送消息毫无压力 - [x] **高性能**1K+ 群聊数目、20 线程并行发送消息毫无压力
- [x] **多种启动方式**支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动 - [x] **多种启动方式**支持以无头、LiteLoader 插件、仅 QQ GUI 三种方式启动
- [x] **多平台支持**: 支持Windows/Linux(可选Docker)/Android Termux/MacOs覆盖全平台
- [x] **安装简单**: 支持一键脚本/程序自动部署/镜像部署等多种覆盖范围
- [x] **低占用**:无头模式占用资源极低,适合在服务器上运行 - [x] **低占用**:无头模式占用资源极低,适合在服务器上运行
- [x] **超多接口**:实现大部分 OneBot 和 go-cqhttp 接口,超多扩展 API - [x] **超多接口**:实现大部分 OneBot 和 go-cqhttp 接口,超多扩展 API
- [x] **WebUI**:自带 WebUI 支持,远程管理更加便捷 - [x] **WebUI**:自带 WebUI 支持,远程管理更加便捷

Binary file not shown.

Binary file not shown.

38
launcher/launcher.bat Normal file
View File

@ -0,0 +1,38 @@
@echo off
chcp 65001
net session >nul 2>&1
if %errorLevel% == 0 (
echo Administrator mode detected.
) else (
echo Please run this script in administrator mode.
powershell -Command "Start-Process 'wt.exe' -ArgumentList 'cmd /c cd /d \"%cd%\" && \"%~f0\"' -Verb runAs"
exit
)
set NAPCAT_PATCH_PATH=%cd%\patchNapCat.js
set NAPCAT_LOAD_PATH=%cd%\loadNapCat.js
set NAPCAT_INJECT_PATH=%cd%\NapCatWinBootHook.dll
set NAPCAT_LAUNCHER_PATH=%cd%\NapCatWinBootMain.exe
set NAPCAT_MAIN_PATH=%cd%\napcat.mjs
:loop_read
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
set RetString=%%b
goto :napcat_boot
)
:napcat_boot
for %%a in (%RetString%) do (
set "pathWithoutUninstall=%%~dpa"
)
SET QQPath=%pathWithoutUninstall%QQ.exe
if not exist "%QQpath%" (
echo provided QQ path is invalid: %QQpath%
pause
exit /b
)
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%"

5
launcher/loadNapCat.js Normal file
View File

@ -0,0 +1,5 @@
const path = require('path');
const CurrentPath = path.dirname(__filename);
(async () => {
await import("file://" + path.join(CurrentPath, './napcat/napcat.mjs'));
})();

1
launcher/patchNapCat.js Normal file
View File

@ -0,0 +1 @@
require('./launcher.node').load('external_index', module);

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.43", "version": "2.2.47",
"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.43", "version": "2.2.47",
"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

@ -22,10 +22,15 @@ export abstract class ConfigBase<T> {
} }
getConfigPath(pathName: string | undefined): string { getConfigPath(pathName: string | undefined): string {
const suffix = pathName ? `_${pathName}` : ''; if (!pathName) {
const filename = `${this.name}${suffix}.json`; const filename = `${this.name}.json`;
const mainPath = this.core.context.pathWrapper.binaryPath;
return path.join(mainPath, 'config', filename);
} else {
const filename = `${this.name}_${pathName}.json`;
return path.join(this.configPath, filename); return path.join(this.configPath, filename);
} }
}
read(): T { read(): T {
const logger = this.core.context.logger; const logger = this.core.context.logger;

View File

@ -37,7 +37,7 @@ export class FileNapCatOneBotUUID {
if (!uuid.startsWith('NapCatOneBot|ModelIdFile|')) return undefined; if (!uuid.startsWith('NapCatOneBot|ModelIdFile|')) return undefined;
const data = uuid.split('|'); const data = uuid.split('|');
if (data.length !== 6) return undefined; if (data.length !== 6) return undefined;
const [, , chatType, peerUid, modelId,fileId] = data; const [, , chatType, peerUid, modelId, fileId] = data;
return { return {
peer: { peer: {
chatType: chatType as any, chatType: chatType as any,
@ -156,10 +156,22 @@ export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
}; };
} }
export function getQQPackageInfoPath(exePath: string = ''): string {
if (os.platform() === 'darwin') {
return path.join(path.dirname(exePath), '..', 'Resources', 'app', 'package.json');
} else {
return path.join(path.dirname(exePath), 'resources', 'app', 'package.json');
}
}
export function getQQVersionConfigPath(exePath: string = ''): string | undefined { export function getQQVersionConfigPath(exePath: string = ''): string | undefined {
let configVersionInfoPath; let configVersionInfoPath;
if (os.platform() !== 'linux') { if (os.platform() === 'win32') {
configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json'); configVersionInfoPath = path.join(path.dirname(exePath), 'resources', 'app', 'versions', 'config.json');
} else if (os.platform() === 'darwin') {
const userPath = os.homedir();
const appDataPath = path.resolve(userPath, './Library/Application Support/QQ');
configVersionInfoPath = path.resolve(appDataPath, './versions/config.json');
} else { } else {
const userPath = os.homedir(); const userPath = os.homedir();
const appDataPath = path.resolve(userPath, './.config/QQ'); const appDataPath = path.resolve(userPath, './.config/QQ');

View File

@ -1,6 +1,7 @@
import path, { dirname } from 'path'; import path, { dirname } from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import fs from 'fs'; import fs from 'fs';
import os from 'os';
export class NapCatPathWrapper { export class NapCatPathWrapper {
binaryPath: string; binaryPath: string;
@ -11,17 +12,23 @@ export class NapCatPathWrapper {
constructor(mainPath: string = dirname(fileURLToPath(import.meta.url))) { constructor(mainPath: string = dirname(fileURLToPath(import.meta.url))) {
this.binaryPath = mainPath; this.binaryPath = mainPath;
this.logsPath = path.join(this.binaryPath, 'logs'); let writePath: string;
this.configPath = path.join(this.binaryPath, 'config'); if (os.platform() === 'darwin') {
this.cachePath = path.join(this.binaryPath, 'cache'); writePath = path.join(os.homedir(), 'Library', 'Application Support', 'QQ', 'NapCat');
} else {
writePath = this.binaryPath;
}
this.logsPath = path.join(writePath, 'logs');
this.configPath = path.join(writePath, 'config');
this.cachePath = path.join(writePath, 'cache');
this.staticPath = path.join(this.binaryPath, 'static'); this.staticPath = path.join(this.binaryPath, 'static');
if (fs.existsSync(this.logsPath)) { if (!fs.existsSync(this.logsPath)) {
fs.mkdirSync(this.logsPath, { recursive: true }); fs.mkdirSync(this.logsPath, { recursive: true });
} }
if (fs.existsSync(this.configPath)) { if (!fs.existsSync(this.configPath)) {
fs.mkdirSync(this.configPath, { recursive: true }); fs.mkdirSync(this.configPath, { recursive: true });
} }
if (fs.existsSync(this.cachePath)) { if (!fs.existsSync(this.cachePath)) {
fs.mkdirSync(this.cachePath, { recursive: true }); fs.mkdirSync(this.cachePath, { recursive: true });
} }
} }

View File

@ -1,7 +1,6 @@
import path from 'node:path';
import fs from 'node:fs'; import fs from 'node:fs';
import { systemPlatform } from '@/common/system'; import { systemPlatform } from '@/common/system';
import { getDefaultQQVersionConfigInfo, getQQVersionConfigPath } from './helper'; import { getDefaultQQVersionConfigInfo, getQQPackageInfoPath, getQQVersionConfigPath } from './helper';
import AppidTable from '@/core/external/appid.json'; import AppidTable from '@/core/external/appid.json';
import { LogWrapper } from './log'; import { LogWrapper } from './log';
@ -20,7 +19,7 @@ export class QQBasicInfoWrapper {
//基础目录获取 //基础目录获取
this.context = context; this.context = context;
this.QQMainPath = process.execPath; this.QQMainPath = process.execPath;
this.QQPackageInfoPath = path.join(path.dirname(this.QQMainPath), 'resources', 'app', 'package.json'); this.QQPackageInfoPath = getQQPackageInfoPath(this.QQMainPath);
this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath); this.QQVersionConfigPath = getQQVersionConfigPath(this.QQMainPath);
//基础信息获取 无快更则启用默认模板填充 //基础信息获取 无快更则启用默认模板填充
@ -53,9 +52,25 @@ export class QQBasicInfoWrapper {
//此方法不要直接使用 //此方法不要直接使用
getQUAInternal() { getQUAInternal() {
return systemPlatform === 'linux' switch (systemPlatform) {
? `V1_LNX_NQ_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B` case 'linux':
: `V1_WIN_NQ_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`; return `V1_LNX_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
case 'darwin':
return `V1_MAC_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
default:
return `V1_WIN_${this.getFullQQVesion()}_${this.getQQBuildStr()}_GW_B`;
}
}
getAppidInternal() {
switch (systemPlatform) {
case 'linux':
return '537243600';
case 'darwin':
return '537243441';
default:
return '537243538';
}
} }
getAppidV2(): { appid: string; qua: string } { getAppidV2(): { appid: string; qua: string } {
@ -71,6 +86,6 @@ export class QQBasicInfoWrapper {
// else // else
this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`); this.context.logger.log(`[QQ版本兼容性检测] 获取Appid异常 请检测NapCat/QQNT是否正常`);
this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,); this.context.logger.log(`[QQ版本兼容性检测] ${fullVersion} 版本兼容性不佳,可能会导致一些功能无法正常使用`,);
return { appid: systemPlatform === 'linux' ? '537243600' : '537243441', qua: this.getQUAInternal() }; return { appid: this.getAppidInternal(), qua: this.getQUAInternal() };
} }
} }

View File

@ -1 +1 @@
export const napCatVersion = '2.2.43'; export const napCatVersion = '2.2.47';

View File

@ -1,5 +1,4 @@
import { import {
ChatType,
GeneralCallResult, GeneralCallResult,
Group, Group,
GroupMember, GroupMember,
@ -10,7 +9,7 @@ import {
MemberExtSourceType, MemberExtSourceType,
NapCatCore, NapCatCore,
} from '@/core'; } from '@/core';
import { isNumeric, runAllWithTimeout } from '@/common/helper'; import { isNumeric } from '@/common/helper';
import { LimitedHashTable } from '@/common/message-unique'; import { LimitedHashTable } from '@/common/message-unique';
export class NTQQGroupApi { export class NTQQGroupApi {
@ -248,7 +247,7 @@ export class NTQQGroupApi {
'NodeIKernelGroupListener/onMemberInfoChange', 'NodeIKernelGroupListener/onMemberInfoChange',
1, 1,
forced ? 5000 : 250, forced ? 5000 : 250,
(params) => params === GroupCode, (params, _, members) => params === GroupCode && members.size > 0,
); );
const retData = await ( const retData = await (
this.core.eventWrapper this.core.eventWrapper

View File

@ -75,7 +75,6 @@ export class NTQQUserApi {
(profile) => profile.uid === uid, (profile) => profile.uid === uid,
); );
const RetUser: User = { const RetUser: User = {
...profile.simpleInfo.coreInfo,
...profile.simpleInfo.status, ...profile.simpleInfo.status,
...profile.simpleInfo.vasInfo, ...profile.simpleInfo.vasInfo,
...profile.commonExt, ...profile.commonExt,
@ -83,17 +82,22 @@ export class NTQQUserApi {
qqLevel: profile.commonExt?.qqLevel, qqLevel: profile.commonExt?.qqLevel,
age: profile.simpleInfo.baseInfo.age, age: profile.simpleInfo.baseInfo.age,
pendantId: '', pendantId: '',
...profile.simpleInfo.coreInfo
}; };
return RetUser; return RetUser;
} }
async getUserDetailInfo(uid: string): Promise<User> { async getUserDetailInfo(uid: string): Promise<User> {
const retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB), uid); let retUser = await solveAsyncProblem(async (uid) => this.fetchUserDetailInfo(uid, UserDetailSource.KDB), uid);
if (retUser && retUser.uin !== '0') { if (retUser && retUser.uin !== '0') {
return retUser; return retUser;
} }
this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.'); this.context.logger.logDebug('[NapCat] [Mark] getUserDetailInfo Mode1 Failed.');
return this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER); retUser = await this.fetchUserDetailInfo(uid, UserDetailSource.KSERVER);
if (retUser && retUser.uin === '0') {
retUser.uin = await this.core.apis.UserApi.getUidByUinV2(uid) ?? '0';
}
return retUser;
} }
async modifySelfProfile(param: ModifyProfileParams) { async modifySelfProfile(param: ModifyProfileParams) {

View File

@ -131,20 +131,53 @@ export class NTQQWebApi {
// return await res.json(); // return await res.json();
// } // }
async setGroupNotice(GroupCode: string, Content: string) { async setGroupNotice(
GroupCode: string,
Content: string,
pinned: number = 0,
type: number = 1,
is_show_edit_card: number = 1,
tip_window_type: number = 1,
confirm_required: number = 1,
picId: string = '',
imgWidth: number = 540,
imgHeight: number = 300,
) {
interface SetNoticeRetSuccess {
ec: number;
em: string;
id: number;
ltsm: number;
new_fid: string;
read_only: number;
role: number;
srv_code: number;
}
const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com'); const cookieObject = await this.core.apis.UserApi.getCookies('qun.qq.com');
let ret: any = undefined;
try { try {
ret = await RequestUtil.HttpGetJson<any>( let settings = JSON.stringify({
`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${new URLSearchParams({ is_show_edit_card: is_show_edit_card,
tip_window_type: tip_window_type,
confirm_required: confirm_required
});
const externalParam = {
pic: picId,
imgWidth: imgWidth.toString(),
imgHeight: imgHeight.toString(),
};
let ret: SetNoticeRetSuccess = await RequestUtil.HttpGetJson<SetNoticeRetSuccess>(
`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?${new URLSearchParams({
bkn: this.getBknFromCookie(cookieObject), bkn: this.getBknFromCookie(cookieObject),
qid: GroupCode, qid: GroupCode,
text: Content, text: Content,
pinned: '0', pinned: pinned.toString(),
type: '1', type: type.toString(),
settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}', settings: settings,
...(picId === '' ? {} : externalParam)
}).toString()}`, }).toString()}`,
'GET', 'POST',
'', '',
{ 'Cookie': this.cookieToString(cookieObject) } { 'Cookie': this.cookieToString(cookieObject) }
); );

View File

@ -6,5 +6,9 @@
"9.9.15-27597": { "9.9.15-27597": {
"appid": 537243441, "appid": 537243441,
"qua": "V1_WIN_NQ_9.9.15_27597_GW_B" "qua": "V1_WIN_NQ_9.9.15_27597_GW_B"
},
"6.9.53-27597": {
"appid": 537243538,
"qua": "V1_MAC_NQ_6.9.53_27597_GW_B"
} }
} }

View File

@ -42,9 +42,15 @@ export enum NapCatCoreWorkingEnv {
} }
export function loadQQWrapper(QQVersion: string): WrapperNodeApi { export function loadQQWrapper(QQVersion: string): WrapperNodeApi {
let wrapperNodePath = path.resolve(path.dirname(process.execPath), './resources/app/wrapper.node'); let appPath;
if (os.platform() === 'darwin') {
appPath = path.resolve(path.dirname(process.execPath), '../Resources/app');
} else {
appPath = path.resolve(path.dirname(process.execPath), './resources/app');
}
let wrapperNodePath = path.resolve(appPath, 'wrapper.node');
if (!fs.existsSync(wrapperNodePath)) { if (!fs.existsSync(wrapperNodePath)) {
wrapperNodePath = path.join(path.dirname(process.execPath), `resources/app/versions/${QQVersion}/wrapper.node`); wrapperNodePath = path.join(appPath, `versions/${QQVersion}/wrapper.node`);
} }
const nativemodule: any = { exports: {} }; const nativemodule: any = { exports: {} };
process.dlopen(nativemodule, wrapperNodePath); process.dlopen(nativemodule, wrapperNodePath);

View File

@ -1,6 +1,6 @@
import { OB11Return } from '../types'; import { OB11Return } from '../types';
import { isNull } from '../../common/helper'; import { isNull } from '@/common/helper';
export class OB11Response { export class OB11Response {
static res<T>(data: T, status: string, retcode: number, message: string = ''): OB11Return<T> { static res<T>(data: T, status: string, retcode: number, message: string = ''): OB11Return<T> {

View File

@ -1,6 +1,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';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {

View File

@ -2,6 +2,7 @@ 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 { FileNapCatOneBotUUID } from '@/common/helper'; import { FileNapCatOneBotUUID } from '@/common/helper';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {

View File

@ -2,6 +2,7 @@ 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 { OB11Entities } from '@/onebot/entities'; import { OB11Entities } from '@/onebot/entities';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
properties: { properties: {

View File

@ -11,7 +11,10 @@ const SchemaData = {
content: { type: 'string' }, content: { type: 'string' },
image: { type: 'string' }, image: { type: 'string' },
pinned: { type: ['number', 'string'] }, pinned: { type: ['number', 'string'] },
type: { type: ['number', 'string'] },
confirm_required: { type: ['number', 'string'] }, confirm_required: { type: ['number', 'string'] },
is_show_edit_card: { type: ['number', 'string'] },
tip_window_type: { type: ['number', 'string'] },
}, },
required: ['group_id', 'content'], required: ['group_id', 'content'],
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
@ -22,6 +25,7 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_SendGroupNotice; actionName = ActionName.GoCQHTTP_SendGroupNotice;
async _handle(payload: Payload) { async _handle(payload: Payload) {
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) {
//公告图逻辑 //公告图逻辑
@ -47,12 +51,28 @@ export class SendGroupNotice extends BaseAction<Payload, null> {
} }
UploadImage = ImageUploadResult.picInfo; UploadImage = ImageUploadResult.picInfo;
} }
const noticePinned = +(payload.pinned ?? 0);
const noticeConfirmRequired = +(payload.confirm_required ?? 0);
const publishGroupBulletinResult = await this.core.apis.GroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, noticePinned, noticeConfirmRequired);
if (publishGroupBulletinResult.result != 0) { const noticeType = +(payload.type ?? 1);
throw `设置群公告失败,错误信息:${publishGroupBulletinResult.errMsg}`; const noticePinned = +(payload.pinned ?? 0);
const noticeShowEditCard = +(payload.is_show_edit_card ?? 0);
const noticeTipWindowType = +(payload.tip_window_type ?? 0);
const noticeConfirmRequired = +(payload.confirm_required ?? 1);
//const publishGroupBulletinResult = await this.core.apis.GroupApi.publishGroupBulletin(payload.group_id.toString(), payload.content, UploadImage, noticePinned, noticeConfirmRequired);
const publishGroupBulletinResult = await this.core.apis.WebApi.setGroupNotice(
payload.group_id.toString(),
payload.content,
noticePinned,
noticeType,
noticeShowEditCard,
noticeTipWindowType,
noticeConfirmRequired,
UploadImage?.id,
UploadImage?.width,
UploadImage?.height
);
if (!publishGroupBulletinResult || publishGroupBulletinResult.ec != 0) {
throw `设置群公告失败,错误信息:${publishGroupBulletinResult?.em}`;
} }
return null; return null;
} }

View File

@ -43,9 +43,6 @@ import { OB11FriendRecallNoticeEvent } from '@/onebot/event/notice/OB11FriendRec
import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent'; import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecallNoticeEvent';
import { LRUCache } from '@/common/lru-cache'; import { LRUCache } from '@/common/lru-cache';
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener'; import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
import { SysMessage } from '@/core/proto/SysMessage';
import { GreyTipWrapper } from '@/core/proto/GreyTipWrapper';
import { EmojiLikeToOthersWrapper1 } from '@/core/proto/EmojiLikeToOthers';
//OneBot实现类 //OneBot实现类
export class NapCatOneBot11Adapter { export class NapCatOneBot11Adapter {
@ -241,33 +238,35 @@ export class NapCatOneBot11Adapter {
private initMsgListener() { private initMsgListener() {
const msgListener = new NodeIKernelMsgListener(); const msgListener = new NodeIKernelMsgListener();
msgListener.onRecvSysMsg = async msg => { /*
// const sysMsg = SysMessage.fromBinary(Uint8Array.from(msg)); msgListener.onRecvSysMsg = async () => {
// if (sysMsg.msgSpec.length === 0) { const sysMsg = SysMessage.fromBinary(Uint8Array.from(msg));
// return; if (sysMsg.msgSpec.length === 0) {
// } return;
// const { msgType, subType, subSubType } = sysMsg.msgSpec[0]; }
// if (msgType === 732 && subType === 16 && subSubType === 16) { const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
// const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7))); if (msgType === 732 && subType === 16 && subSubType === 16) {
// if (greyTip.subTypeId === 36) { const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7)));
// const emojiLikeToOthers = EmojiLikeToOthersWrapper1 if (greyTip.subTypeId === 36) {
// .fromBinary(greyTip.rest) const emojiLikeToOthers = EmojiLikeToOthersWrapper1
// .wrapper! .fromBinary(greyTip.rest)
// .body!; .wrapper!
// if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like .body!;
// return; if (emojiLikeToOthers.attributes?.operation !== 1) { // Un-like
// } return;
// const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent( }
// greyTip.groupCode.toString(), const eventOrEmpty = await this.apis.GroupApi.createGroupEmojiLikeEvent(
// await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid), greyTip.groupCode.toString(),
// emojiLikeToOthers.msgSpec!.msgSeq.toString(), await this.core.apis.UserApi.getUinByUidV2(emojiLikeToOthers.attributes!.senderUid),
// emojiLikeToOthers.attributes!.emojiId, emojiLikeToOthers.msgSpec!.msgSeq.toString(),
// ); emojiLikeToOthers.attributes!.emojiId,
// // eslint-disable-next-line @typescript-eslint/no-unused-expressions );
// eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty); // eslint-disable-next-line @typescript-eslint/no-unused-expressions
// } eventOrEmpty && await this.networkManager.emitEvent(eventOrEmpty);
// } }
}
}; };
*/
msgListener.onInputStatusPush = async data => { msgListener.onInputStatusPush = async data => {
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin); const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);

View File

@ -49,12 +49,20 @@ export async function NCoreInitShell() {
const session = new wrapper.NodeIQQNTWrapperSession(); const session = new wrapper.NodeIQQNTWrapperSession();
// from get dataPath // from get dataPath
const [dataPath, dataPathGlobal] = (() => {
if (os.platform() === 'darwin') {
const userPath = os.homedir();
const appDataPath = path.resolve(userPath, './Library/Application Support/QQ');
return [appDataPath, path.join(appDataPath, 'global')];
}
let dataPath = wrapper.NodeQQNTWrapperUtil.getNTUserDataInfoConfig(); let dataPath = wrapper.NodeQQNTWrapperUtil.getNTUserDataInfoConfig();
if (!dataPath) { if (!dataPath) {
dataPath = path.resolve(os.homedir(), './.config/QQ'); dataPath = path.resolve(os.homedir(), './.config/QQ');
fs.mkdirSync(dataPath, { recursive: true }); fs.mkdirSync(dataPath, { recursive: true });
} }
const dataPathGlobal = path.resolve(dataPath, './nt_qq/global'); const dataPathGlobal = path.resolve(dataPath, './nt_qq/global');
return [dataPath, dataPathGlobal];
})();
// from initConfig // from initConfig
engine.initWithDeskTopConfig( engine.initWithDeskTopConfig(
@ -115,7 +123,7 @@ export async function NCoreInitShell() {
const realBase64 = pngBase64QrcodeData.replace(/^data:image\/\w+;base64,/, ''); const realBase64 = pngBase64QrcodeData.replace(/^data:image\/\w+;base64,/, '');
const buffer = Buffer.from(realBase64, 'base64'); const buffer = Buffer.from(realBase64, 'base64');
logger.logWarn('请扫描下面的二维码然后在手Q上授权登录'); logger.logWarn('请扫描下面的二维码然后在手Q上授权登录');
const qrcodePath = path.join(pathWrapper.binaryPath, 'qrcode.png'); const qrcodePath = path.join(pathWrapper.cachePath, 'qrcode.png');
qrcode.generate(qrcodeUrl, { small: true }, (res) => { qrcode.generate(qrcodeUrl, { small: true }, (res) => {
logger.logWarn([ logger.logWarn([
'\n', '\n',

View File

@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
SettingItem( SettingItem(
'<span id="napcat-update-title">Napcat</span>', '<span id="napcat-update-title">Napcat</span>',
undefined, undefined,
SettingButton('V2.2.43', 'napcat-update-button', 'secondary'), SettingButton('V2.2.47', 'napcat-update-button', 'secondary'),
), ),
]), ]),
SettingList([ SettingList([

View File

@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
SettingItem( SettingItem(
'<span id="napcat-update-title">Napcat</span>', '<span id="napcat-update-title">Napcat</span>',
void 0, void 0,
SettingButton("V2.2.43", "napcat-update-button", "secondary") SettingButton("V2.2.47", "napcat-update-button", "secondary")
) )
]), ]),
SettingList([ SettingList([

View File

@ -25,12 +25,6 @@
"paths": { "paths": {
"@*": [ "@*": [
"./src*" "./src*"
],
"@/core": [
"./src/core/index",
],
"@/core/*": [
"./src/core/*"
] ]
} }
}, },

View File

@ -11,7 +11,6 @@ const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].fl
function genCpModule(module: string) { function genCpModule(module: string) {
return { src: `./node_modules/${module}`, dest: `dist/node_modules/${module}`, flatten: false }; return { src: `./node_modules/${module}`, dest: `dist/node_modules/${module}`, flatten: false };
} }
let startScripts: string[] | undefined = undefined; let startScripts: string[] | undefined = undefined;
if (process.env.NAPCAT_BUILDSYS == 'linux') { if (process.env.NAPCAT_BUILDSYS == 'linux') {
if (process.env.NAPCAT_BUILDARCH == 'x64') { if (process.env.NAPCAT_BUILDARCH == 'x64') {
@ -82,6 +81,7 @@ const ShellBaseConfigPlugin: PluginOption[] = [
{ src: './src/core/external/napcat.json', dest: 'dist/config/' }, { src: './src/core/external/napcat.json', dest: 'dist/config/' },
{ src: './src/onebot/config/onebot11.json', dest: 'dist/config/' }, { src: './src/onebot/config/onebot11.json', dest: 'dist/config/' },
{ src: './package.json', dest: 'dist' }, { src: './package.json', dest: 'dist' },
{ src: './launcher/', dest: 'dist', flatten: true },
// { src: './README.md', dest: 'dist' }, // { src: './README.md', dest: 'dist' },
// { src: './logo.png', dest: 'dist/logs' }, // { src: './logo.png', dest: 'dist/logs' },
...(startScripts.map((startScript) => { ...(startScripts.map((startScript) => {