mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b5ef6ce6b0 | ||
![]() |
704ac11cbb | ||
![]() |
aa9663d85e | ||
![]() |
05291f34fb | ||
![]() |
2260fe32a1 | ||
![]() |
2c398a6832 | ||
![]() |
3e1f566699 | ||
![]() |
4f89f184b8 | ||
![]() |
787685c937 | ||
![]() |
ed9cd2fe38 | ||
![]() |
e287906a9d | ||
![]() |
8bae789020 | ||
![]() |
ce57b7b725 | ||
![]() |
1d9872195d | ||
![]() |
98d1f8e29f | ||
![]() |
221b3fb730 | ||
![]() |
90a834495a | ||
![]() |
8bfd102232 | ||
![]() |
65e784f169 | ||
![]() |
0fc81c672f | ||
![]() |
62ae0f4321 | ||
![]() |
a01a0a1a18 | ||
![]() |
4c30cc69ad | ||
![]() |
1d43b75df4 |
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -127,10 +127,6 @@ jobs:
|
|||||||
zip -q -r NapCat.Framework.Windows.Once.zip *
|
zip -q -r NapCat.Framework.Windows.Once.zip *
|
||||||
cd ..
|
cd ..
|
||||||
mv ./NapCat.Framework.Windows.Once/NapCat.Framework.Windows.Once.zip ./
|
mv ./NapCat.Framework.Windows.Once/NapCat.Framework.Windows.Once.zip ./
|
||||||
mv ./external/packet/napcat.packet.arm64 ./
|
|
||||||
mv ./external/packet/napcat.packet.exe ./
|
|
||||||
mv ./external/packet/napcat.packet.linux ./
|
|
||||||
mv ./external/packet/napcat.packet.production.py ./
|
|
||||||
- name: Extract version from tag
|
- name: Extract version from tag
|
||||||
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
@@ -147,8 +143,4 @@ jobs:
|
|||||||
NapCat.Framework.zip
|
NapCat.Framework.zip
|
||||||
NapCat.Shell.zip
|
NapCat.Shell.zip
|
||||||
NapCat.Framework.Windows.Once.zip
|
NapCat.Framework.Windows.Once.zip
|
||||||
napcat.packet.arm64
|
|
||||||
napcat.packet.exe
|
|
||||||
napcat.packet.linux
|
|
||||||
napcat.packet.production.py
|
|
||||||
draft: true
|
draft: true
|
||||||
|
@@ -30,6 +30,10 @@ NapCatQQ (aka 猫猫框架) 是现代化的基于 NTQQ 的 Bot 协议端实现
|
|||||||
|
|
||||||
[Cloudflare.Pages](https://napneko.pages.dev/)
|
[Cloudflare.Pages](https://napneko.pages.dev/)
|
||||||
|
|
||||||
|
[Server.China](https://napneko.com/)
|
||||||
|
|
||||||
|
[Server.Other](https://napcat.cyou/)
|
||||||
|
|
||||||
[Github.IO](https://napneko.github.io/)
|
[Github.IO](https://napneko.github.io/)
|
||||||
## 回家旅途
|
## 回家旅途
|
||||||
[QQ Group](https://qm.qq.com/q/VfjAq5HIMS)
|
[QQ Group](https://qm.qq.com/q/VfjAq5HIMS)
|
||||||
|
BIN
external/LiteLoaderWrapper.zip
vendored
BIN
external/LiteLoaderWrapper.zip
vendored
Binary file not shown.
BIN
external/packet/napcat.packet.arm64
vendored
BIN
external/packet/napcat.packet.arm64
vendored
Binary file not shown.
BIN
external/packet/napcat.packet.exe
vendored
BIN
external/packet/napcat.packet.exe
vendored
Binary file not shown.
BIN
external/packet/napcat.packet.linux
vendored
BIN
external/packet/napcat.packet.linux
vendored
Binary file not shown.
102
external/packet/napcat.packet.production.py
vendored
102
external/packet/napcat.packet.production.py
vendored
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
|||||||
"name": "NapCatQQ",
|
"name": "NapCatQQ",
|
||||||
"slug": "NapCat.Framework",
|
"slug": "NapCat.Framework",
|
||||||
"description": "高性能的 OneBot 11 协议实现",
|
"description": "高性能的 OneBot 11 协议实现",
|
||||||
"version": "3.6.7",
|
"version": "3.6.15",
|
||||||
"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": "3.6.7",
|
"version": "3.6.15",
|
||||||
"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",
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
"@typescript-eslint/parser": "^8.3.0",
|
"@typescript-eslint/parser": "^8.3.0",
|
||||||
"ajv": "^8.13.0",
|
"ajv": "^8.13.0",
|
||||||
"async-mutex": "^0.5.0",
|
"async-mutex": "^0.5.0",
|
||||||
"chalk": "^5.3.0",
|
|
||||||
"commander": "^12.1.0",
|
"commander": "^12.1.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"eslint": "^9.14.0",
|
"eslint": "^9.14.0",
|
||||||
@@ -45,12 +44,12 @@
|
|||||||
"typescript-eslint": "^8.13.0",
|
"typescript-eslint": "^8.13.0",
|
||||||
"vite": "^5.2.6",
|
"vite": "^5.2.6",
|
||||||
"vite-plugin-cp": "^4.0.8",
|
"vite-plugin-cp": "^4.0.8",
|
||||||
"vite-tsconfig-paths": "^5.1.0"
|
"vite-tsconfig-paths": "^5.1.0",
|
||||||
|
"winston": "^3.17.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^5.0.0",
|
"express": "^5.0.0",
|
||||||
"fluent-ffmpeg": "^2.1.2",
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"log4js": "^6.9.1",
|
|
||||||
"qrcode-terminal": "^0.12.0",
|
"qrcode-terminal": "^0.12.0",
|
||||||
"silk-wasm": "^3.6.1",
|
"silk-wasm": "^3.6.1",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import log4js, { Configuration } from 'log4js';
|
import winston, { format, transports } from 'winston';
|
||||||
import { truncateString } from '@/common/helper';
|
import { truncateString } from '@/common/helper';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import chalk from 'chalk';
|
import fs from 'node:fs';
|
||||||
import { AtType, ChatType, ElementType, MessageElement, RawMessage, SelfInfo } from '@/core';
|
import { AtType, ChatType, ElementType, MessageElement, RawMessage, SelfInfo } from '@/core';
|
||||||
|
|
||||||
export enum LogLevel {
|
export enum LogLevel {
|
||||||
@@ -27,97 +27,132 @@ function getFormattedTimestamp() {
|
|||||||
export class LogWrapper {
|
export class LogWrapper {
|
||||||
fileLogEnabled = true;
|
fileLogEnabled = true;
|
||||||
consoleLogEnabled = true;
|
consoleLogEnabled = true;
|
||||||
logConfig: Configuration;
|
logger: winston.Logger;
|
||||||
loggerConsole: log4js.Logger;
|
|
||||||
loggerFile: log4js.Logger;
|
|
||||||
loggerDefault: log4js.Logger;
|
|
||||||
// eslint-disable-next-line no-control-regex
|
|
||||||
colorEscape = /\x1B[@-_][0-?]*[ -/]*[@-~]/g;
|
|
||||||
|
|
||||||
constructor(logDir: string) {
|
constructor(logDir: string) {
|
||||||
const filename = `${getFormattedTimestamp()}.log`;
|
const filename = `${getFormattedTimestamp()}.log`;
|
||||||
const logPath = path.join(logDir, filename);
|
const logPath = path.join(logDir, filename);
|
||||||
this.logConfig = {
|
|
||||||
appenders: {
|
this.logger = winston.createLogger({
|
||||||
FileAppender: { // 输出到文件的appender
|
level: 'debug',
|
||||||
type: 'file',
|
format: format.combine(
|
||||||
filename: logPath, // 指定日志文件的位置和文件名
|
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
||||||
maxLogSize: 10485760, // 日志文件的最大大小(单位:字节),这里设置为10MB
|
format.printf(({ timestamp, level, message, ...meta }) => {
|
||||||
layout: {
|
const userInfo = meta.userInfo ? `${meta.userInfo} | ` : '';
|
||||||
type: 'pattern',
|
return `${timestamp} [${level}] ${userInfo}${message}`;
|
||||||
pattern: '%d{yyyy-MM-dd hh:mm:ss} [%p] %X{userInfo} | %m',
|
})
|
||||||
},
|
),
|
||||||
},
|
transports: [
|
||||||
ConsoleAppender: { // 输出到控制台的appender
|
new transports.File({
|
||||||
type: 'console',
|
filename: logPath,
|
||||||
layout: {
|
level: 'debug',
|
||||||
type: 'pattern',
|
maxsize: 5 * 1024 * 1024, // 5MB
|
||||||
pattern: `%d{yyyy-MM-dd hh:mm:ss} [%[%p%]] ${chalk.magenta('%X{userInfo}')} | %m`,
|
maxFiles: 5
|
||||||
},
|
}),
|
||||||
},
|
new transports.Console({
|
||||||
},
|
format: format.combine(
|
||||||
categories: {
|
format.colorize(),
|
||||||
default: { appenders: ['FileAppender', 'ConsoleAppender'], level: 'debug' }, // 默认情况下同时输出到文件和控制台
|
format.printf(({ timestamp, level, message, ...meta }) => {
|
||||||
file: { appenders: ['FileAppender'], level: 'debug' },
|
const userInfo = meta.userInfo ? `${meta.userInfo} | ` : '';
|
||||||
console: { appenders: ['ConsoleAppender'], level: 'debug' },
|
return `${timestamp} [${level}] ${userInfo}${message}`;
|
||||||
},
|
})
|
||||||
};
|
)
|
||||||
log4js.configure(this.logConfig);
|
})
|
||||||
this.loggerConsole = log4js.getLogger('console');
|
]
|
||||||
this.loggerFile = log4js.getLogger('file');
|
});
|
||||||
this.loggerDefault = log4js.getLogger('default');
|
|
||||||
this.setLogSelfInfo({ nick: '', uin: '', uid: '' });
|
this.setLogSelfInfo({ nick: '', uin: '', uid: '' });
|
||||||
|
this.cleanOldLogs(logDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanOldLogs(logDir: string) {
|
||||||
|
const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
|
||||||
|
fs.readdir(logDir, (err, files) => {
|
||||||
|
if (err) {
|
||||||
|
this.logger.error('Failed to read log directory', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
files.forEach(file => {
|
||||||
|
const filePath = path.join(logDir, file);
|
||||||
|
fs.stat(filePath, (err, stats) => {
|
||||||
|
if (err) {
|
||||||
|
this.logger.error('Failed to get file stats', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (stats.mtime.getTime() < oneWeekAgo) {
|
||||||
|
fs.unlink(filePath, err => {
|
||||||
|
if (err) {
|
||||||
|
if (err.code === 'ENOENT') {
|
||||||
|
this.logger.warn(`File already deleted: ${file}`);
|
||||||
|
} else {
|
||||||
|
this.logger.error('Failed to delete old log file', err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.logger.info(`Deleted old log file: ${file}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setFileAndConsoleLogLevel(fileLogLevel: LogLevel, consoleLogLevel: LogLevel) {
|
setFileAndConsoleLogLevel(fileLogLevel: LogLevel, consoleLogLevel: LogLevel) {
|
||||||
this.logConfig.categories.file.level = fileLogLevel;
|
this.logger.transports.forEach((transport) => {
|
||||||
this.logConfig.categories.console.level = consoleLogLevel;
|
if (transport instanceof transports.File) {
|
||||||
log4js.configure(this.logConfig);
|
transport.level = fileLogLevel;
|
||||||
|
} else if (transport instanceof transports.Console) {
|
||||||
|
transport.level = consoleLogLevel;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setLogSelfInfo(selfInfo: { nick: string, uin: string, uid: string }) {
|
setLogSelfInfo(selfInfo: { nick: string, uin: string, uid: string }) {
|
||||||
const userInfo = `${selfInfo.nick}(${selfInfo.uin})`;
|
const userInfo = `${selfInfo.nick}(${selfInfo.uin})`;
|
||||||
this.loggerConsole.addContext('userInfo', userInfo);
|
this.logger.defaultMeta = { userInfo };
|
||||||
this.loggerFile.addContext('userInfo', userInfo);
|
|
||||||
this.loggerDefault.addContext('userInfo', userInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setFileLogEnabled(isEnabled: boolean) {
|
setFileLogEnabled(isEnabled: boolean) {
|
||||||
this.fileLogEnabled = isEnabled;
|
this.fileLogEnabled = isEnabled;
|
||||||
|
this.logger.transports.forEach((transport) => {
|
||||||
|
if (transport instanceof transports.File) {
|
||||||
|
transport.silent = !isEnabled;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setConsoleLogEnabled(isEnabled: boolean) {
|
setConsoleLogEnabled(isEnabled: boolean) {
|
||||||
this.consoleLogEnabled = isEnabled;
|
this.consoleLogEnabled = isEnabled;
|
||||||
|
this.logger.transports.forEach((transport) => {
|
||||||
|
if (transport instanceof transports.Console) {
|
||||||
|
transport.silent = !isEnabled;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formatMsg(msg: any[]) {
|
formatMsg(msg: any[]) {
|
||||||
let logMsg = '';
|
return msg.map(msgItem => {
|
||||||
for (const msgItem of msg) {
|
if (msgItem instanceof Error) {
|
||||||
if (msgItem instanceof Error) { // 判断是否是错误
|
return msgItem.stack;
|
||||||
logMsg += msgItem.stack + ' ';
|
} else if (typeof msgItem === 'object') {
|
||||||
continue;
|
return JSON.stringify(truncateString(JSON.parse(JSON.stringify(msgItem, null, 2))));
|
||||||
} else if (typeof msgItem === 'object') { // 判断是否是对象
|
|
||||||
const obj = JSON.parse(JSON.stringify(msgItem, null, 2));
|
|
||||||
logMsg += JSON.stringify(truncateString(obj)) + ' ';
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
logMsg += msgItem + ' ';
|
return msgItem;
|
||||||
}
|
}).join(' ');
|
||||||
return logMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_log(level: LogLevel, ...args: any[]) {
|
_log(level: LogLevel, ...args: any[]) {
|
||||||
if (this.consoleLogEnabled) {
|
const message = this.formatMsg(args);
|
||||||
this.loggerConsole[level](this.formatMsg(args));
|
if (this.consoleLogEnabled && this.fileLogEnabled) {
|
||||||
}
|
this.logger.log(level, message);
|
||||||
if (this.fileLogEnabled) {
|
} else if (this.consoleLogEnabled) {
|
||||||
this.loggerFile[level](this.formatMsg(args).replace(this.colorEscape, ''));
|
this.logger.log(level, message);
|
||||||
|
} else if (this.fileLogEnabled) {
|
||||||
|
this.logger.log(level, message.replace(/\x1B[@-_][0-?]*[ -/]*[@-~]/g, ''));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log(...args: any[]) {
|
log(...args: any[]) {
|
||||||
// info 等级
|
|
||||||
this._log(LogLevel.INFO, ...args);
|
this._log(LogLevel.INFO, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,12 +175,11 @@ export class LogWrapper {
|
|||||||
logMessage(msg: RawMessage, selfInfo: SelfInfo) {
|
logMessage(msg: RawMessage, selfInfo: SelfInfo) {
|
||||||
const isSelfSent = msg.senderUin === selfInfo.uin;
|
const isSelfSent = msg.senderUin === selfInfo.uin;
|
||||||
|
|
||||||
// Intercept grey tip
|
|
||||||
if (msg.elements[0]?.elementType === ElementType.GreyTip) {
|
if (msg.elements[0]?.elementType === ElementType.GreyTip) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log(`${isSelfSent ? '发送 ->' : '接收 <-' } ${rawMessageToText(msg)}`);
|
this.log(`${isSelfSent ? '发送 ->' : '接收 <-'} ${rawMessageToText(msg)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,12 +201,10 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
|||||||
}
|
}
|
||||||
} else if (msg.chatType == ChatType.KCHATTYPEDATALINE) {
|
} else if (msg.chatType == ChatType.KCHATTYPEDATALINE) {
|
||||||
tokens.push('移动设备');
|
tokens.push('移动设备');
|
||||||
} else /* temp */ {
|
} else {
|
||||||
tokens.push(`临时消息 (${msg.peerUin})`);
|
tokens.push(`临时消息 (${msg.peerUin})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// message content
|
|
||||||
|
|
||||||
function msgElementToText(element: MessageElement) {
|
function msgElementToText(element: MessageElement) {
|
||||||
if (element.textElement) {
|
if (element.textElement) {
|
||||||
if (element.textElement.atType === AtType.notAt) {
|
if (element.textElement.atType === AtType.notAt) {
|
||||||
@@ -190,11 +222,11 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
|||||||
record => element.replyElement!.sourceMsgIdInRecords === record.msgId,
|
record => element.replyElement!.sourceMsgIdInRecords === record.msgId,
|
||||||
);
|
);
|
||||||
return `[回复消息 ${recordMsgOrNull &&
|
return `[回复消息 ${recordMsgOrNull &&
|
||||||
recordMsgOrNull.peerUin != '284840486' && recordMsgOrNull.peerUin != '1094950020'// 非转发消息; 否则定位不到
|
recordMsgOrNull.peerUin != '284840486' && recordMsgOrNull.peerUin != '1094950020'
|
||||||
?
|
?
|
||||||
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
|
rawMessageToText(recordMsgOrNull, recursiveLevel + 1) :
|
||||||
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})`
|
`未找到消息记录 (MsgId = ${element.replyElement.sourceMsgIdInRecords})`
|
||||||
}]`;
|
}]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element.picElement) {
|
if (element.picElement) {
|
||||||
@@ -245,4 +277,4 @@ export function rawMessageToText(msg: RawMessage, recursiveLevel = 0): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return tokens.join(' ');
|
return tokens.join(' ');
|
||||||
}
|
}
|
@@ -1 +1 @@
|
|||||||
export const napCatVersion = '3.6.7';
|
export const napCatVersion = '3.6.15';
|
||||||
|
26
src/core/external/offset.json
vendored
26
src/core/external/offset.json
vendored
@@ -1,8 +1,4 @@
|
|||||||
{
|
{
|
||||||
"6.9.56-28418-arm64": {
|
|
||||||
"send": "4471360",
|
|
||||||
"recv": "4473BCC"
|
|
||||||
},
|
|
||||||
"3.2.12-28418-x64": {
|
"3.2.12-28418-x64": {
|
||||||
"recv": "A0723E0",
|
"recv": "A0723E0",
|
||||||
"send": "A06EAE0"
|
"send": "A06EAE0"
|
||||||
@@ -11,6 +7,14 @@
|
|||||||
"recv": "37A9004",
|
"recv": "37A9004",
|
||||||
"send": "37A4BD0"
|
"send": "37A4BD0"
|
||||||
},
|
},
|
||||||
|
"6.9.56-28418-x64": {
|
||||||
|
"send": "4471360",
|
||||||
|
"recv": "4473BCC"
|
||||||
|
},
|
||||||
|
"6.9.56-28418-arm64": {
|
||||||
|
"send": "3FBDBF8",
|
||||||
|
"recv": "3FC0410"
|
||||||
|
},
|
||||||
"9.9.15-28498-x64": {
|
"9.9.15-28498-x64": {
|
||||||
"recv": "37A9004",
|
"recv": "37A9004",
|
||||||
"send": "37A4BD0"
|
"send": "37A4BD0"
|
||||||
@@ -39,10 +43,14 @@
|
|||||||
"send": "6E91318",
|
"send": "6E91318",
|
||||||
"recv": "6E94B50"
|
"recv": "6E94B50"
|
||||||
},
|
},
|
||||||
"6.9.58-28971-arm64": {
|
"6.9.58-28971-x64": {
|
||||||
"send": "449ACA0",
|
"send": "449ACA0",
|
||||||
"recv": "449D50C"
|
"recv": "449D50C"
|
||||||
},
|
},
|
||||||
|
"6.9.58-28971-arm64": {
|
||||||
|
"send": "3FE0DB0",
|
||||||
|
"recv": "3FE35C8"
|
||||||
|
},
|
||||||
"9.9.16-29271-x64": {
|
"9.9.16-29271-x64": {
|
||||||
"send": "3833510",
|
"send": "3833510",
|
||||||
"recv": "3837944"
|
"recv": "3837944"
|
||||||
@@ -66,5 +74,13 @@
|
|||||||
"3.2.13-29456-arm64": {
|
"3.2.13-29456-arm64": {
|
||||||
"send": "6ECA130",
|
"send": "6ECA130",
|
||||||
"recv": "6ECD968"
|
"recv": "6ECD968"
|
||||||
|
},
|
||||||
|
"6.9.59-29456-x64": {
|
||||||
|
"send": "44C57A0",
|
||||||
|
"recv": "44C800C"
|
||||||
|
},
|
||||||
|
"6.9.59-29456-arm64": {
|
||||||
|
"send": "4005FE8",
|
||||||
|
"recv": "4008800"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { ChatType, RawMessage } from '@/core/entities';
|
import { ChatType, KickedOffLineInfo, RawMessage } from '@/core/entities';
|
||||||
import { CommonFileInfo } from '@/core';
|
import { CommonFileInfo } from '@/core';
|
||||||
|
|
||||||
export interface OnRichMediaDownloadCompleteParams {
|
export interface OnRichMediaDownloadCompleteParams {
|
||||||
@@ -212,7 +212,7 @@ export class NodeIKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onKickedOffLine(kickedInfo: unknown) {
|
onKickedOffLine(kickedInfo: KickedOffLineInfo) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,6 +23,14 @@ export async function NCoreInitFramework(
|
|||||||
) {
|
) {
|
||||||
//在进入本层前是否登录未进行判断
|
//在进入本层前是否登录未进行判断
|
||||||
console.log('NapCat Framework App Loading...');
|
console.log('NapCat Framework App Loading...');
|
||||||
|
|
||||||
|
process.on('uncaughtException', (err) => {
|
||||||
|
console.log('[NapCat] [Error] Unhandled Exception:', err.message);
|
||||||
|
});
|
||||||
|
process.on('unhandledRejection', (reason, promise) => {
|
||||||
|
console.log('[NapCat] [Error] unhandledRejection:', reason);
|
||||||
|
});
|
||||||
|
|
||||||
const pathWrapper = new NapCatPathWrapper();
|
const pathWrapper = new NapCatPathWrapper();
|
||||||
const logger = new LogWrapper(pathWrapper.logsPath);
|
const logger = new LogWrapper(pathWrapper.logsPath);
|
||||||
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
||||||
|
BIN
src/native/packet/MoeHoo.darwin.arm64.node
Normal file
BIN
src/native/packet/MoeHoo.darwin.arm64.node
Normal file
Binary file not shown.
@@ -42,7 +42,7 @@ export default class GoCQHTTPUploadGroupFile extends BaseAction<Payload, null> {
|
|||||||
deleteAfterSentFiles: []
|
deleteAfterSentFiles: []
|
||||||
};
|
};
|
||||||
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name, payload.folder ?? payload.folder_id);
|
const sendFileEle = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name, payload.folder ?? payload.folder_id);
|
||||||
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, [sendFileEle], [], true);
|
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(peer, [sendFileEle], msgContext.deleteAfterSentFiles, true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -53,7 +53,7 @@ export default class GoCQHTTPUploadPrivateFile extends BaseAction<Payload, null>
|
|||||||
deleteAfterSentFiles: []
|
deleteAfterSentFiles: []
|
||||||
};
|
};
|
||||||
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name);
|
const sendFileEle: SendFileElement = await this.core.apis.FileApi.createValidSendFileElement(msgContext, downloadResult.path, payload.name);
|
||||||
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], [], true);
|
await this.obContext.apis.MsgApi.sendMsgWithOb11UniqueId(await this.getPeer(payload), [sendFileEle], msgContext.deleteAfterSentFiles, true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,12 +2,14 @@ import { ChatType, Peer } from '@/core/entities';
|
|||||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||||
import BaseAction from '../BaseAction';
|
import BaseAction from '../BaseAction';
|
||||||
import { ActionName } from '../types';
|
import { ActionName } from '../types';
|
||||||
|
import { MessageUnique } from '@/common/message-unique';
|
||||||
|
|
||||||
const SchemaData = {
|
const SchemaData = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
user_id: { type: ['number', 'string'] },
|
user_id: { type: ['number', 'string'] },
|
||||||
group_id: { type: ['number', 'string'] },
|
group_id: { type: ['number', 'string'] },
|
||||||
|
message_id: { type: ['number', 'string'] },
|
||||||
},
|
},
|
||||||
} as const satisfies JSONSchema;
|
} as const satisfies JSONSchema;
|
||||||
|
|
||||||
@@ -15,6 +17,16 @@ type PlayloadType = FromSchema<typeof SchemaData>;
|
|||||||
|
|
||||||
class MarkMsgAsRead extends BaseAction<PlayloadType, null> {
|
class MarkMsgAsRead extends BaseAction<PlayloadType, null> {
|
||||||
async getPeer(payload: PlayloadType): Promise<Peer> {
|
async getPeer(payload: PlayloadType): Promise<Peer> {
|
||||||
|
if (payload.message_id) {
|
||||||
|
let s_peer = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id)?.Peer;
|
||||||
|
if (s_peer) {
|
||||||
|
return s_peer;
|
||||||
|
}
|
||||||
|
let l_peer = MessageUnique.getPeerByMsgId(payload.message_id.toString())?.Peer;
|
||||||
|
if (l_peer) {
|
||||||
|
return l_peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (payload.user_id) {
|
if (payload.user_id) {
|
||||||
const peerUid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
|
const peerUid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
|
||||||
if (!peerUid) {
|
if (!peerUid) {
|
||||||
|
@@ -190,6 +190,7 @@ export class OneBotMsgApi {
|
|||||||
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "", "." + _.key + ".jpg"),
|
file_id: FileNapCatOneBotUUID.encode(peer, msg.msgId, elementWrapper.elementId, "", "." + _.key + ".jpg"),
|
||||||
path: url,
|
path: url,
|
||||||
url: url,
|
url: url,
|
||||||
|
key: _.key,
|
||||||
file_unique: _.key
|
file_unique: _.key
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
16
src/onebot/event/notice/BotOfflineEvent.ts
Normal file
16
src/onebot/event/notice/BotOfflineEvent.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { OB11BaseNoticeEvent } from './OB11BaseNoticeEvent';
|
||||||
|
import { NapCatCore } from '@/core';
|
||||||
|
|
||||||
|
export class BotOfflineEvent extends OB11BaseNoticeEvent {
|
||||||
|
notice_type = 'bot_offline';
|
||||||
|
user_id: number;
|
||||||
|
tag: string = 'BotOfflineEvent';
|
||||||
|
message: string = 'BotOfflineEvent';
|
||||||
|
|
||||||
|
public constructor(core: NapCatCore, tag: string, message: string) {
|
||||||
|
super(core);
|
||||||
|
this.user_id = +core.selfInfo.uin;
|
||||||
|
this.tag = tag;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
@@ -47,6 +47,7 @@ import { LRUCache } from '@/common/lru-cache';
|
|||||||
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
|
||||||
import { Native } from '@/native';
|
import { Native } from '@/native';
|
||||||
import { decodeMessage, decodeRecallGroup } from '@/core/packet/proto/old/Message';
|
import { decodeMessage, decodeRecallGroup } from '@/core/packet/proto/old/Message';
|
||||||
|
import { BotOfflineEvent } from './event/notice/BotOfflineEvent';
|
||||||
|
|
||||||
//OneBot实现类
|
//OneBot实现类
|
||||||
export class NapCatOneBot11Adapter {
|
export class NapCatOneBot11Adapter {
|
||||||
@@ -343,7 +344,11 @@ export class NapCatOneBot11Adapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
msgListener.onKickedOffLine = async (kick) => {
|
||||||
|
let event = new BotOfflineEvent(this.core, kick.tipsTitle, kick.tipsDesc);
|
||||||
|
this.networkManager.emitEvent(event)
|
||||||
|
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理Bot掉线失败', e));
|
||||||
|
}
|
||||||
this.context.session.getMsgService().addKernelMsgListener(
|
this.context.session.getMsgService().addKernelMsgListener(
|
||||||
proxiedListenerOf(msgListener, this.context.logger),
|
proxiedListenerOf(msgListener, this.context.logger),
|
||||||
);
|
);
|
||||||
|
@@ -36,7 +36,12 @@ const cmdOptions = program.opts();
|
|||||||
// NapCat Shell App ES 入口文件
|
// NapCat Shell App ES 入口文件
|
||||||
export async function NCoreInitShell() {
|
export async function NCoreInitShell() {
|
||||||
console.log('NapCat Shell App Loading...');
|
console.log('NapCat Shell App Loading...');
|
||||||
|
process.on('uncaughtException', (err) => {
|
||||||
|
console.log('[NapCat] [Error] Unhandled Exception:', err.message);
|
||||||
|
});
|
||||||
|
process.on('unhandledRejection', (reason, promise) => {
|
||||||
|
console.log('[NapCat] [Error] unhandledRejection:', reason);
|
||||||
|
});
|
||||||
const pathWrapper = new NapCatPathWrapper();
|
const pathWrapper = new NapCatPathWrapper();
|
||||||
const logger = new LogWrapper(pathWrapper.logsPath);
|
const logger = new LogWrapper(pathWrapper.logsPath);
|
||||||
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
||||||
@@ -227,7 +232,7 @@ export async function NCoreInitShell() {
|
|||||||
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
logger.log(`可用于快速登录的 QQ:\n${historyLoginList
|
||||||
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
.map((u, index) => `${index + 1}. ${u.uin} ${u.nickName}`)
|
||||||
.join('\n')
|
.join('\n')
|
||||||
}`);
|
}`);
|
||||||
}
|
}
|
||||||
loginService.getQRCodePicture();
|
loginService.getQRCodePicture();
|
||||||
}
|
}
|
||||||
|
@@ -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("V3.6.7", "napcat-update-button", "secondary")
|
SettingButton("V3.6.15", "napcat-update-button", "secondary")
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
SettingList([
|
SettingList([
|
||||||
|
@@ -4,7 +4,7 @@ import { resolve } from 'path';
|
|||||||
import nodeResolve from '@rollup/plugin-node-resolve';
|
import nodeResolve from '@rollup/plugin-node-resolve';
|
||||||
import { builtinModules } from 'module';
|
import { builtinModules } from 'module';
|
||||||
//依赖排除
|
//依赖排除
|
||||||
const external = ['silk-wasm', 'ws', 'express', 'fluent-ffmpeg', 'log4js', 'qrcode-terminal'];
|
const external = ['silk-wasm', 'ws', 'express', 'fluent-ffmpeg', 'qrcode-terminal'];
|
||||||
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
|
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
|
||||||
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 };
|
||||||
|
Reference in New Issue
Block a user