mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8353533d60 | ||
![]() |
c06df27424 | ||
![]() |
ad82919ddf | ||
![]() |
44dbba17e1 | ||
![]() |
5ba110e1da | ||
![]() |
b6e392fdb2 | ||
![]() |
2280e83aa2 | ||
![]() |
f49b94edb9 | ||
![]() |
2428a12221 | ||
![]() |
9c353f3760 | ||
![]() |
5b86d25d7f | ||
![]() |
2b168e8bbc | ||
![]() |
537db32847 | ||
![]() |
498b7f9f2b | ||
![]() |
9935568597 | ||
![]() |
467003af8c | ||
![]() |
4c9edcc47b | ||
![]() |
24bf9cf121 | ||
![]() |
e06f6f39a9 | ||
![]() |
98ee0c307b | ||
![]() |
5e53ea0bc3 | ||
![]() |
847d88ea77 | ||
![]() |
d5046cc2b3 | ||
![]() |
3ad64b7cbb | ||
![]() |
0dbfe8ca55 | ||
![]() |
91b794d66d | ||
![]() |
0d65e1e314 | ||
![]() |
2d8f58c6d8 | ||
![]() |
65888fa816 | ||
![]() |
857e882c6e | ||
![]() |
add2931834 | ||
![]() |
cdda5f45ee | ||
![]() |
5f73d6a913 | ||
![]() |
0637882fbc | ||
![]() |
3f785bab20 | ||
![]() |
a4ca89bdd6 |
Binary file not shown.
Binary file not shown.
@@ -34,6 +34,6 @@ if not exist "%QQpath%" (
|
|||||||
)
|
)
|
||||||
|
|
||||||
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
set NAPCAT_MAIN_PATH=%NAPCAT_MAIN_PATH:\=/%
|
||||||
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > %NAPCAT_LOAD_PATH%
|
echo (async () =^> {await import("file:///%NAPCAT_MAIN_PATH%")})() > "%NAPCAT_LOAD_PATH%"
|
||||||
|
|
||||||
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1
|
"%NAPCAT_LAUNCHER_PATH%" "%QQPath%" "%NAPCAT_INJECT_PATH%" %1
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "qq-chat",
|
"name": "qq-chat",
|
||||||
"version": "9.9.15-28060",
|
"version": "9.9.15-28131",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "QQ",
|
"description": "QQ",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"qd": "externals/devtools/cli/index.js"
|
"qd": "externals/devtools/cli/index.js"
|
||||||
},
|
},
|
||||||
"main": "./loadNapCat.js",
|
"main": "./loadNapCat.js",
|
||||||
"buildVersion": "28060",
|
"buildVersion": "28131",
|
||||||
"isPureShell": true,
|
"isPureShell": true,
|
||||||
"isByteCodeShell": true,
|
"isByteCodeShell": true,
|
||||||
"platform": "win32",
|
"platform": "win32",
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "2.6.4",
|
"version": "2.6.13",
|
||||||
"icon": "./logo.png",
|
"icon": "./logo.png",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "napcat",
|
"name": "napcat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "2.6.4",
|
"version": "2.6.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",
|
||||||
|
@@ -83,7 +83,7 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
logger.logError('convert silk failed', error.stack);
|
logger.logError.bind(logger)('convert silk failed', error.stack);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -40,7 +40,7 @@ export abstract class ConfigBase<T> {
|
|||||||
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
|
fs.writeFileSync(configPath, fs.readFileSync(this.getConfigPath(undefined), 'utf-8'));
|
||||||
logger.log(`[Core] [Config] 配置文件创建成功!\n`);
|
logger.log(`[Core] [Config] 配置文件创建成功!\n`);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.logError(`[Core] [Config] 创建配置文件时发生错误:`, e.message);
|
logger.logError.bind(logger)(`[Core] [Config] 创建配置文件时发生错误:`, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -49,9 +49,9 @@ export abstract class ConfigBase<T> {
|
|||||||
return this.configData;
|
return this.configData;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e instanceof SyntaxError) {
|
if (e instanceof SyntaxError) {
|
||||||
logger.logError(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message);
|
logger.logError.bind(logger)(`[Core] [Config] 配置文件格式错误,请检查配置文件:`, e.message);
|
||||||
} else {
|
} else {
|
||||||
logger.logError(`[Core] [Config] 读取配置文件时发生错误:`, e.message);
|
logger.logError.bind(logger)(`[Core] [Config] 读取配置文件时发生错误:`, e.message);
|
||||||
}
|
}
|
||||||
return {} as T;
|
return {} as T;
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ export abstract class ConfigBase<T> {
|
|||||||
try {
|
try {
|
||||||
fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2));
|
fs.writeFileSync(configPath, JSON.stringify(newConfigData, this.getKeys(), 2));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.logError(`保存配置文件 ${configPath} 时发生错误:`, e.message);
|
logger.logError.bind(logger)(`保存配置文件 ${configPath} 时发生错误:`, e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -183,11 +183,11 @@ export class NTEventWrapper {
|
|||||||
timeout = 5000,
|
timeout = 5000,
|
||||||
) {
|
) {
|
||||||
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
|
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(
|
||||||
(resolve, reject) => {
|
async (resolve, reject) => {
|
||||||
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 retEvent: any = {};
|
let retEvent: any = {};
|
||||||
|
|
||||||
function sendDataCallback() {
|
function sendDataCallback() {
|
||||||
if (complete == 0) {
|
if (complete == 0) {
|
||||||
@@ -235,7 +235,7 @@ export class NTEventWrapper {
|
|||||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
|
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallback);
|
||||||
this.createListenerFunction(ListenerMainName);
|
this.createListenerFunction(ListenerMainName);
|
||||||
const eventFunction = this.createEventFunction(serviceAndMethod);
|
const eventFunction = this.createEventFunction(serviceAndMethod);
|
||||||
if (eventFunction) eventFunction(...(args)).then((retEvent: Awaited<ReturnType<EventType>>) => {
|
retEvent = await eventFunction!(...(args));
|
||||||
if (!checkerEvent(retEvent) && timeoutRef.hasRef()) {
|
if (!checkerEvent(retEvent) && timeoutRef.hasRef()) {
|
||||||
clearTimeout(timeoutRef);
|
clearTimeout(timeoutRef);
|
||||||
reject(
|
reject(
|
||||||
@@ -250,7 +250,7 @@ export class NTEventWrapper {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -180,11 +180,11 @@ export function getDefaultQQVersionConfigInfo(): QQVersionConfigType {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
baseVersion: '9.9.15-28060',
|
baseVersion: '9.9.15-28131',
|
||||||
curVersion: '9.9.15-28060',
|
curVersion: '9.9.15-28131',
|
||||||
prevVersion: '',
|
prevVersion: '',
|
||||||
onErrorVersions: [],
|
onErrorVersions: [],
|
||||||
buildId: '28060',
|
buildId: '28131',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,12 +1,8 @@
|
|||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { networkInterfaces } from 'os';
|
|
||||||
import { randomUUID } from 'crypto';
|
|
||||||
|
|
||||||
// 缓解Win7设备兼容性问题
|
// 缓解Win7设备兼容性问题
|
||||||
let osName: string;
|
let osName: string;
|
||||||
// 设备ID
|
|
||||||
let machineId: Promise<string>;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
osName = os.hostname();
|
osName = os.hostname();
|
||||||
@@ -14,54 +10,6 @@ try {
|
|||||||
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
|
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
const invalidMacAddresses = new Set([
|
|
||||||
'00:00:00:00:00:00',
|
|
||||||
'ff:ff:ff:ff:ff:ff',
|
|
||||||
'ac:de:48:00:11:22',
|
|
||||||
]);
|
|
||||||
|
|
||||||
function validateMacAddress(candidate: string): boolean {
|
|
||||||
// eslint-disable-next-line no-useless-escape
|
|
||||||
const tempCandidate = candidate.replace(/\-/g, ':').toLowerCase();
|
|
||||||
return !invalidMacAddresses.has(tempCandidate);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getMachineId(): Promise<string> {
|
|
||||||
if (!machineId) {
|
|
||||||
machineId = (async () => {
|
|
||||||
const id = await getMacMachineId();
|
|
||||||
return id ?? randomUUID(); // fallback, generate a UUID
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
|
|
||||||
return machineId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMac(): string {
|
|
||||||
const ifaces = networkInterfaces();
|
|
||||||
for (const name in ifaces) {
|
|
||||||
const networkInterface = ifaces[name];
|
|
||||||
if (networkInterface) {
|
|
||||||
for (const { mac } of networkInterface) {
|
|
||||||
if (validateMacAddress(mac)) {
|
|
||||||
return mac;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Unable to retrieve mac address (unexpected format)');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getMacMachineId(): Promise<string | undefined> {
|
|
||||||
try {
|
|
||||||
const crypto = await import('crypto');
|
|
||||||
const macAddress = getMac();
|
|
||||||
return crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex');
|
|
||||||
} catch (err) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const homeDir = os.homedir();
|
const homeDir = os.homedir();
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '2.6.4';
|
export const napCatVersion = '2.6.13';
|
||||||
|
@@ -145,7 +145,7 @@ export class NTQQFileApi {
|
|||||||
try {
|
try {
|
||||||
videoInfo = await getVideoInfo(filePath, logger);
|
videoInfo = await getVideoInfo(filePath, logger);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.logError('获取视频信息失败,将使用默认值', e);
|
logger.logError.bind(logger)('获取视频信息失败,将使用默认值', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileExt = 'mp4';
|
let fileExt = 'mp4';
|
||||||
@@ -153,7 +153,7 @@ export class NTQQFileApi {
|
|||||||
const tempExt = (await fileType.fileTypeFromFile(filePath))?.ext;
|
const tempExt = (await fileType.fileTypeFromFile(filePath))?.ext;
|
||||||
if (tempExt) fileExt = tempExt;
|
if (tempExt) fileExt = tempExt;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.context.logger.logError('获取文件类型失败', e);
|
this.context.logger.logError.bind(logger)('获取文件类型失败', e);
|
||||||
}
|
}
|
||||||
const newFilePath = filePath + '.' + fileExt;
|
const newFilePath = filePath + '.' + fileExt;
|
||||||
fs.copyFileSync(filePath, newFilePath);
|
fs.copyFileSync(filePath, newFilePath);
|
||||||
@@ -227,7 +227,7 @@ export class NTQQFileApi {
|
|||||||
}
|
}
|
||||||
if (converted) {
|
if (converted) {
|
||||||
fsPromises.unlink(silkPath).then().catch(
|
fsPromises.unlink(silkPath).then().catch(
|
||||||
(e) => this.context.logger.logError('删除临时文件失败', e)
|
(e) => this.context.logger.logError.bind(this.context.logger)('删除临时文件失败', e)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@@ -264,7 +264,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取龙王信息失败');
|
this.context.logger.logError.bind(this.context.logger)('获取龙王信息失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
||||||
@@ -280,7 +280,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取群聊之火失败');
|
this.context.logger.logError.bind(this.context.logger)('获取群聊之火失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.PERFORMER || getType === WebHonorType.ALL) {
|
||||||
@@ -296,7 +296,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取群聊炽焰失败');
|
this.context.logger.logError.bind(this.context.logger)('获取群聊炽焰失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) {
|
||||||
@@ -312,7 +312,7 @@ export class NTQQWebApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logError('获取快乐源泉失败');
|
this.context.logger.logError.bind(this.context.logger)('获取快乐源泉失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
export interface IdMusicSignPostData {
|
export interface IdMusicSignPostData {
|
||||||
type: 'qq' | '163',
|
type: 'qq' | '163' | 'kugou' | 'migu' | 'kuwo',
|
||||||
id: string | number,
|
id: string | number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CustomMusicSignPostData {
|
export interface CustomMusicSignPostData {
|
||||||
type: 'custom',
|
type: 'qq' | '163' | 'kugou' | 'migu' | 'kuwo' | 'custom',
|
||||||
|
id: undefined,
|
||||||
url: string,
|
url: string,
|
||||||
audio: string,
|
audio?: string,
|
||||||
title: string,
|
title?: string,
|
||||||
image?: string,
|
image: string,
|
||||||
singer?: string
|
singer?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/core/external/appid.json
vendored
12
src/core/external/appid.json
vendored
@@ -1,10 +1,18 @@
|
|||||||
{
|
{
|
||||||
"9.9.15-28060":{
|
"9.9.15-28060": {
|
||||||
"appid": 537246092,
|
"appid": 537246092,
|
||||||
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
|
"qua": "V1_WIN_NQ_9.9.15_28060_GW_B"
|
||||||
},
|
},
|
||||||
"3.2.12-28060":{
|
"9.9.15-28131": {
|
||||||
|
"appid": 537246092,
|
||||||
|
"qua": "V1_WIN_NQ_9.9.15_28131_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-28060": {
|
||||||
"appid": 537246140,
|
"appid": 537246140,
|
||||||
"qua": "V1_LNX_NQ_3.2.12_28060_GW_B"
|
"qua": "V1_LNX_NQ_3.2.12_28060_GW_B"
|
||||||
|
},
|
||||||
|
"3.2.12-28131": {
|
||||||
|
"appid": 537246140,
|
||||||
|
"qua": "V1_LNX_NQ_3.2.12_28131_GW_B"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -26,7 +26,7 @@ export class RkeyManager {
|
|||||||
try {
|
try {
|
||||||
await this.refreshRkey();
|
await this.refreshRkey();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('获取rkey失败', e);
|
this.logger.logError.bind(this.logger)('获取rkey失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.rkeyData;
|
return this.rkeyData;
|
||||||
@@ -44,7 +44,7 @@ export class RkeyManager {
|
|||||||
try {
|
try {
|
||||||
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
|
this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError(`[Rkey] Get Rkey ${url} Error `, e);
|
this.logger.logError.bind(this.logger)(`[Rkey] Get Rkey ${url} Error `, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
|
|||||||
import { NapCatPathWrapper } from '@/common/path';
|
import { NapCatPathWrapper } from '@/common/path';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { getMachineId, hostname, systemName, systemVersion } from '@/common/system';
|
import { hostname, systemName, systemVersion } from '@/common/system';
|
||||||
import { NTEventWrapper } from '@/common/event';
|
import { NTEventWrapper } from '@/common/event';
|
||||||
import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/entities';
|
import { DataSource, GroupMember, KickedOffLineInfo, SelfInfo, SelfStatusInfo } from '@/core/entities';
|
||||||
import { NapCatConfigLoader } from '@/core/helper/config';
|
import { NapCatConfigLoader } from '@/core/helper/config';
|
||||||
@@ -99,7 +99,7 @@ export class NapCatCore {
|
|||||||
if (!fs.existsSync(this.NapCatTempPath)) {
|
if (!fs.existsSync(this.NapCatTempPath)) {
|
||||||
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
fs.mkdirSync(this.NapCatTempPath, { recursive: true });
|
||||||
}
|
}
|
||||||
this.initNapCatCoreListeners().then().catch(this.context.logger.logError);
|
this.initNapCatCoreListeners().then().catch(this.context.logger.logError.bind(this.context.logger));
|
||||||
|
|
||||||
this.context.logger.setFileLogEnabled(
|
this.context.logger.setFileLogEnabled(
|
||||||
this.configLoader.configData.fileLog,
|
this.configLoader.configData.fileLog,
|
||||||
@@ -127,7 +127,7 @@ export class NapCatCore {
|
|||||||
const msgListener = new NodeIKernelMsgListener();
|
const msgListener = new NodeIKernelMsgListener();
|
||||||
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
|
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
|
||||||
// 下线通知
|
// 下线通知
|
||||||
this.context.logger.logError('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
|
this.context.logger.logError.bind(this.context.logger)('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
|
||||||
this.selfInfo.online = false;
|
this.selfInfo.online = false;
|
||||||
};
|
};
|
||||||
msgListener.onRecvMsg = (msgs) => {
|
msgListener.onRecvMsg = (msgs) => {
|
||||||
@@ -247,10 +247,16 @@ export class NapCatCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function genSessionConfig(QQVersionAppid: string, QQVersion: string, selfUin: string, selfUid: string, account_path: string): Promise<WrapperSessionInitConfig> {
|
export async function genSessionConfig(
|
||||||
|
guid:string,
|
||||||
|
QQVersionAppid: string,
|
||||||
|
QQVersion: string,
|
||||||
|
selfUin: string,
|
||||||
|
selfUid: string,
|
||||||
|
account_path: string
|
||||||
|
): Promise<WrapperSessionInitConfig> {
|
||||||
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
const downloadPath = path.join(account_path, 'NapCat', 'temp');
|
||||||
fs.mkdirSync(downloadPath, { recursive: true });
|
fs.mkdirSync(downloadPath, { recursive: true });
|
||||||
const guid: string = await getMachineId();//26702 支持JS获取guid值 在LoginService中获取 TODO mlikiow a
|
|
||||||
//os.platform()
|
//os.platform()
|
||||||
let systemPlatform = PlatformType.KWINDOWS;
|
let systemPlatform = PlatformType.KWINDOWS;
|
||||||
switch (os.platform()) {
|
switch (os.platform()) {
|
||||||
@@ -261,7 +267,7 @@ export async function genSessionConfig(QQVersionAppid: string, QQVersion: string
|
|||||||
systemPlatform = PlatformType.KMAC;
|
systemPlatform = PlatformType.KMAC;
|
||||||
break;
|
break;
|
||||||
case 'linux':
|
case 'linux':
|
||||||
systemPlatform = PlatformType.KANDROID; //Android 怎么不算Linux!
|
systemPlatform = PlatformType.KLINUX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
5
src/core/listeners/NodeIO3MiscListener.ts
Normal file
5
src/core/listeners/NodeIO3MiscListener.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export class NodeIO3MiscListener {
|
||||||
|
getOnAmgomDataPiece(...arg: unknown[]) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
import { NodeIKernelLoginListener } from '@/core/listeners/NodeIKernelLoginListener';
|
import { NodeIKernelLoginListener } from '@/core/listeners/NodeIKernelLoginListener';
|
||||||
|
import { GeneralCallResult } from './common';
|
||||||
|
|
||||||
export interface LoginInitConfig {
|
export interface LoginInitConfig {
|
||||||
machineId: '';
|
machineId: '';
|
||||||
@@ -59,6 +60,9 @@ export interface QuickLoginResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeIKernelLoginService {
|
export interface NodeIKernelLoginService {
|
||||||
|
setLoginMiscData(arg0: string, value: string): unknown;
|
||||||
|
getMachineGuid(): string;
|
||||||
|
|
||||||
get(): NodeIKernelLoginService;
|
get(): NodeIKernelLoginService;
|
||||||
|
|
||||||
connect(): boolean;
|
connect(): boolean;
|
||||||
@@ -69,7 +73,7 @@ export interface NodeIKernelLoginService {
|
|||||||
|
|
||||||
initConfig(config: LoginInitConfig): void;
|
initConfig(config: LoginInitConfig): void;
|
||||||
|
|
||||||
getLoginMiscData(cb: (r: unknown) => void): void;
|
getLoginMiscData(data: string): Promise<GeneralCallResult & { value: string }>;
|
||||||
|
|
||||||
getLoginList(): Promise<{
|
getLoginList(): Promise<{
|
||||||
result: number, // 0是ok
|
result: number, // 0是ok
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
import { GeneralCallResult } from './common';
|
import { GeneralCallResult } from './common';
|
||||||
|
|
||||||
export interface NodeIKernelNodeMiscService {
|
export interface NodeIKernelNodeMiscService {
|
||||||
|
writeVersionToRegistry(version: string): void;
|
||||||
|
|
||||||
getMiniAppPath(): unknown;
|
getMiniAppPath(): unknown;
|
||||||
|
|
||||||
setMiniAppVersion(version: string): unknown;
|
setMiniAppVersion(version: string): unknown;
|
||||||
|
@@ -4,14 +4,14 @@ export interface NodeIKernelUnitedConfigService {
|
|||||||
|
|
||||||
removeKernelUnitedConfigListener(listenerId:number): void;
|
removeKernelUnitedConfigListener(listenerId:number): void;
|
||||||
|
|
||||||
fetchUnitedCommendConfig(...args: any[]): unknown;// needs 1 arguments
|
|
||||||
|
|
||||||
fetchUnitedSwitchConfig(...args: any[]): unknown;// needs 1 arguments
|
fetchUnitedSwitchConfig(...args: any[]): unknown;// needs 1 arguments
|
||||||
|
|
||||||
loadUnitedConfig(...args: any[]): unknown;// needs 1 arguments
|
|
||||||
|
|
||||||
isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments
|
isUnitedConfigSwitchOn(...args: any[]): unknown;// needs 1 arguments
|
||||||
|
|
||||||
registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments
|
registerUnitedConfigPushGroupList(...args: any[]): unknown;// needs 1 arguments
|
||||||
|
|
||||||
|
fetchUnitedCommendConfig(ids: `${string}`[]): void
|
||||||
|
|
||||||
|
loadUnitedConfig(id: string): Promise<unknown>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
11
src/core/services/NodeIO3MiscService.ts
Normal file
11
src/core/services/NodeIO3MiscService.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { NodeIO3MiscListener } from "../listeners/NodeIO3MiscListener";
|
||||||
|
|
||||||
|
export interface NodeIO3MiscService {
|
||||||
|
get(): NodeIO3MiscService;
|
||||||
|
|
||||||
|
addO3MiscListener(listeners: NodeIO3MiscListener): number;
|
||||||
|
|
||||||
|
setAmgomDataPiece(appid: string, dataPiece: Uint8Array): void;
|
||||||
|
|
||||||
|
reportAmgomWeather(type: string, uk2: string, arg: Array<string>): void;
|
||||||
|
}
|
@@ -26,6 +26,7 @@ import { NodeIKernelRecentContactService } from './services/NodeIKernelRecentCon
|
|||||||
import { NodeIKernelMSFService } from './services/NodeIKernelMSFService';
|
import { NodeIKernelMSFService } from './services/NodeIKernelMSFService';
|
||||||
import { NodeIkernelTestPerformanceService } from './services/NodeIkernelTestPerformanceService';
|
import { NodeIkernelTestPerformanceService } from './services/NodeIkernelTestPerformanceService';
|
||||||
import { NodeIKernelECDHService } from './services/NodeIKernelECDHService';
|
import { NodeIKernelECDHService } from './services/NodeIKernelECDHService';
|
||||||
|
import { NodeIO3MiscService } from './services/NodeIO3MiscService';
|
||||||
|
|
||||||
export interface NodeQQNTWrapperUtil {
|
export interface NodeQQNTWrapperUtil {
|
||||||
get(): unknown;
|
get(): unknown;
|
||||||
@@ -253,7 +254,7 @@ export interface EnginInitDesktopConfig {
|
|||||||
app_type: 4;
|
app_type: 4;
|
||||||
app_version: string;
|
app_version: string;
|
||||||
os_version: string;
|
os_version: string;
|
||||||
use_xlog: true;
|
use_xlog: boolean;
|
||||||
qua: string;
|
qua: string;
|
||||||
global_path_config: {
|
global_path_config: {
|
||||||
desktopGlobalPath: string;
|
desktopGlobalPath: string;
|
||||||
@@ -268,21 +269,20 @@ export interface NodeIQQNTWrapperEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface WrapperNodeApi {
|
export interface WrapperNodeApi {
|
||||||
[key: string]: any;
|
NodeIO3MiscService: NodeIO3MiscService;
|
||||||
|
|
||||||
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
NodeQQNTWrapperUtil: NodeQQNTWrapperUtil;
|
||||||
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
NodeIQQNTWrapperSession: NodeIQQNTWrapperSession;
|
||||||
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
NodeIQQNTWrapperEngine: NodeIQQNTWrapperEngine;
|
||||||
NodeIKernelLoginService: NodeIKernelLoginService;
|
NodeIKernelLoginService: NodeIKernelLoginService;
|
||||||
NodeIKernelProfileService: NodeIKernelProfileService;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
export enum PlatformType {
|
export enum PlatformType {
|
||||||
KUNKNOWN,
|
KUNKNOWN,
|
||||||
KANDROID,
|
KANDROID,
|
||||||
KIOS,
|
KIOS,
|
||||||
KWINDOWS,
|
KWINDOWS,
|
||||||
KMAC,
|
KMAC,
|
||||||
|
KLINUX
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DeviceType {
|
export enum DeviceType {
|
||||||
|
@@ -49,7 +49,7 @@ export async function NCoreInitFramework(
|
|||||||
const loaderObject = new NapCatFramework(wrapper, session, logger, loginService, selfInfo, basicInfoWrapper, pathWrapper);
|
const loaderObject = new NapCatFramework(wrapper, session, logger, loginService, selfInfo, basicInfoWrapper, pathWrapper);
|
||||||
|
|
||||||
//启动WebUi
|
//启动WebUi
|
||||||
InitWebUi(logger, pathWrapper).then().catch(logger.logError);
|
InitWebUi(logger, pathWrapper).then().catch(logger.logError.bind(logger));
|
||||||
//初始化LLNC的Onebot实现
|
//初始化LLNC的Onebot实现
|
||||||
new NapCatOneBot11Adapter(loaderObject.core, loaderObject.context, pathWrapper);
|
new NapCatOneBot11Adapter(loaderObject.core, loaderObject.context, pathWrapper);
|
||||||
}
|
}
|
||||||
|
@@ -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.core.context.logger.logError('发生错误', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('发生错误', 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.core.context.logger.logError('发生错误', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('发生错误', e);
|
||||||
return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo);
|
return OB11Response.error(e.stack?.toString() || e.toString(), 1200, echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -149,7 +149,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
//对Mgsid和OB11ID混用情况兜底
|
//对Mgsid和OB11ID混用情况兜底
|
||||||
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
const nodeMsg = MessageUnique.getMsgIdAndPeerByShortId(parseInt(nodeId)) || MessageUnique.getPeerByMsgId(nodeId);
|
||||||
if (!nodeMsg) {
|
if (!nodeMsg) {
|
||||||
logger.logError('转发消息失败,未找到消息', nodeId);
|
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', nodeId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nodeMsgIds.push(nodeMsg.MsgId);
|
nodeMsgIds.push(nodeMsg.MsgId);
|
||||||
@@ -161,7 +161,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
const isNodeMsg = OB11Data.filter(e => e.type === OB11MessageDataType.node).length;//找到子转发消息
|
||||||
if (isNodeMsg !== 0) {
|
if (isNodeMsg !== 0) {
|
||||||
if (isNodeMsg !== OB11Data.length) {
|
if (isNodeMsg !== OB11Data.length) {
|
||||||
logger.logError('子消息中包含非node消息 跳过不合法部分');
|
logger.logError.bind(this.core.context.logger)('子消息中包含非node消息 跳过不合法部分');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
const nodeMsg = await this.handleForwardedNodes(selfPeer, OB11Data.filter(e => e.type === OB11MessageDataType.node));
|
||||||
@@ -209,7 +209,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
for (const msgId of nodeMsgIds) {
|
for (const msgId of nodeMsgIds) {
|
||||||
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
const nodeMsgPeer = MessageUnique.getPeerByMsgId(msgId);
|
||||||
if (!nodeMsgPeer) {
|
if (!nodeMsgPeer) {
|
||||||
logger.logError('转发消息失败,未找到消息', msgId);
|
logger.logError.bind(this.core.context.logger)('转发消息失败,未找到消息', msgId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
const nodeMsg = (await this.core.apis.MsgApi.getMsgsByMsgId(nodeMsgPeer.Peer, [msgId])).msgList[0];
|
||||||
@@ -238,7 +238,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
|
logger.logDebug('开发转发', srcPeer, destPeer, retMsgIds);
|
||||||
return await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
|
return await this.core.apis.MsgApi.multiForwardMsg(srcPeer!, destPeer, retMsgIds);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.logError('forward failed', e);
|
logger.logError.bind(this.core.context.logger)('forward failed', e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
|
|||||||
try {
|
try {
|
||||||
return await this.core.apis.MsgApi.sendMsg(selfPeer, sendElements, true);
|
return await this.core.apis.MsgApi.sendMsg(selfPeer, sendElements, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.logError(e, '克隆转发消息失败,将忽略本条消息', msg);
|
logger.logError.bind(this.core.context.logger)(e, '克隆转发消息失败,将忽略本条消息', msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -289,7 +289,7 @@ export class OneBotGroupApi {
|
|||||||
}
|
}
|
||||||
const replyMsg = replyMsgList[0];
|
const replyMsg = replyMsgList[0];
|
||||||
if (!replyMsg) {
|
if (!replyMsg) {
|
||||||
this.core.context.logger.logError('解析表情回应消息失败: 未找到回应消息');
|
this.core.context.logger.logError.bind(this.core.context.logger)('解析表情回应消息失败: 未找到回应消息');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return new OB11GroupMsgEmojiLikeEvent(
|
return new OB11GroupMsgEmojiLikeEvent(
|
||||||
|
@@ -122,7 +122,7 @@ export class OneBotMsgApi {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.core.context.logger.logError('获取图片url失败', e.stack);
|
this.core.context.logger.logError.bind(this.core.context.logger)('获取图片url失败', e.stack);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -201,7 +201,7 @@ export class OneBotMsgApi {
|
|||||||
guildId: '',
|
guildId: '',
|
||||||
};
|
};
|
||||||
if (!records || !element.replyMsgTime || !element.senderUidStr) {
|
if (!records || !element.replyMsgTime || !element.senderUidStr) {
|
||||||
this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
|
this.core.context.logger.logError.bind(this.core.context.logger)('获取不到引用的消息', element.replayMsgSeq);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ export class OneBotMsgApi {
|
|||||||
.msgList.find(msg => msg.msgRandom === records.msgRandom);
|
.msgList.find(msg => msg.msgRandom === records.msgRandom);
|
||||||
|
|
||||||
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
|
if (!replyMsg || records.msgRandom !== replyMsg.msgRandom) {
|
||||||
this.core.context.logger.logError('获取不到引用的消息', element.replayMsgSeq);
|
this.core.context.logger.logError.bind(this.core.context.logger)('获取不到引用的消息', element.replayMsgSeq);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return createReplyData(replyMsg.msgId);
|
return createReplyData(replyMsg.msgId);
|
||||||
@@ -421,6 +421,10 @@ export class OneBotMsgApi {
|
|||||||
// 从face_config.json中获取表情名称
|
// 从face_config.json中获取表情名称
|
||||||
const sysFaces = faceConfig.sysface;
|
const sysFaces = faceConfig.sysface;
|
||||||
const face: any = sysFaces.find((systemFace) => systemFace.QSid === parsedFaceId.toString());
|
const face: any = sysFaces.find((systemFace) => systemFace.QSid === parsedFaceId.toString());
|
||||||
|
if (!face) {
|
||||||
|
this.core.context.logger.logError.bind(this.core.context.logger)('不支持的ID', id);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
parsedFaceId = parseInt(parsedFaceId.toString());
|
parsedFaceId = parseInt(parsedFaceId.toString());
|
||||||
let faceType = 1;
|
let faceType = 1;
|
||||||
if (parsedFaceId >= 222) {
|
if (parsedFaceId >= 222) {
|
||||||
@@ -543,32 +547,28 @@ export class OneBotMsgApi {
|
|||||||
|
|
||||||
[OB11MessageDataType.music]: async ({ data }, context) => {
|
[OB11MessageDataType.music]: async ({ data }, context) => {
|
||||||
// 保留, 直到...找到更好的解决方案
|
// 保留, 直到...找到更好的解决方案
|
||||||
if (data.type === 'custom') {
|
if (data.id !== undefined) {
|
||||||
if (!data.url) {
|
if (!['qq', '163', 'kugou', 'kuwo', 'migu'].includes(data.type)) {
|
||||||
this.core.context.logger.logError('自定义音卡缺少参数url');
|
this.core.context.logger.logError.bind(this.core.context.logger)('音乐卡片type错误, 只支持qq、163、kugou、kuwo、migu,当前type:', data.type);
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!data.audio) {
|
|
||||||
this.core.context.logger.logError('自定义音卡缺少参数audio');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!data.title) {
|
|
||||||
this.core.context.logger.logError('自定义音卡缺少参数title');
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!['qq', '163'].includes(data.type)) {
|
if (!['qq', '163', 'kugou', 'kuwo', 'migu', 'custom'].includes(data.type)) {
|
||||||
this.core.context.logger.logError('音乐卡片type错误, 只支持qq、163、custom,当前type:', data.type);
|
this.core.context.logger.logError.bind(this.core.context.logger)('音乐卡片type错误, 只支持qq、163、kugou、kuwo、migu、custom,当前type:', data.type);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (!data.id) {
|
if (!data.url) {
|
||||||
this.core.context.logger.logError('音乐卡片缺少参数id');
|
this.core.context.logger.logError.bind(this.core.context.logger)('自定义音卡缺少参数url');
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (!data.image) {
|
||||||
|
this.core.context.logger.logError.bind(this.core.context.logger)('自定义音卡缺少参数image');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let postData: IdMusicSignPostData | CustomMusicSignPostData;
|
let postData: IdMusicSignPostData | CustomMusicSignPostData;
|
||||||
if (data.type === 'custom' && data.content) {
|
if (data.id === undefined && data.content) {
|
||||||
const { content, ...others } = data;
|
const { content, ...others } = data;
|
||||||
postData = { singer: content, ...others };
|
postData = { singer: content, ...others };
|
||||||
} else {
|
} else {
|
||||||
@@ -576,7 +576,7 @@ export class OneBotMsgApi {
|
|||||||
}
|
}
|
||||||
let signUrl = this.obContext.configLoader.configData.musicSignUrl;
|
let signUrl = this.obContext.configLoader.configData.musicSignUrl;
|
||||||
if (!signUrl) {
|
if (!signUrl) {
|
||||||
signUrl = 'https://ss.xingzhige.com/music_card/card';//感谢思思!
|
signUrl = 'https://ss.xingzhige.com/music_card/card';//感谢思思!已获思思许可 其余地方使用请自行询问
|
||||||
//throw Error('音乐消息签名地址未配置');
|
//throw Error('音乐消息签名地址未配置');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -586,7 +586,7 @@ export class OneBotMsgApi {
|
|||||||
type: OB11MessageDataType.json
|
type: OB11MessageDataType.json
|
||||||
}, context);
|
}, context);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.core.context.logger.logError('生成音乐消息失败', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('生成音乐消息失败', e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -628,18 +628,14 @@ export class OneBotMsgApi {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const element of msg.elements) {
|
for (const element of msg.elements) {
|
||||||
if (element.grayTipElement) {
|
if (element.grayTipElement && element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
|
||||||
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
|
|
||||||
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 1061) {
|
||||||
const PokeEvent = await this.obContext.apis.FriendApi.parsePrivatePokeEvent(element.grayTipElement);
|
const PokeEvent = await this.obContext.apis.FriendApi.parsePrivatePokeEvent(element.grayTipElement);
|
||||||
if (PokeEvent) return PokeEvent;
|
if (PokeEvent) return PokeEvent;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (element.grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_XMLMSG) {
|
|
||||||
//好友添加成功事件
|
//好友添加成功事件
|
||||||
if (element.grayTipElement.xmlElement.templId === '10229' && msg.peerUin !== '') {
|
if (element.grayTipElement.jsonGrayTipElement.busiId == 19324 && msg.peerUid !== '') {
|
||||||
return new OB11FriendAddNoticeEvent(this.core, parseInt(msg.peerUin) || Number(await this.core.apis.UserApi.getUinByUidV2(msg.peerUid)));
|
return new OB11FriendAddNoticeEvent(this.core, Number(await this.core.apis.UserApi.getUinByUidV2(msg.peerUid)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -701,36 +697,46 @@ export class OneBotMsgApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const msgSegments = (await Promise.allSettled(msg.elements.map(
|
// 处理消息段
|
||||||
|
const msgSegments = await Promise.allSettled(msg.elements.map(
|
||||||
async (element) => {
|
async (element) => {
|
||||||
for (const key in element) {
|
for (const key in element) {
|
||||||
if (keyCanBeParsed(key, this.rawToOb11Converters) && element[key]) {
|
if (keyCanBeParsed(key, this.rawToOb11Converters) && element[key]) {
|
||||||
return await this.rawToOb11Converters[key]?.(
|
const parsedElement = await this.rawToOb11Converters[key]?.(
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
element[key],
|
element[key],
|
||||||
msg,
|
msg,
|
||||||
element,
|
element,
|
||||||
);
|
);
|
||||||
|
// 对于 face 类型的消息,检查是否存在
|
||||||
|
if (key === 'faceElement' && !parsedElement) {
|
||||||
|
return null; // 如果没有找到对应的表情,返回 null
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
))).filter(entry => {
|
));
|
||||||
|
|
||||||
|
// 过滤掉无效的消息段
|
||||||
|
const validSegments = msgSegments.filter(entry => {
|
||||||
if (entry.status === 'fulfilled') {
|
if (entry.status === 'fulfilled') {
|
||||||
return !!entry.value;
|
return !!entry.value;
|
||||||
} else {
|
} else {
|
||||||
this.core.context.logger.logError('消息段解析失败', entry.reason);
|
this.core.context.logger.logError.bind(this.core.context.logger)('消息段解析失败', entry.reason);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}).map((entry) => (<PromiseFulfilledResult<OB11MessageData>>entry).value);
|
}).map((entry) => (<PromiseFulfilledResult<OB11MessageData>>entry).value).filter(value => value != null);
|
||||||
|
|
||||||
const msgAsCQCode = msgSegments.map(msg => encodeCQCode(msg)).join('').trim();
|
const msgAsCQCode = validSegments.map(msg => encodeCQCode(msg)).join('').trim();
|
||||||
|
|
||||||
if (messagePostFormat === 'string') {
|
if (messagePostFormat === 'string') {
|
||||||
resMsg.message = msgAsCQCode;
|
resMsg.message = msgAsCQCode;
|
||||||
resMsg.raw_message = msgAsCQCode;
|
resMsg.raw_message = msgAsCQCode;
|
||||||
} else {
|
} else {
|
||||||
resMsg.message = msgSegments;
|
resMsg.message = validSegments;
|
||||||
resMsg.raw_message = msgAsCQCode;
|
resMsg.raw_message = msgAsCQCode;
|
||||||
}
|
}
|
||||||
return resMsg;
|
return resMsg;
|
||||||
@@ -787,7 +793,7 @@ export class OneBotMsgApi {
|
|||||||
timeout += PredictTime;// 10S Basic Timeout + PredictTime( For File 512kb/s )
|
timeout += PredictTime;// 10S Basic Timeout + PredictTime( For File 512kb/s )
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.core.context.logger.logError('发送消息计算预计时间异常', e);
|
this.core.context.logger.logError.bind(this.core.context.logger)('发送消息计算预计时间异常', e);
|
||||||
}
|
}
|
||||||
const returnMsg = await this.core.apis.MsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
const returnMsg = await this.core.apis.MsgApi.sendMsg(peer, sendElements, waitComplete, timeout);
|
||||||
if (!returnMsg) throw new Error('发送消息失败');
|
if (!returnMsg) throw new Error('发送消息失败');
|
||||||
@@ -797,7 +803,7 @@ export class OneBotMsgApi {
|
|||||||
peerUid: peer.peerUid,
|
peerUid: peer.peerUid,
|
||||||
}, returnMsg.msgId);
|
}, returnMsg.msgId);
|
||||||
deleteAfterSentFiles.forEach(file => {
|
deleteAfterSentFiles.forEach(file => {
|
||||||
fsPromise.unlink(file).then().catch(e => this.core.context.logger.logError('发送消息删除文件失败', e));
|
fsPromise.unlink(file).then().catch(e => this.core.context.logger.logError.bind(this.core.context.logger)('发送消息删除文件失败', e));
|
||||||
});
|
});
|
||||||
return returnMsg;
|
return returnMsg;
|
||||||
}
|
}
|
||||||
@@ -808,7 +814,7 @@ export class OneBotMsgApi {
|
|||||||
) {
|
) {
|
||||||
const realUri = inputdata.url || inputdata.file || inputdata.path || '';
|
const realUri = inputdata.url || inputdata.file || inputdata.path || '';
|
||||||
if (realUri.length === 0) {
|
if (realUri.length === 0) {
|
||||||
this.core.context.logger.logError('文件消息缺少参数', inputdata);
|
this.core.context.logger.logError.bind(this.core.context.logger)('文件消息缺少参数', inputdata);
|
||||||
throw Error('文件消息缺少参数');
|
throw Error('文件消息缺少参数');
|
||||||
}
|
}
|
||||||
const {
|
const {
|
||||||
@@ -819,7 +825,7 @@ export class OneBotMsgApi {
|
|||||||
} = (await uri2local(this.core.NapCatTempPath, realUri));
|
} = (await uri2local(this.core.NapCatTempPath, realUri));
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
this.core.context.logger.logError('文件下载失败', errMsg);
|
this.core.context.logger.logError.bind(this.core.context.logger)('文件下载失败', errMsg);
|
||||||
throw Error('文件下载失败' + errMsg);
|
throw Error('文件下载失败' + errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,7 +71,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
this.actions = createActionMap(this, core);
|
this.actions = createActionMap(this, core);
|
||||||
this.networkManager = new OB11NetworkManager();
|
this.networkManager = new OB11NetworkManager();
|
||||||
this.InitOneBot()
|
this.InitOneBot()
|
||||||
.catch(e => this.context.logger.logError('初始化OneBot失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('初始化OneBot失败', e));
|
||||||
}
|
}
|
||||||
|
|
||||||
async InitOneBot() {
|
async InitOneBot() {
|
||||||
@@ -87,7 +87,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid).then(user => {
|
this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid).then(user => {
|
||||||
selfInfo.nick = user.nick;
|
selfInfo.nick = user.nick;
|
||||||
this.context.logger.setLogSelfInfo(selfInfo);
|
this.context.logger.setLogSelfInfo(selfInfo);
|
||||||
}).catch(this.context.logger.logError);
|
}).catch(this.context.logger.logError.bind(this.context.logger));
|
||||||
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
|
||||||
|
|
||||||
//创建NetWork服务
|
//创建NetWork服务
|
||||||
@@ -241,7 +241,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
msgListener.onRecvSysMsg = (msg) => {
|
msgListener.onRecvSysMsg = (msg) => {
|
||||||
this.apis.MsgApi.parseSysMessage(msg).then((event) => {
|
this.apis.MsgApi.parseSysMessage(msg).then((event) => {
|
||||||
if (event) this.networkManager.emitEvent(event);
|
if (event) this.networkManager.emitEvent(event);
|
||||||
}).catch(e => this.context.logger.logError('constructSysMessage error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructSysMessage error: ', e));
|
||||||
};
|
};
|
||||||
|
|
||||||
msgListener.onInputStatusPush = async data => {
|
msgListener.onInputStatusPush = async data => {
|
||||||
@@ -270,7 +270,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
m.msgId,
|
m.msgId,
|
||||||
);
|
);
|
||||||
await this.emitMsg(m)
|
await this.emitMsg(m)
|
||||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -278,7 +278,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
const recallMsgs = new LRUCache<string, boolean>(100);
|
const recallMsgs = new LRUCache<string, boolean>(100);
|
||||||
msgListener.onMsgInfoListUpdate = async msgList => {
|
msgListener.onMsgInfoListUpdate = async msgList => {
|
||||||
this.emitRecallMsg(msgList, recallMsgs)
|
this.emitRecallMsg(msgList, recallMsgs)
|
||||||
.catch(e => this.context.logger.logError('处理消息失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
|
||||||
|
|
||||||
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
|
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
|
||||||
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && !msgIdSend.get(msg.msgId)) {
|
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && !msgIdSend.get(msg.msgId)) {
|
||||||
@@ -380,7 +380,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
].includes(notify.type) ? 'unset' : 'set',
|
].includes(notify.type) ? 'unset' : 'set',
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群管理员变动失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e));
|
||||||
} else {
|
} else {
|
||||||
this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode));
|
this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode));
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
subType,
|
subType,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupDecreaseEvent)
|
this.networkManager.emitEvent(groupDecreaseEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群成员退出失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群成员退出失败', e));
|
||||||
// notify.status == 1 表示未处理 2表示处理完成
|
// notify.status == 1 表示未处理 2表示处理完成
|
||||||
} else if ([
|
} else if ([
|
||||||
GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS,
|
GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS,
|
||||||
@@ -425,9 +425,9 @@ export class NapCatOneBot11Adapter {
|
|||||||
flag,
|
flag,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupRequestEvent)
|
this.networkManager.emitEvent(groupRequestEvent)
|
||||||
.catch(e => this.context.logger.logError('处理加群请求失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理加群请求失败', e));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.context.logger.logError('获取加群人QQ号失败 Uid:', notify.user1.uid, e);
|
this.context.logger.logError.bind(this.context.logger)('获取加群人QQ号失败 Uid:', notify.user1.uid, e);
|
||||||
}
|
}
|
||||||
} else if (notify.type == GroupNotifyMsgType.INVITED_BY_MEMBER && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
} else if (notify.type == GroupNotifyMsgType.INVITED_BY_MEMBER && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
||||||
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
|
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
|
||||||
@@ -440,7 +440,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
flag,
|
flag,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupInviteEvent)
|
this.networkManager.emitEvent(groupInviteEvent)
|
||||||
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e));
|
||||||
} else if (notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
} else if (notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
|
||||||
this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`);
|
this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`);
|
||||||
const groupInviteEvent = new OB11GroupRequestEvent(
|
const groupInviteEvent = new OB11GroupRequestEvent(
|
||||||
@@ -452,7 +452,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
flag,
|
flag,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupInviteEvent)
|
this.networkManager.emitEvent(groupInviteEvent)
|
||||||
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,9 +474,9 @@ export class NapCatOneBot11Adapter {
|
|||||||
member.role === GroupMemberRole.admin ? 'set' : 'unset',
|
member.role === GroupMemberRole.admin ? 'set' : 'unset',
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
this.networkManager.emitEvent(groupAdminNoticeEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群管理员变动失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e));
|
||||||
existMember.isChangeRole = false;
|
existMember.isChangeRole = false;
|
||||||
this.context.logger.logDebug('群管理员变动处理完毕');
|
this.context.logger.logDebug.bind(this.context.logger)('群管理员变动处理完毕');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -499,8 +499,6 @@ export class NapCatOneBot11Adapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// logOB11Message(this.core, ob11Msg)
|
|
||||||
// .catch(e => this.context.logger.logError('logMessage error: ', e));
|
|
||||||
const isSelfMsg = ob11Msg.user_id.toString() == this.core.selfInfo.uin;
|
const isSelfMsg = ob11Msg.user_id.toString() == this.core.selfInfo.uin;
|
||||||
if (isSelfMsg && !reportSelfMessage) {
|
if (isSelfMsg && !reportSelfMessage) {
|
||||||
return;
|
return;
|
||||||
@@ -509,21 +507,21 @@ export class NapCatOneBot11Adapter {
|
|||||||
ob11Msg.target_id = parseInt(message.peerUin);
|
ob11Msg.target_id = parseInt(message.peerUin);
|
||||||
}
|
}
|
||||||
this.networkManager.emitEvent(ob11Msg);
|
this.networkManager.emitEvent(ob11Msg);
|
||||||
}).catch(e => this.context.logger.logError('constructMessage error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructMessage error: ', e));
|
||||||
|
|
||||||
this.apis.GroupApi.parseGroupEvent(message).then(groupEvent => {
|
this.apis.GroupApi.parseGroupEvent(message).then(groupEvent => {
|
||||||
if (groupEvent) {
|
if (groupEvent) {
|
||||||
// log("post group event", groupEvent);
|
// log("post group event", groupEvent);
|
||||||
this.networkManager.emitEvent(groupEvent);
|
this.networkManager.emitEvent(groupEvent);
|
||||||
}
|
}
|
||||||
}).catch(e => this.context.logger.logError('constructGroupEvent error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructGroupEvent error: ', e));
|
||||||
|
|
||||||
this.apis.MsgApi.parsePrivateMsgEvent(message).then(privateEvent => {
|
this.apis.MsgApi.parsePrivateMsgEvent(message).then(privateEvent => {
|
||||||
if (privateEvent) {
|
if (privateEvent) {
|
||||||
// log("post private event", privateEvent);
|
// log("post private event", privateEvent);
|
||||||
this.networkManager.emitEvent(privateEvent);
|
this.networkManager.emitEvent(privateEvent);
|
||||||
}
|
}
|
||||||
}).catch(e => this.context.logger.logError('constructPrivateEvent error: ', e));
|
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructPrivateEvent error: ', e));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async emitRecallMsg(msgList: RawMessage[], cache: LRUCache<string, boolean>) {
|
private async emitRecallMsg(msgList: RawMessage[], cache: LRUCache<string, boolean>) {
|
||||||
@@ -543,7 +541,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
oriMessageId,
|
oriMessageId,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(friendRecallEvent)
|
this.networkManager.emitEvent(friendRecallEvent)
|
||||||
.catch(e => this.context.logger.logError('处理好友消息撤回失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理好友消息撤回失败', e));
|
||||||
} else if (message.chatType == ChatType.KCHATTYPEGROUP) {
|
} else if (message.chatType == ChatType.KCHATTYPEGROUP) {
|
||||||
let operatorId = message.senderUin;
|
let operatorId = message.senderUin;
|
||||||
for (const element of message.elements) {
|
for (const element of message.elements) {
|
||||||
@@ -560,7 +558,7 @@ export class NapCatOneBot11Adapter {
|
|||||||
oriMessageId,
|
oriMessageId,
|
||||||
);
|
);
|
||||||
this.networkManager.emitEvent(groupRecallEvent)
|
this.networkManager.emitEvent(groupRecallEvent)
|
||||||
.catch(e => this.context.logger.logError('处理群消息撤回失败', e));
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群消息撤回失败', e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -49,12 +49,12 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.obContext.apis.QuickActionApi
|
this.obContext.apis.QuickActionApi
|
||||||
.handleQuickOperation(event as QuickActionEvent, resJson)
|
.handleQuickOperation(event as QuickActionEvent, resJson)
|
||||||
.catch(this.logger.logError);
|
.catch(this.logger.logError.bind(this.logger));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.logger.logError('[OneBot] [Http Client] 新消息事件HTTP上报返回快速操作失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [Http Client] 新消息事件HTTP上报返回快速操作失败', e);
|
||||||
}
|
}
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
this.logger.logError('[OneBot] [Http Client] 新消息事件HTTP上报失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [Http Client] 新消息事件HTTP上报失败', e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -91,7 +91,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.connectEvent(this.core);
|
this.connectEvent(this.core);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发送连接生命周期失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发送连接生命周期失败', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -100,8 +100,8 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
});
|
});
|
||||||
this.connection.once('close', () => {
|
this.connection.once('close', () => {
|
||||||
if (!isClosedByError) {
|
if (!isClosedByError) {
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接意外关闭`);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接意外关闭`);
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
||||||
if (!this.isClosed) {
|
if (!this.isClosed) {
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
||||||
@@ -110,8 +110,8 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
});
|
});
|
||||||
this.connection.on('error', (err) => {
|
this.connection.on('error', (err) => {
|
||||||
isClosedByError = true;
|
isClosedByError = true;
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接错误`, err);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 反向WebSocket (${this.url}) 连接错误`, err);
|
||||||
this.logger.logError(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
this.logger.logError.bind(this.logger)(`[OneBot] [WebSocket Client] 在 ${Math.floor(this.reconnectIntervalInMillis / 1000)} 秒后尝试重新连接`);
|
||||||
if (!this.isClosed) {
|
if (!this.isClosed) {
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
setTimeout(() => this.tryConnect(), this.reconnectIntervalInMillis);
|
||||||
@@ -124,7 +124,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT));
|
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发送生命周期失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发送生命周期失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
||||||
const action = this.actions.get(receiveData.action);
|
const action = this.actions.get(receiveData.action);
|
||||||
if (!action) {
|
if (!action) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
||||||
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo));
|
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -55,7 +55,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
|
|
||||||
wsClient.on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Client Error:', err.message));
|
wsClient.on('error', (err) => this.logger.log('[OneBot] [WebSocket Server] Client Error:', err.message));
|
||||||
wsClient.on('message', (message) => {
|
wsClient.on('message', (message) => {
|
||||||
this.handleMessage(wsClient, message).then().catch(this.logger.logError);
|
this.handleMessage(wsClient, message).then().catch(this.logger.logError.bind(this.logger));
|
||||||
});
|
});
|
||||||
wsClient.on('ping', () => {
|
wsClient.on('ping', () => {
|
||||||
wsClient.pong();
|
wsClient.pong();
|
||||||
@@ -89,7 +89,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
try {
|
try {
|
||||||
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT), wsClient);
|
this.checkStateAndReply<any>(new OB11LifeCycleEvent(core, LifeCycleSubType.CONNECT), wsClient);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Server] 发送生命周期失败', e);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] 发送生命周期失败', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,11 +103,11 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
|
|
||||||
open() {
|
open() {
|
||||||
if (this.isOpen) {
|
if (this.isOpen) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Server] Cannot open a opened WebSocket server');
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] Cannot open a opened WebSocket server');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.hasBeenClosed) {
|
if (this.hasBeenClosed) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Server] Cannot open a WebSocket server that has been closed');
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Server] Cannot open a WebSocket server that has been closed');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const addressInfo = this.wsServer.address();
|
const addressInfo = this.wsServer.address();
|
||||||
@@ -170,7 +170,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
|
|||||||
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证
|
||||||
const action = this.actions.get(receiveData.action);
|
const action = this.actions.get(receiveData.action);
|
||||||
if (!action) {
|
if (!action) {
|
||||||
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
this.logger.logError.bind(this.logger)('[OneBot] [WebSocket Client] 发生错误', '不支持的api ' + receiveData.action);
|
||||||
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo), wsClient);
|
this.checkStateAndReply<any>(OB11Response.error('不支持的api ' + receiveData.action, 1404, echo), wsClient);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ import { NapCatOneBot11Adapter } from '@/onebot';
|
|||||||
import { InitWebUi } from '@/webui';
|
import { InitWebUi } from '@/webui';
|
||||||
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
|
||||||
import { napCatVersion } from '@/common/version';
|
import { napCatVersion } from '@/common/version';
|
||||||
|
import { NodeIO3MiscListener } from '@/core/listeners/NodeIO3MiscListener';
|
||||||
|
|
||||||
program.option('-q, --qq [number]', 'QQ号').parse(process.argv);
|
program.option('-q, --qq [number]', 'QQ号').parse(process.argv);
|
||||||
const cmdOptions = program.opts();
|
const cmdOptions = program.opts();
|
||||||
@@ -40,13 +41,18 @@ export async function NCoreInitShell() {
|
|||||||
const logger = new LogWrapper(pathWrapper.logsPath);
|
const logger = new LogWrapper(pathWrapper.logsPath);
|
||||||
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
||||||
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
||||||
|
|
||||||
|
const o3Service = wrapper.NodeIO3MiscService.get();
|
||||||
|
o3Service.addO3MiscListener(new NodeIO3MiscListener());
|
||||||
|
|
||||||
logger.log(`[NapCat] [Core] NapCat.Core Version: ` + napCatVersion);
|
logger.log(`[NapCat] [Core] NapCat.Core Version: ` + napCatVersion);
|
||||||
InitWebUi(logger, pathWrapper).then().catch(logger.logError);
|
InitWebUi(logger, pathWrapper).then().catch(logger.logError.bind(logger));
|
||||||
|
|
||||||
// from constructor
|
// from constructor
|
||||||
const engine = wrapper.NodeIQQNTWrapperEngine.get();
|
const engine = wrapper.NodeIQQNTWrapperEngine.get();
|
||||||
//const util = wrapper.NodeQQNTWrapperUtil.get();
|
//const util = wrapper.NodeQQNTWrapperUtil.get();
|
||||||
const loginService = wrapper.NodeIKernelLoginService.get();
|
const loginService = wrapper.NodeIKernelLoginService.get();
|
||||||
|
|
||||||
const session = wrapper.NodeIQQNTWrapperSession.create();
|
const session = wrapper.NodeIQQNTWrapperSession.create();
|
||||||
|
|
||||||
// from get dataPath
|
// from get dataPath
|
||||||
@@ -73,7 +79,7 @@ export async function NCoreInitShell() {
|
|||||||
systemPlatform = PlatformType.KMAC;
|
systemPlatform = PlatformType.KMAC;
|
||||||
break;
|
break;
|
||||||
case 'linux':
|
case 'linux':
|
||||||
systemPlatform = PlatformType.KANDROID; //Android 怎么不算Linux!
|
systemPlatform = PlatformType.KLINUX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!basicInfoWrapper.QQVersionAppid || !basicInfoWrapper.QQVersionQua) throw new Error('QQVersionAppid or QQVersionQua is not defined');
|
if (!basicInfoWrapper.QQVersionAppid || !basicInfoWrapper.QQVersionQua) throw new Error('QQVersionAppid or QQVersionQua is not defined');
|
||||||
@@ -85,7 +91,7 @@ export async function NCoreInitShell() {
|
|||||||
app_type: 4,
|
app_type: 4,
|
||||||
app_version: basicInfoWrapper.getFullQQVesion(),
|
app_version: basicInfoWrapper.getFullQQVesion(),
|
||||||
os_version: systemVersion,
|
os_version: systemVersion,
|
||||||
use_xlog: true,
|
use_xlog: false,
|
||||||
qua: basicInfoWrapper.QQVersionQua,
|
qua: basicInfoWrapper.QQVersionQua,
|
||||||
global_path_config: {
|
global_path_config: {
|
||||||
desktopGlobalPath: dataPathGlobal,
|
desktopGlobalPath: dataPathGlobal,
|
||||||
@@ -113,13 +119,14 @@ export async function NCoreInitShell() {
|
|||||||
quickLoginUin = '';
|
quickLoginUin = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let dataTimestape = new Date().getTime().toString();
|
||||||
|
o3Service.reportAmgomWeather('login', 'a1', [dataTimestape, '0', '0']);
|
||||||
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
||||||
const loginListener = new NodeIKernelLoginListener();
|
const loginListener = new NodeIKernelLoginListener();
|
||||||
let isLogined = false;
|
let isLogined = false;
|
||||||
// from constructor
|
// from constructor
|
||||||
loginListener.onUserLoggedIn = (userid: string) => {
|
loginListener.onUserLoggedIn = (userid: string) => {
|
||||||
logger.logError(`当前账号(${userid})已登录,无法重复登录`);
|
logger.logError.bind(logger)(`当前账号(${userid})已登录,无法重复登录`);
|
||||||
};
|
};
|
||||||
|
|
||||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||||
@@ -153,9 +160,8 @@ export async function NCoreInitShell() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
||||||
//logger.logError('登录失败(onQRCodeSessionFailed)', errCode, errMsg);
|
|
||||||
if (!isLogined) {
|
if (!isLogined) {
|
||||||
logger.logError('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
logger.logError.bind(logger)('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
||||||
if (errType == 1 && errCode == 3) {
|
if (errType == 1 && errCode == 3) {
|
||||||
// 二维码过期刷新
|
// 二维码过期刷新
|
||||||
}
|
}
|
||||||
@@ -163,14 +169,13 @@ export async function NCoreInitShell() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
loginListener.onLoginFailed = (args) => {
|
loginListener.onLoginFailed = (args) => {
|
||||||
//logger.logError('登录失败(onLoginFailed)', args);
|
logger.logError.bind(logger)('[Core] [Login] Login Error , ErrInfo: ', args);
|
||||||
logger.logError('[Core] [Login] Login Error , ErrInfo: ', args);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger) as any);
|
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger) as any);
|
||||||
const isConnect = loginService.connect();
|
const isConnect = loginService.connect();
|
||||||
if (!isConnect) {
|
if (!isConnect) {
|
||||||
logger.logError('核心登录服务连接失败!');
|
logger.logError.bind(logger)('核心登录服务连接失败!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.log('核心登录服务连接成功!');
|
logger.log('核心登录服务连接成功!');
|
||||||
@@ -179,18 +184,25 @@ export async function NCoreInitShell() {
|
|||||||
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
|
||||||
WebUiDataRuntime.setQQQuickLoginList(res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin.toString()));
|
WebUiDataRuntime.setQQQuickLoginList(res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin.toString()));
|
||||||
});
|
});
|
||||||
|
if (basicInfoWrapper.QQVersionConfig?.curVersion) {
|
||||||
|
loginService.getLoginMiscData('hotUpdateSign').then((res) => {
|
||||||
|
if (res.result === 0) {
|
||||||
|
loginService.setLoginMiscData('hotUpdateSign', res.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
session.getNodeMiscService().writeVersionToRegistry(basicInfoWrapper.QQVersionConfig?.curVersion);
|
||||||
|
}
|
||||||
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
|
||||||
return await new Promise((resolve) => {
|
return await new Promise((resolve) => {
|
||||||
if (uin) {
|
if (uin) {
|
||||||
logger.log('正在快速登录 ', uin);
|
logger.log.bind(logger)('正在快速登录 ', uin);
|
||||||
loginService.quickLoginWithUin(uin).then(res => {
|
loginService.quickLoginWithUin(uin).then(res => {
|
||||||
if (res.loginErrorInfo.errMsg) {
|
if (res.loginErrorInfo.errMsg) {
|
||||||
resolve({ result: false, message: res.loginErrorInfo.errMsg });
|
resolve({ result: false, message: res.loginErrorInfo.errMsg });
|
||||||
}
|
}
|
||||||
resolve({ result: true, message: '' });
|
resolve({ result: true, message: '' });
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
logger.logError(e);
|
logger.logError.bind(logger)(e);
|
||||||
resolve({ result: false, message: '快速登录发生错误' });
|
resolve({ result: false, message: '快速登录发生错误' });
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -206,14 +218,14 @@ export async function NCoreInitShell() {
|
|||||||
loginService.quickLoginWithUin(quickLoginUin)
|
loginService.quickLoginWithUin(quickLoginUin)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.loginErrorInfo.errMsg) {
|
if (result.loginErrorInfo.errMsg) {
|
||||||
logger.logError('快速登录错误:', result.loginErrorInfo.errMsg);
|
logger.logError.bind(logger)('快速登录错误:', result.loginErrorInfo.errMsg);
|
||||||
if (!isLogined) loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch();
|
.catch();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
logger.logError('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
logger.logError.bind(logger)('快速登录失败,未找到该 QQ 历史登录记录,将使用二维码登录方式');
|
||||||
if (!isLogined) loginService.getQRCodePicture();
|
if (!isLogined) loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -228,12 +240,24 @@ export async function NCoreInitShell() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// BEFORE LOGGING IN
|
// BEFORE LOGGING IN
|
||||||
|
let amgomDataPiece = 'eb1fd6ac257461580dc7438eb099f23aae04ca679f4d88f53072dc56e3bb1129';
|
||||||
|
o3Service.setAmgomDataPiece(basicInfoWrapper.QQVersionAppid, new Uint8Array(Buffer.from(amgomDataPiece, 'hex')));
|
||||||
// AFTER LOGGING IN
|
// AFTER LOGGING IN
|
||||||
|
//99b15bdb4c984fc69d5aa1feb9aa16xx --> 99b15bdb-4c98-4fc6-9d5a-a1feb9aa16xx
|
||||||
|
//把guid从左向右转换为guid格式 loginService.getMachineGuid()
|
||||||
|
|
||||||
|
let guid = loginService.getMachineGuid();
|
||||||
|
guid = guid.slice(0, 8) + '-' + guid.slice(8, 12) + '-' + guid.slice(12, 16) + '-' + guid.slice(16, 20) + '-' + guid.slice(20);
|
||||||
|
//console.log('guid:', guid);
|
||||||
|
//NodeIO3MiscService/reportAmgomWeather login a6 [ '1726748166943', '184', '329' ]
|
||||||
|
o3Service.reportAmgomWeather('login', 'a6', [dataTimestape, '184', '329']);
|
||||||
|
// if(session.getUnitedConfigService()){
|
||||||
|
// session.getUnitedConfigService().fetchUnitedCommendConfig([]);
|
||||||
|
// }
|
||||||
// from initSession
|
// from initSession
|
||||||
await new Promise<void>(async (resolve, reject) => {
|
await new Promise<void>(async (resolve, reject) => {
|
||||||
const sessionConfig = await genSessionConfig(
|
const sessionConfig = await genSessionConfig(
|
||||||
|
guid,
|
||||||
basicInfoWrapper.QQVersionAppid!,
|
basicInfoWrapper.QQVersionAppid!,
|
||||||
basicInfoWrapper.getFullQQVesion(),
|
basicInfoWrapper.getFullQQVesion(),
|
||||||
selfInfo.uin,
|
selfInfo.uin,
|
||||||
|
@@ -54,7 +54,7 @@ export async function InitWebUi(logger: LogWrapper, pathWrapper: NapCatPathWrapp
|
|||||||
).then((data) => {
|
).then((data) => {
|
||||||
log(`[NapCat] [WebUi] WebUi Publish Panel Url: http://${data.IP.IP}:${config.port}${config.prefix}/webui/?token=${config.token}`);
|
log(`[NapCat] [WebUi] WebUi Publish Panel Url: http://${data.IP.IP}:${config.port}${config.prefix}/webui/?token=${config.token}`);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
logger.logError(`[NapCat] [WebUi] Get Publish Panel Url Error: ${err}`);
|
logger.logError.bind(logger)(`[NapCat] [WebUi] Get Publish Panel Url Error: ${err}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@@ -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.6.4', 'napcat-update-button', 'secondary'),
|
SettingButton('V2.6.13', 'napcat-update-button', 'secondary'),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
|
|||||||
SettingItem(
|
SettingItem(
|
||||||
'<span id="napcat-update-title">Napcat</span>',
|
'<span id="napcat-update-title">Napcat</span>',
|
||||||
void 0,
|
void 0,
|
||||||
SettingButton("V2.6.4", "napcat-update-button", "secondary")
|
SettingButton("V2.6.13", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
Reference in New Issue
Block a user