mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6be6023236 | ||
![]() |
42cee0d018 | ||
![]() |
041f725748 | ||
![]() |
0594d61631 | ||
![]() |
15cae6b765 | ||
![]() |
b984116c35 | ||
![]() |
13bda6e3f4 | ||
![]() |
c0d18549d1 | ||
![]() |
3caff72fce | ||
![]() |
1313e9c3f4 | ||
![]() |
0848d5a39e | ||
![]() |
7660646059 | ||
![]() |
bcd90fc744 | ||
![]() |
638fc22d62 | ||
![]() |
c87d365b88 | ||
![]() |
aee9602f25 | ||
![]() |
976fbd0220 | ||
![]() |
afd955d06f | ||
![]() |
4d548da66b | ||
![]() |
41b70f53d1 | ||
![]() |
a47a618bcd | ||
![]() |
62170a30af | ||
![]() |
780c5ac23c | ||
![]() |
9fba519a5a | ||
![]() |
3cd0e7d26b | ||
![]() |
a8fd6af994 | ||
![]() |
4000b89644 | ||
![]() |
9c00bbc0b7 | ||
![]() |
a2989d3b38 | ||
![]() |
fc731b60d5 | ||
![]() |
193980dd4a | ||
![]() |
35427b0768 | ||
![]() |
73ea130e40 | ||
![]() |
5667e6aaee | ||
![]() |
fbd626131d | ||
![]() |
7b82444338 | ||
![]() |
8108b9f565 | ||
![]() |
c6ddd00cd9 |
@@ -4,16 +4,12 @@
|
||||
"name": "NapCatQQ",
|
||||
"slug": "NapCat.Framework",
|
||||
"description": "高性能的 OneBot 11 协议实现",
|
||||
"version": "4.2.50",
|
||||
"version": "4.2.63",
|
||||
"icon": "./logo.png",
|
||||
"authors": [
|
||||
{
|
||||
"name": "MliKiowa",
|
||||
"link": "https://github.com/MliKiowa"
|
||||
},
|
||||
{
|
||||
"name": "Young",
|
||||
"link": "https://github.com/Wesley-Young"
|
||||
"name": "NapNeko",
|
||||
"link": "https://github.com/NapNeko"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "4.2.50",
|
||||
"version": "4.2.63",
|
||||
"scripts": {
|
||||
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
|
||||
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
|
||||
@@ -37,7 +37,7 @@
|
||||
"@typescript-eslint/parser": "^8.3.0",
|
||||
"ajv": "^8.13.0",
|
||||
"async-mutex": "^0.5.0",
|
||||
"commander": "^12.1.0",
|
||||
"commander": "^13.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"eslint": "^9.14.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
|
@@ -1,18 +1,21 @@
|
||||
import https from 'node:https';
|
||||
import { napCatVersion } from './version';
|
||||
import os from 'os';
|
||||
import os from 'node:os';
|
||||
export class UmamiTraceCore {
|
||||
napcatVersion = napCatVersion;
|
||||
qqversion = '1.0.0';
|
||||
guid = 'default-user';
|
||||
heartbeatInterval: NodeJS.Timeout | null = null;
|
||||
website: string = '1fabb2b1-c3a3-4416-b1be-31e2cbdce978';
|
||||
website: string = '596cbbb2-1740-4373-a807-cf3d0637bfa7';
|
||||
referrer: string = 'https://trace.napneko.icu/';
|
||||
hostname: string = 'trace.napneko.icu';
|
||||
ua: string = '';
|
||||
|
||||
init(qqversion: string, guid: string) {
|
||||
workname: string = 'default';
|
||||
bootTime = Date.now();
|
||||
cache: string = '';
|
||||
init(qqversion: string, guid: string, workname: string) {
|
||||
this.qqversion = qqversion;
|
||||
this.workname = workname;
|
||||
let UaList = {
|
||||
'linux': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/124.0.0.0 Safari/537.36 PTST/240508.140043',
|
||||
'win32': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.2128.93 Safari/537.36',
|
||||
@@ -42,32 +45,49 @@ export class UmamiTraceCore {
|
||||
const data = {
|
||||
napcat_version: this.napcatVersion,
|
||||
qq_version: this.qqversion,
|
||||
guid: guid
|
||||
napcat_working: this.workname,
|
||||
device_guid: this.guid,
|
||||
device_platform: os.platform(),
|
||||
device_arch: os.arch(),
|
||||
boot_time: new Date(this.bootTime + 8 * 60 * 60 * 1000).toISOString().replace('T', ' ').substring(0, 19),
|
||||
sys_time: new Date(Date.now() - os.uptime() * 1000 + 8 * 60 * 60 * 1000).toISOString().replace('T', ' ').substring(0, 19)
|
||||
};
|
||||
this.sendRequest({ website: this.website, ...data }, 'identify');
|
||||
this.sendEvent(
|
||||
{
|
||||
website: this.website,
|
||||
hostname: this.hostname,
|
||||
referrer: this.referrer,
|
||||
tittle: 'NapCat ' + this.napcatVersion,
|
||||
url: `/${this.qqversion}/${this.napcatVersion}/${this.workname}/identify`,
|
||||
},
|
||||
data,
|
||||
'identify'
|
||||
);
|
||||
}
|
||||
|
||||
sendEvent(event: string, data?: object) {
|
||||
sendEvent(event: string | object, data?: object, type = 'event') {
|
||||
const env = process.env;
|
||||
const language = env.LANG || env.LANGUAGE || env.LC_ALL || env.LC_MESSAGES;
|
||||
const payload = {
|
||||
name: event,
|
||||
...(typeof event === 'string' ? { event } : event),
|
||||
hostname: this.hostname,
|
||||
referrer: this.referrer,
|
||||
website: this.website,
|
||||
language: language || 'es-US',
|
||||
napcat_version: this.napcatVersion,
|
||||
qq_version: this.qqversion,
|
||||
language: language || 'en-US',
|
||||
screen: '1920x1080',
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
};
|
||||
this.sendRequest(payload);
|
||||
this.sendRequest(payload, type);
|
||||
}
|
||||
|
||||
sendTrace(eventName: string) {
|
||||
sendTrace(eventName: string, data: string = '') {
|
||||
const payload = {
|
||||
website: this.website,
|
||||
hostname: this.hostname,
|
||||
title: 'NapCat ' + this.napcatVersion,
|
||||
url: `/${this.qqversion}/${this.napcatVersion}/${eventName}`,
|
||||
url: `/${this.qqversion}/${this.napcatVersion}/${this.workname}/${eventName}` + (!!data ? `/${data}` : ''),
|
||||
referrer: this.referrer,
|
||||
};
|
||||
this.sendRequest(payload);
|
||||
@@ -82,7 +102,8 @@ export class UmamiTraceCore {
|
||||
headers: {
|
||||
"Host": "umami.napneko.icu",
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": this.ua
|
||||
"User-Agent": this.ua,
|
||||
...(this.cache ? { 'x-umami-cache': this.cache } : {})
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,9 +112,11 @@ export class UmamiTraceCore {
|
||||
|
||||
});
|
||||
res.on('data', (data) => {
|
||||
|
||||
if (!this.cache) {
|
||||
this.cache = data.toString();
|
||||
}
|
||||
});
|
||||
});
|
||||
}).on('error', () => { });
|
||||
|
||||
request.write(JSON.stringify({ type, payload }));
|
||||
request.end();
|
||||
@@ -104,13 +127,10 @@ export class UmamiTraceCore {
|
||||
clearInterval(this.heartbeatInterval);
|
||||
}
|
||||
this.heartbeatInterval = setInterval(() => {
|
||||
this.sendEvent('heartbeat', {
|
||||
this.sendEvent({
|
||||
name: 'heartbeat',
|
||||
title: 'NapCat ' + this.napcatVersion,
|
||||
language: process.env.LANG || 'en-US',
|
||||
url: `/${this.qqversion}/${this.napcatVersion}/heartbeat`,
|
||||
version: this.napcatVersion,
|
||||
qq_version: this.qqversion,
|
||||
user_id: this.guid
|
||||
url: `/${this.qqversion}/${this.napcatVersion}/${this.workname}/heartbeat`,
|
||||
});
|
||||
}, 5 * 60 * 1000);
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
export const napCatVersion = '4.2.50';
|
||||
export const napCatVersion = '4.2.63';
|
||||
|
@@ -156,9 +156,9 @@ export class NapCatCore {
|
||||
|
||||
msgListener.onKickedOffLine = (Info: KickedOffLineInfo) => {
|
||||
if (this.context.workingEnv === NapCatCoreWorkingEnv.Framework) {
|
||||
UmamiTrace.sendEvent('framework/kickoff');
|
||||
UmamiTrace.sendTrace('event/kickoff');
|
||||
} else {
|
||||
UmamiTrace.sendEvent('shell/kickoff');
|
||||
UmamiTrace.sendTrace('event/kickoff');
|
||||
}
|
||||
// 下线通知
|
||||
this.context.logger.logError('[KickedOffLine] [' + Info.tipsTitle + '] ' + Info.tipsDesc);
|
||||
|
@@ -21,7 +21,7 @@ export class PacketOperationContext {
|
||||
}
|
||||
|
||||
async GroupPoke(groupUin: number, uin: number) {
|
||||
const req = trans.SendPoke.build(groupUin, uin);
|
||||
const req = trans.SendPoke.build(uin, groupUin);
|
||||
await this.context.client.sendOidbPacket(req);
|
||||
}
|
||||
|
||||
|
@@ -9,4 +9,5 @@ export * from './sign';
|
||||
export * from './element';
|
||||
export * from './constant';
|
||||
export * from './graytip';
|
||||
export * from './emoji';
|
||||
export * from './emoji';
|
||||
export * from './service';
|
35
src/core/types/service.ts
Normal file
35
src/core/types/service.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export enum LoginErrorCode {
|
||||
KLOGINERRORACCOUNTNOTUIN = 140022018,
|
||||
KLOGINERRORACCOUNTORPASSWORDERROR = 140022013,
|
||||
KLOGINERRORBLACKACCOUNT = 150022021,
|
||||
KLOGINERRORDEFAULT = 140022000,
|
||||
KLOGINERROREXPIRETICKET = 140022014,
|
||||
KLOGINERRORFROZEN = 140022005,
|
||||
KLOGINERRORILLAGETICKET = 140022016,
|
||||
KLOGINERRORINVAILDCOOKIE = 140022012,
|
||||
KLOGINERRORINVALIDPARAMETER = 140022001,
|
||||
KLOGINERRORKICKEDTICKET = 140022015,
|
||||
KLOGINERRORMUTIPLEPASSWORDINCORRECT = 150022029,
|
||||
KLOGINERRORNEEDUPDATE = 140022004,
|
||||
KLOGINERRORNEEDVERIFYREALNAME = 140022019,
|
||||
KLOGINERRORNEWDEVICE = 140022010,
|
||||
KLOGINERRORNICEACCOUNTEXPIRED = 150022020,
|
||||
KLOGINERRORNICEACCOUNTPARENTCHILDEXPIRED = 150022025,
|
||||
KLOGINERRORPASSWORD = 2,
|
||||
KLOGINERRORPROOFWATER = 140022008,
|
||||
KLOGINERRORPROTECT = 140022006,
|
||||
KLOGINERRORREFUSEPASSOWRDLOGIN = 140022009,
|
||||
KLOGINERRORREMINDCANAELLATEDSTATUS = 150022028,
|
||||
KLOGINERRORSCAN = 1,
|
||||
KLOGINERRORSCCESS = 0,
|
||||
KLOGINERRORSECBEAT = 140022017,
|
||||
KLOGINERRORSMSINVALID = 150022026,
|
||||
KLOGINERRORSTRICK = 140022007,
|
||||
KLOGINERRORSYSTEMFAILED = 140022002,
|
||||
KLOGINERRORTGTGTEXCHAGEA1FORBID = 150022027,
|
||||
KLOGINERRORTIMEOUTRETRY = 140022003,
|
||||
KLOGINERRORTOOMANYTIMESTODAY = 150022023,
|
||||
KLOGINERRORTOOOFTEN = 150022022,
|
||||
KLOGINERRORUNREGISTERED = 150022024,
|
||||
KLOGINERRORUNUSUALDEVICE = 140022011,
|
||||
}
|
@@ -26,7 +26,7 @@ export async function NCoreInitFramework(
|
||||
console.log('NapCat Framework App Loading...');
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
UmamiTrace.sendEvent('framework/error', { name: err.name });
|
||||
UmamiTrace.sendTrace('uncaught/error', err.message);
|
||||
console.log('[NapCat] [Error] Unhandled Exception:', err.message);
|
||||
});
|
||||
|
||||
@@ -39,9 +39,9 @@ export async function NCoreInitFramework(
|
||||
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
||||
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
||||
let guid = loginService.getMachineGuid();
|
||||
UmamiTrace.init(basicInfoWrapper.getFullQQVesion(), guid);
|
||||
UmamiTrace.sendTrace('framework/boot');
|
||||
UmamiTrace.sendEvent('framework/login');
|
||||
UmamiTrace.init(basicInfoWrapper.getFullQQVesion(), guid,'framework');
|
||||
UmamiTrace.sendTrace('boot/init');
|
||||
UmamiTrace.sendTrace('login/success');
|
||||
//直到登录成功后,执行下一步
|
||||
const selfInfo = await new Promise<SelfInfo>((resolveSelfInfo) => {
|
||||
const loginListener = new NodeIKernelLoginListener();
|
||||
|
@@ -17,7 +17,7 @@ class SetGroupSignBase extends GetPacketStatusDepends<Payload, any> {
|
||||
}
|
||||
|
||||
export class SetGroupSign extends SetGroupSignBase {
|
||||
actionName = ActionName.SendGroupSign;
|
||||
actionName = ActionName.SetGroupSign;
|
||||
}
|
||||
|
||||
export class SendGroupSign extends SetGroupSignBase {
|
||||
|
@@ -14,6 +14,6 @@ export class GroupPoke extends GetPacketStatusDepends<Payload, any> {
|
||||
payloadSchema = SchemaData;
|
||||
|
||||
async _handle(payload: Payload) {
|
||||
await this.core.apis.PacketApi.pkt.operation.GroupPoke(+payload.user_id, +payload.group_id);
|
||||
await this.core.apis.PacketApi.pkt.operation.GroupPoke(+payload.group_id, +payload.user_id);
|
||||
}
|
||||
}
|
||||
|
@@ -15,9 +15,9 @@ export class SendPoke extends GetPacketStatusDepends<Payload, any> {
|
||||
|
||||
async _handle(payload: Payload) {
|
||||
if (payload.group_id) {
|
||||
this.core.apis.PacketApi.pkt.operation.GroupPoke(+payload.group_id, +payload.user_id);
|
||||
await this.core.apis.PacketApi.pkt.operation.GroupPoke(+payload.group_id, +payload.user_id);
|
||||
} else {
|
||||
this.core.apis.PacketApi.pkt.operation.FriendPoke(+payload.user_id);
|
||||
await this.core.apis.PacketApi.pkt.operation.FriendPoke(+payload.user_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ import { UmamiTrace } from '@/common/umami';
|
||||
// NapCat Shell App ES 入口文件
|
||||
async function handleUncaughtExceptions(logger: LogWrapper) {
|
||||
process.on('uncaughtException', (err) => {
|
||||
UmamiTrace.sendEvent('framework/error', { name: err.name, message: err.message });
|
||||
UmamiTrace.sendTrace('uncaught/error', err.message);
|
||||
logger.logError('[NapCat] [Error] Unhandled Exception:', err.message);
|
||||
});
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
@@ -153,9 +153,9 @@ async function handleLogin(
|
||||
};
|
||||
|
||||
loginListener.onQRCodeSessionFailed = (errType: number, errCode: number, errMsg: string) => {
|
||||
UmamiTrace.sendEvent('shell/qrlogin/error', { errType, errCode, errMsg });
|
||||
UmamiTrace.sendTrace('qrlogin/error', [errType, errCode, errMsg].toString());
|
||||
if (!isLogined) {
|
||||
logger.logError('[Core] [Login] Login Error,ErrCode: ', errCode, ' ErrMsg:', errMsg);
|
||||
logger.logError('[Core] [Login] Login Error,ErrType: ', errType, ' ErrCode:', errCode);
|
||||
if (errType == 1 && errCode == 3) {
|
||||
// 二维码过期刷新
|
||||
}
|
||||
@@ -163,9 +163,9 @@ async function handleLogin(
|
||||
}
|
||||
};
|
||||
|
||||
loginListener.onLoginFailed = (args) => {
|
||||
UmamiTrace.sendEvent('shell/login/error', { args });
|
||||
logger.logError('[Core] [Login] Login Error , ErrInfo: ', args.toString());
|
||||
loginListener.onLoginFailed = (...args) => {
|
||||
UmamiTrace.sendTrace('login/error', args.toString());
|
||||
logger.logError('[Core] [Login] Login Error , ErrInfo: ', JSON.stringify(args));
|
||||
};
|
||||
|
||||
loginService.addKernelLoginListener(proxiedListenerOf(loginListener, logger));
|
||||
@@ -298,10 +298,10 @@ export async function NCoreInitShell() {
|
||||
|
||||
const dataTimestape = new Date().getTime().toString();
|
||||
o3Service.reportAmgomWeather('login', 'a1', [dataTimestape, '0', '0']);
|
||||
UmamiTrace.init(basicInfoWrapper.getFullQQVesion(), loginService.getMachineGuid());
|
||||
UmamiTrace.sendTrace('shell/boot');
|
||||
UmamiTrace.init(basicInfoWrapper.getFullQQVesion(), loginService.getMachineGuid(), 'shell');
|
||||
UmamiTrace.sendTrace('boot/init');
|
||||
const selfInfo = await handleLogin(loginService, logger, pathWrapper, quickLoginUin, historyLoginList);
|
||||
UmamiTrace.sendEvent('shell/login');
|
||||
UmamiTrace.sendTrace('login/success');
|
||||
const amgomDataPiece = 'eb1fd6ac257461580dc7438eb099f23aae04ca679f4d88f53072dc56e3bb1129';
|
||||
o3Service.setAmgomDataPiece(basicInfoWrapper.QQVersionAppid, new Uint8Array(Buffer.from(amgomDataPiece, 'hex')));
|
||||
|
||||
|
@@ -90,7 +90,7 @@ export class WebUiConfigWrapper {
|
||||
try {
|
||||
const configPath = resolve(webUiPathWrapper.configPath, './webui.json');
|
||||
|
||||
if (!await fs.access(configPath, constants.R_OK).then(() => true).catch(() => false)) {
|
||||
if (!await fs.access(configPath, constants.F_OK).then(() => true).catch(() => false)) {
|
||||
await fs.writeFile(configPath, JSON.stringify(defaultconfig, null, 4));
|
||||
}
|
||||
|
||||
@@ -101,7 +101,12 @@ export class WebUiConfigWrapper {
|
||||
if (!parsedConfig.prefix.startsWith('/')) parsedConfig.prefix = '/' + parsedConfig.prefix;
|
||||
if (parsedConfig.prefix.endsWith('/')) parsedConfig.prefix = parsedConfig.prefix.slice(0, -1);
|
||||
// 配置已经被操作过了,还是回写一下吧,不然新配置不会出现在配置文件里
|
||||
await fs.writeFile(configPath, JSON.stringify(parsedConfig, null, 4));
|
||||
if (await fs.access(configPath, constants.W_OK).then(() => true).catch(() => false)) {
|
||||
await fs.writeFile(configPath, JSON.stringify(parsedConfig, null, 4));
|
||||
}
|
||||
else {
|
||||
console.warn(`文件: ${configPath} 没有写入权限, 配置的更改部分可能会在重启后还原.`);
|
||||
}
|
||||
// 不希望回写的配置放后面
|
||||
|
||||
// 查询主机地址是否可用
|
||||
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"target": "ES2021",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": [
|
||||
"ES2020",
|
||||
"ES2021",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
|
Reference in New Issue
Block a user