NapCatQQ/src/test/index.ts
2024-04-15 00:09:08 +08:00

208 lines
6.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import path from 'node:path';
import fs from 'node:fs';
import * as log4js from 'log4js';
import * as YAML from 'yaml';
import qrcode from 'qrcode-terminal';
import { NapCatCore, napCatCore } from '@/core';
import { NapCatOnebot11 } from '@/onebot11/main';
import PackageInfo from '@/../package.json';
import { INapCatConfig } from './types';
import { RawMessage } from '@/core/qqnt/entities';
const DefaultNapCatConfig: INapCatConfig = {
account: {
uin: '10086',
password: 'password',
noQuickLogin: false,
},
heartbeat: {
interval: 5,
},
adapters: {
onebot: {
address: '0.0.0.0',
port: 8123,
accessToken: 'token123456',
}
},
log: {
level: 'info',
},
};
function getLog4jConfig(logLevel = 'info', writeFile = false): log4js.Configuration {
const outputMethod = [ 'console' ];
if (writeFile) outputMethod.push('file');
const defaultCategory = {
appenders: outputMethod,
level: logLevel,
};
return {
appenders: {
console: {
type: 'stdout'
},
file: {
type: 'file',
},
ascii: {
type: 'stdout',
layout: {
type: 'pattern',
pattern: '%[%m%]',
},
},
asciiNoColor: {
type: 'stdout',
layout: {
type: 'pattern',
pattern: '%m',
},
},
},
categories: {
default: defaultCategory,
ascii: {
appenders: [ 'ascii' ],
level: 'info',
},
asciiNoColor: {
appenders: [ 'asciiNoColor' ],
level: 'info',
}
},
};
}
export class NapCat {
readonly dataPath: string;
readonly config: INapCatConfig;
readonly core: NapCatCore;
readonly onebot: NapCatOnebot11;
readonly log: log4js.Logger;
readonly logMsg: log4js.Logger;
constructor() {
// Get data path (usually the same path of NapCat)
this.dataPath = path.resolve(__dirname, './');
// Init core
this.core = napCatCore;
this.onebot = new NapCatOnebot11();
// Get user config
if (!fs.existsSync(path.resolve(this.dataPath, './config.yml'))) { // Detect if no config file exist
// Use default logger
log4js.configure(getLog4jConfig('all'));
this.log = log4js.getLogger('App');
this.logMsg = log4js.getLogger('Message');
this.drawBootAscii();
this.config = DefaultNapCatConfig;
fs.writeFileSync(path.resolve(this.dataPath, './config.yml'), YAML.stringify(DefaultNapCatConfig));
this.log.error('未找到配置文件!');
this.log.error('已为您创建了默认配置文件,请关闭 NapCatQQ 后填写配置文件再启动');
this.log.error('完整的配置文件详解可前往 [DOC_URL] 查看');
return;
}
this.config = YAML.parse(fs.readFileSync(path.resolve(this.dataPath, './config.yml'), { encoding: 'utf8' }));
// Apply log4j config before use it
log4js.configure(getLog4jConfig('all'));
// log4js.configure(getLog4jConfig(this.config.log.level));
this.log = log4js.getLogger('App');
this.logMsg = log4js.getLogger('Message');
this.drawBootAscii();
// Init app
this.initApp();
}
// Output ASCII because i love it
private drawBootAscii() {
const logAscii = log4js.getLogger('ascii');
[
'',
' _ _ _____ _ ____ ____',
' | \\ | | / ____| | | / __ \\ / __ \\',
' | \\| | __ _ _ __ | | __ _ | |_ | | | || | | |',
' | . ` | / _` || \'_ \\ | | / _` || __|| | | || | | |',
' | |\\ || (_| || |_) || |____ | (_| || |_ | |__| || |__| |',
' |_| \\_| \\__,_|| .__/ \\_____| \\__,_| \\__| \\___\\_\\ \\___\\_\\',
' | |',
' |_| ',
].forEach(i => {
logAscii.info(i);
});
logAscii.info(`---------------------< NapCatQQ v${PackageInfo.version} >---------------------`);
}
private initApp() {
this.core.on('system.login.qrcode', ({ url }: { url: string }) => {
this.log.info('请扫描下面的二维码然后在手Q上授权登录');
const ascii = log4js.getLogger('asciiNoColor');
qrcode.generate(url, { small: true }, (res) => {
ascii.info(res);
});
});
this.core.on('system.login.slider', ({ url }: { url: string }) => {
this.log.info('登录需要验证,请访问下面的滑块验证链接,然后按下回车:');
const ascii = log4js.getLogger('asciiNoColor');
ascii.info(url);
});
this.core.on('system.online', () => {
this.onLoginSuccess();
});
this.core.on('system.login.error', ({ code, message }: { code: string, message: string }) => {
this.log.error(`登录出现问题(${code}`);
this.log.error(message);
});
if (!this.config.account || !this.config.account.uin) {
this.log.info('未读取到账号配置,终止初始化...');
return;
}
this.log.info(`正在尝试登录账号 ${this.config.account.uin} ...`);
if (this.config.account.password) this.core.login.password(this.config.account.uin, this.config.account.password);
else if (!this.config.account.noQuickLogin) this.core.login.quick(this.config.account.uin);
else this.core.login.qrcode();
}
private onLoginSuccess() {
this.log.info('登录成功');
this.core.on('message.private', (e) => {
this.logMsg.info(`[Private] ${e.peerName}(${e.senderUin}) -> ${msgElementParser(e)}`);
});
this.core.on('message.group', (e) => {
this.logMsg.info(`[Group] ${e.peerName}(${e.peerUin}) - ${e.sendMemberName ? e.sendMemberName : e.sendNickName}(${e.senderUin}) -> ${msgElementParser(e)}`);
});
}
}
const msgElementParser = (msg: RawMessage) => {
let result = '';
for (const element of msg.elements) {
if (element.textElement) {
if (element.textElement.atType === 0) result += element.textElement.content;
else result += `[@${element.textElement.atType === 2 ? element.textElement.atUid : 'all'}]`;
}
if (element.picElement) result += `[Pic=${element.picElement.fileName}]`;
if (element.pttElement) result += '[Voice]';
if (element.faceElement) result += `[Face=${element.faceElement.faceIndex}]`;
if (element.videoElement) result += `[Video=${element.videoElement.fileName}]`;
if (element.fileElement) result += `[File=${element.fileElement.fileName}]`;
if (element.marketFaceElement) result += `[MarketFace=${element.marketFaceElement.faceName}]`;
}
return result;
};