Skip to content

Commit

Permalink
重制app类
Browse files Browse the repository at this point in the history
  • Loading branch information
Lhcfl committed Sep 3, 2023
1 parent 4f8967a commit 020435a
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 117 deletions.
5 changes: 4 additions & 1 deletion config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ bot_sysadmin_id:
bot_name: "琳酱"

# TG风格: "/" QQ风格: "."
command_style: "/"
command_style: "/"

# 轮询超时消息不处理时间(秒)
outdate_seconds: 300
116 changes: 10 additions & 106 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,120 +1,24 @@
// 读取配置和模块
import fs from 'fs';
// import Promise from 'promise';
import yaml from 'js-yaml';
// import readline from 'readline'
import std from './lib/std.js';
import fatalError from './lib/fatal_error.js';
import db from './lib/db.js';
import {
botOnOff,
commandParser,
getCommands,
getGlobalMessageHandles,
getReplyHandles,
registCommand,
registGlobalMessageHandle,
registReplyHandle
} from './lib/command.js';
import { App } from './types/app.js';
import { YamlConfig } from './types/config.js';
import { exit } from 'process';
import TelegramBot, { BotCommand } from 'node-telegram-bot-api';
import { CreateBot } from './types/bridge.js';
import { reverseReadFileIfExists } from './util/fs.js';
} from '@/lib/command.js';
import { BotCommand } from 'node-telegram-bot-api';
import { Application } from '@/lib/app.js';

// 创建app
const app: App = {
db,
std,
registCommand,
registGlobalMessageHandle,
registReplyHandle,

_config: undefined,

get config(): YamlConfig {
if (this._config) {
return this._config;
} else {
throw '未找到config';
}
},
get bot(): TelegramBot {
if (this._bot) {
return this._bot;
} else {
throw '无bot被初始化';
}
},


get version() {
return JSON.parse(fs.readFileSync('package.json', { encoding: 'utf-8' })).version;
},
get configExample() {
return fs.readFileSync('config.example.yml', { encoding: 'utf-8' }).toString();
},

async initConfig() {
// 读取配置文件
const configContent = reverseReadFileIfExists('config.yml');
if (!configContent) {
await std.questionSync(
'未找到配置文件。是否使用默认配置文件config.examle.yml覆盖config.yml (yes)',
(answer) => {
if (answer === 'yes') {
try {
app.setConfig(app.configExample);
console.log('写入完成,本程序自动退出。');
} catch (err) {
fatalError(err, '写入配置文件失败。');
process.exit(-1);
}
} else {
console.log('请正确配置config.yml. 本程序将自动退出.');
}
process.exit(0);
});
return;
}
this._config = yaml.load(configContent) as YamlConfig;
},
writeConfig(config_data: string) {
fs.writeFileSync('./config.yml', config_data);
},
};

if (process.argv[2] === '--version') {
console.log(`Linquebot ${app.version}`);
console.log('本程序具有超级琳力');
process.exit(0);
}

// 初始化配置
await app.initConfig();

console.log(app.config);
console.log('---------------');

if (!app.config) { exit(-1); }

// 创建bot
if (app.config.platform.settings[app.config.platform.enabled] === undefined) {
console.log(`未找到${app.config.platform.enabled}的配置,请检查config.yml`);
exit(-1);
}
console.log(`Laauching bot at Platform[${app.config.platform.enabled}]...`);
const createBot = (await import(`./bridges/${app.config.platform.enabled}/index.js`)).createBot as CreateBot;

app._bot = createBot(app.config.platform.settings[app.config.platform.enabled]);

if (!app._bot) {
console.log('bot创建失败,请检查bridge是否正确。');
exit(-1);
}
/** 创建app */
const app = new Application();
/** 初始化app */
await app.init();

app.bot.on('message', (msg) => {
if (Number(new Date)/1000 - msg.date > app.config.outdate_seconds) {
console.log('古老消息被忽略。详见 config.outdate_seconds');
}
console.log(msg);
commandParser(app, msg);
if (botOnOff(app, msg)) {
Expand Down
146 changes: 146 additions & 0 deletions src/lib/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// 读取配置和模块
import fs from 'fs';
// import Promise from 'promise';
import yaml from 'js-yaml';
// import readline from 'readline'
import std from '@/lib/std.js';
import fatalError from '@/lib/fatal_error.js';
import db from '@/lib/db.js';
import {
registCommand,
registGlobalMessageHandle,
registReplyHandle
} from '@/lib/command.js';
import { App } from '@/types/app.js';
import { YamlConfig } from '@/types/config.js';
import process from 'process';
import TelegramBot from 'node-telegram-bot-api';
import { CreateBot } from '@/types/bridge.js';
import { reverseReadFileIfExists } from '@/util/fs.js';
import chalk from 'chalk';

/**
* `@/types/app.ts` 的 App 实现
*/
export class Application implements App {
private _bot?: TelegramBot;
private _config?: YamlConfig;
private _configExample: string;
private _version: string;

constructor() {
const packageJSON = reverseReadFileIfExists('package.json');
if (packageJSON) {
this._version = JSON.parse(packageJSON).version;
} else {
throw 'no version found';
}
try {
this._configExample = reverseReadFileIfExists('config.example.yml') || '';
if (!this._configExample) {
throw 'no config example found';
}
} catch(err) {
this._configExample = '';
console.warn(chalk.yellow('No config.example.yml found. This program will not be able to provide a config example.'));
}
}

async init(): Promise<void> {
console.log('Reading config.yml ...');
await this.initConfig();
console.log(this.config);
console.log('---------------');
console.log('Initializing bot ...');
if (this.config.platform.settings[this.config.platform.enabled] === undefined) {
console.log(`未找到平台${this.config.platform.enabled}的配置,请检查config.yml`);
process.exit(-1);
}
console.log(`Launching bot at Platform[${this.config.platform.enabled}]...`);

const createBot = (await import(`../bridges/${this.config.platform.enabled}/index.js`)).createBot as CreateBot;

try {
this._bot = createBot(this.config.platform.settings[this.config.platform.enabled]);
if (!this._bot) {
throw 'bot is undefined';
}
} catch (err) {
console.log(`-------${chalk.red('[ERROR]')}--------`);
console.log('Launching bot failed. Please check the error information below:');
console.error(err);
process.exit(-1);
}
console.log('---------------');
}

get config(): YamlConfig {
if (this._config) {
return this._config;
} else {
throw '未找到config';
}
}

get bot(): TelegramBot {
if (this._bot) {
return this._bot;
} else {
throw '无bot被初始化';
}
}

get db() {
return db;
}

get std() {
return std;
}

get version(): string {
return this._version;
}
get configExample() {
return this._configExample;
}

private async initConfig() {
// 读取配置文件
const configContent = reverseReadFileIfExists('config.yml');
if (!configContent) {
await std.questionSync(
'未找到配置文件。是否使用默认配置文件config.examle.yml覆盖config.yml (yes)',
(answer) => {
if (answer === 'yes') {
try {
this.writeConfig(this.configExample);
console.log('写入完成,本程序自动退出。');
} catch (err) {
fatalError(err, '写入配置文件失败。');
process.exit(-1);
}
} else {
console.log('请正确配置config.yml. 本程序将自动退出.');
}
process.exit(0);
});
return;
}
this._config = yaml.load(configContent) as YamlConfig;
};

private writeConfig(config_data: string) {
fs.writeFileSync('./config.yml', config_data);
};

get registCommand() {
return registCommand;
};
get registGlobalMessageHandle() {
return registGlobalMessageHandle;
}
get registReplyHandle() {
return registReplyHandle;
}
}
32 changes: 26 additions & 6 deletions src/types/app.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import TelegramBot from 'node-telegram-bot-api';
import { YamlConfig } from './config.js';
import { registCommand, registGlobalMessageHandle, registReplyHandle } from '@/lib/command.js';
import { Std } from '@/lib/std.js';

export interface App {
/** @hidden */
_config?: YamlConfig;
/** @hidden */
_bot?: TelegramBot;
/**
* 用户在 config.yml 的配置
*/
Expand All @@ -15,11 +12,34 @@ export interface App {
* Telegram bot
*/
get bot(): TelegramBot;
/**
* 初始化app。只应执行一次。
*/
init(): Promise<void>;
/**
* 数据库获取
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
get db(): any;

/**
* 获得标准输入输出交互器
*/
get std(): Std;

/**
* 获取版本号
*/
get version(): string;

/**
* 获取配置示例
*/
get configExample(): string;

registCommand: typeof registCommand;
registGlobalMessageHandle: typeof registGlobalMessageHandle;
registReplyHandle: typeof registReplyHandle;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
// [key: string]: any;
}
4 changes: 4 additions & 0 deletions src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export interface YamlConfig {
* TG风格: "/" QQ风格: "."
*/
command_style: '/' | '.';
/**
* 由于一场关机导致轮询时爬取古老消息,记作超时不处理的消息最短时间(秒)
*/
outdate_seconds: number;
}

export interface TelegramPlatform {
Expand Down
21 changes: 17 additions & 4 deletions src/util/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import fs from 'fs';

/**
* 读取文件,如果文件不存在则返回null
* Default use { encoding: 'utf-8' } as `options`
* @param fileName filename or file descriptor
* @param options If the encoding option is specified then this function returns a string. Otherwise it returns a buffer.
*/
export const readFileIfExists = (fileName: string) => {
export const readFileIfExists = (
fileName: string,
options: { encoding: BufferEncoding; flag?: string | undefined; } | undefined = { encoding: 'utf-8' }
) => {
const fileExist = fs.existsSync(fileName);
if (!fileExist) {return null;}
return fs.readFileSync(fileName, { encoding: 'utf-8' });
return fs.readFileSync(fileName, options);
};

const defaultDirs = [
Expand All @@ -18,10 +24,17 @@ const defaultDirs = [

/**
* 从里到外读取文件,如果文件不存在则返回null
* Default use { encoding: 'utf-8' } as `options`
* @param fileName filename or file descriptor
* @param options If the encoding option is specified then this function returns a string. Otherwise it returns a buffer.
*/
export const reverseReadFileIfExists = (fileName: string, reverseDirs: string[] = defaultDirs) => {
export const reverseReadFileIfExists = (
fileName: string,
reverseDirs: string[] = defaultDirs,
options: { encoding: BufferEncoding; flag?: string | undefined; } | undefined = { encoding: 'utf-8' }
) => {
for (const dir of reverseDirs) {
const fileContent = readFileIfExists(dir + fileName);
const fileContent = readFileIfExists(dir + fileName, options);
if (fileContent !== null) {return fileContent;}
}
return null;
Expand Down

0 comments on commit 020435a

Please sign in to comment.