Skip to content

Commit

Permalink
fix: 移除内置数据库
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-cn committed Jul 6, 2024
1 parent 8a5ee26 commit 9d26ac5
Show file tree
Hide file tree
Showing 18 changed files with 145 additions and 94 deletions.
1 change: 0 additions & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"axios": "^1.6.1",
"jiti": "^1.21.0",
"log4js": "^6.9.1",
"level": "^8.0.1",
"tsconfig-paths": "^4.2.0",
"yaml": "^2.4.5"
},
Expand Down
23 changes: 6 additions & 17 deletions core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { Adapter, AdapterBot, AdapterReceive } from './adapter';
import { Message } from './message';
import process from 'process';
import { Config } from './config';
import { LevelDb } from './levelDb';

export function defineConfig(config: Partial<App.Config>): Partial<App.Config>;
export function defineConfig(
Expand All @@ -25,7 +24,6 @@ export function defineConfig(
export class App extends EventEmitter {
logger: Logger = getLogger(`[zhin]`);
config: Config;
#db: LevelDb;
adapters: Map<string, Adapter> = new Map<string, Adapter>();
middlewares: Middleware[] = [];
plugins: PluginMap = new PluginMap();
Expand All @@ -35,10 +33,6 @@ export class App extends EventEmitter {
this.handleMessage = this.handleMessage.bind(this);
this.on('message', this.handleMessage);
this.config = new Config(process.env.ZHIN_CONFIG || 'zhin.config', App.defaultConfig);
this.#db = new LevelDb(path.join(WORK_DIR, 'zhin.db'), {
valueEncoding: 'json',
createIfMissing: true,
});
this.logger.level = this.config.log_level;
return new Proxy(this, {
get(target: App, key) {
Expand Down Expand Up @@ -100,17 +94,14 @@ export class App extends EventEmitter {
return this.pluginList.flatMap(plugin => plugin.commandList);
}

get services() {
let result: App.Services = {
jsondb: this.#db,
};
this.pluginList.forEach(plugin => {
get services(): App.Services {
return this.pluginList.reduce((result, plugin) => {
plugin.services.forEach((service, name) => {
if (Reflect.ownKeys(result).includes(name)) return;
if (Reflect.has(result, name)) return;
Reflect.set(result, name, service);
});
});
return result;
return result;
}, {});
}

findCommand(name: string) {
Expand Down Expand Up @@ -464,9 +455,7 @@ export namespace App {
};
}

export interface Services {
jsondb: LevelDb;
}
export interface Services {}

export type BotConfig<T extends keyof Adapters = keyof Adapters> = {
adapter: T | string;
Expand Down
19 changes: 13 additions & 6 deletions core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ export class Config {
public static exts: string[] = ['.json', '.yaml', '.yml'];
filename: string = '';
#type: Config.Type = Config.Type.YAML;
#data: App.Config;
private _data: App.Config;
get data() {
return this._data;
}
constructor(name: string, defaultValue?: App.Config) {
try {
this.filename = this.#resolveByName(name);
Expand All @@ -17,8 +20,8 @@ export class Config {
if (!Config.exts.includes(ext)) this.filename = path.join(WORK_DIR, `${name}${this.#resolveExt()}`);
this.#saveConfig(defaultValue);
}
this.#data = this.#loadConfig();
return new Proxy<App.Config>(this.#data, {
this._data = this.#loadConfig();
return new Proxy<App.Config>(this._data, {
get: (target, p, receiver) => {
if (Reflect.has(this, p)) return Reflect.get(this, p, receiver);
return this.#proxied(target, p, receiver);
Expand Down Expand Up @@ -75,7 +78,7 @@ export class Config {
throw new Error(`不支持的配置文件类型${this.#type}`);
}
}
#saveConfig(data: App.Config = this.#data) {
#saveConfig(data: App.Config = this._data) {
switch (this.#type) {
case Config.Type.JSON:
return fs.writeFileSync(this.filename, JSON.stringify(data, null, 2));
Expand All @@ -85,13 +88,17 @@ export class Config {
throw new Error(`不支持的配置文件类型${this.#type}`);
}
}
#replaceEnv<T>(data: T): T {
if (typeof data !== 'string') return data;
return data.replace(/\${([^}]+)}/g, (_, key) => process.env[key] || '') as T;
}
#proxied<T extends object, R = any>(obj: T, p: string | symbol, receiver: any): R {
const result = Reflect.get(obj, p, receiver);
if (!result || typeof result !== 'object') return result as R;
if (!result || typeof result !== 'object') return this.#replaceEnv(result as R);
return new Proxy(result, {
get: (target, p, receiver) => {
const result = Reflect.get(target, p, receiver);
if (typeof result !== 'object') return result;
if (typeof result !== 'object') return this.#replaceEnv(result);
return this.#proxied(target, p, receiver);
},
set: (target, p, value, receiver) => {
Expand Down
8 changes: 7 additions & 1 deletion core/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import { Dict } from './types';
import path from 'path';
import { Adapter } from './adapter';
import * as fs from 'fs';
import { getLogger, Logger } from 'log4js';

export interface Plugin extends Plugin.Options {}

export class Plugin extends EventEmitter {
public id: string;
public name: string = '';
private _logger?: Logger;
disposes: Function[] = [];
priority: number;
isMounted: boolean = false;
Expand Down Expand Up @@ -93,7 +95,11 @@ export class Plugin extends EventEmitter {
},
});
}

get logger() {
const logger = (this._logger ||= getLogger(`[zhin:${this.display_name}]`));
logger.level = this.app?.config.log_level || 'info';
return logger;
}
required<T extends keyof App.Services>(...services: (keyof App.Services)[]) {
this[REQUIRED_KEY].push(...services);
}
Expand Down
24 changes: 12 additions & 12 deletions packages/plugins/groupManage/src/banRepeat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ export default (plugin: Plugin) => {
plugin.command('禁止复读').action(async ({ bot, message }) => {
if (message.message_type !== 'group') return '请在群聊中使用';
const curChannel = `${bot.unique_id}:${message.from_id}`;
const isOpen = await plugin.jsondb.find<string[]>('banRepeat', channel => {
const isOpen = await plugin.database.find<string[]>('banRepeat', channel => {
return channel === curChannel;
});
if (isOpen) return segment.text('重复操作');
await plugin.jsondb.push<string>('banRepeat', curChannel);
await plugin.database.push<string>('banRepeat', curChannel);
return `当前群聊已禁止复读,请勿复读消息`;
});
plugin.command('允许复读').action(async ({ bot, message }) => {
if (message.message_type !== 'group') return '请在群聊中使用';
const curChannel = `${bot.unique_id}:${message.from_id}`;
const isOpen = await plugin.jsondb.find<string[]>('banRepeat', channel => {
const isOpen = await plugin.database.find<string[]>('banRepeat', channel => {
return channel === curChannel;
});
if (!isOpen) return segment.text('当前群聊尚未禁止复读,无需操作');
await plugin.jsondb.remove<string>('banRepeat', curChannel);
await plugin.database.remove<string>('banRepeat', curChannel);
return `当前群聊已允许复读,别刷屏哦`;
});

Expand All @@ -43,36 +43,36 @@ export default (plugin: Plugin) => {
sender: { user_id },
} = event;
const curChannel = `${bot.unique_id}:${event.from_id}`;
const isOpen = await plugin.jsondb.find<string[]>('banRepeat', channel => {
const isOpen = await plugin.database.find<string[]>('banRepeat', channel => {
return channel === curChannel;
});
if (!isOpen) return;
const repeatInfo = await plugin.jsondb.find<RepeatInfo[]>('group_repeat_infos', info => {
const repeatInfo = await plugin.database.find<RepeatInfo[]>('group_repeat_infos', info => {
return info.unique_id === bot.unique_id && info.group_id === from_id;
});
if (!repeatInfo)
return plugin.jsondb.push<RepeatInfo>('group_repeat_infos', {
return plugin.database.push<RepeatInfo>('group_repeat_infos', {
unique_id: bot.unique_id,
group_id: from_id,
last_text: raw_message,
repeat_count: 0,
});
if (repeatInfo.last_text !== raw_message)
return plugin.jsondb.replace('group_repeat_infos', repeatInfo, {
return plugin.database.replace('group_repeat_infos', repeatInfo, {
...repeatInfo,
last_text: raw_message,
repeat_count: 0,
});
await plugin.jsondb.replace<RepeatInfo>('group_repeat_infos', repeatInfo, {
await plugin.database.replace<RepeatInfo>('group_repeat_infos', repeatInfo, {
...repeatInfo,
repeat_count: repeatInfo.repeat_count + 1,
});
if (repeatInfo.repeat_count <= 2) return;
let banInfo = await plugin.jsondb.find<BanInfo[]>('group_ban_infos', info => {
let banInfo = await plugin.database.find<BanInfo[]>('group_ban_infos', info => {
return info.unique_id === bot.unique_id && info.group_id === from_id && info.user_id === user_id;
});
if (!banInfo)
await plugin.jsondb.push<BanInfo>(
await plugin.database.push<BanInfo>(
'group_ban_infos',
(banInfo = {
unique_id: bot.unique_id,
Expand All @@ -82,7 +82,7 @@ export default (plugin: Plugin) => {
}),
);
await bot.setGroupBan(from_id, user_id + '', 30 + banInfo.ban_count * 10);
await plugin.jsondb.replace('group_ban_infos', banInfo, {
await plugin.database.replace('group_ban_infos', banInfo, {
...banInfo,
ban_count: banInfo.ban_count + 1,
});
Expand Down
19 changes: 10 additions & 9 deletions packages/plugins/qa/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const fixWeight = (list: QAInfo[]) => {
});
};
const getMatchedQuestion = async (message: Message): Promise<undefined | QAInfo> => {
const dataList = await qaPlugin.jsondb.filter<QAInfo[]>('qa', qa => {
const dataList = await qaPlugin.database.filter<QAInfo[]>('qa', qa => {
if (!qa.adapter || qa.adapter === '*') return true;
return qa.adapter.includes(message.adapter.name);
});
Expand Down Expand Up @@ -70,6 +70,7 @@ const getAnswer = async (message: Message): Promise<undefined | QAInfo> => {
return getAnswer(message);
};
const qaPlugin = new Plugin('问答管理');
qaPlugin.required('database');
const qaCommand = qaPlugin
.command('问答 <question:string> <answer:string>')
.desc('添加问答')
Expand All @@ -80,15 +81,15 @@ const qaCommand = qaPlugin
.option('-s <scope:string> 作用域(private,group,direct,guild),默认所有', 'private,group,direct,guild')
.option('-p <weight:number> 权重', 1)
.action(async ({ message, adapter, prompt, options }, content, answer) => {
const existQa = await qaPlugin.jsondb.find<QAInfo[]>('qa', q => {
const existQa = await qaPlugin.database.find<QAInfo[]>('qa', q => {
return q.content === content;
});
if (existQa) {
const confirmUpdate = await prompt.confirm('该问题已存在,是否继续添加?');
if (!confirmUpdate) return '已取消';
}

await qaPlugin.jsondb.push<QAInfo>('qa', {
await qaPlugin.database.push<QAInfo>('qa', {
content,
adapter: options.adapter,
bot: options.bot,
Expand All @@ -109,7 +110,7 @@ qaCommand
.action(async ({ adapter, bot, prompt, message, options }) => {
const pageSize = 10;
const qaList = (
await qaPlugin.jsondb.filter<QAInfo[]>('qa', (qa, index) => {
await qaPlugin.database.filter<QAInfo[]>('qa', (qa, index) => {
return options.full || qa.scope.includes(message.message_type);
})
).filter((_, index) => {
Expand All @@ -135,13 +136,13 @@ qaCommand
.option('-s [scope:string] 作用域(private,group,direct,guild)')
.option('-p [weight:number] 权重')
.action(async ({ message, adapter, options }, no, content, answer) => {
const existQa = await qaPlugin.jsondb.find<QAInfo[]>('qa', (_, i) => {
const existQa = await qaPlugin.database.find<QAInfo[]>('qa', (_, i) => {
return i === no - 1;
});
if (!existQa) return `问答${no} 不存在`;
const editor = `${adapter.name}:${message.sender?.user_id}`;
if (editor !== existQa?.authorId) return `仅作者本人:${existQa?.authorName} 才能更改哦`;
await qaPlugin.jsondb.replace<QAInfo>('qa', item => JSON.stringify(item) === JSON.stringify(existQa), {
await qaPlugin.database.replace<QAInfo>('qa', item => JSON.stringify(item) === JSON.stringify(existQa), {
...existQa,
content: content || existQa.content,
answer: answer || existQa.answer,
Expand All @@ -153,16 +154,16 @@ qaCommand
.command('删除问答 <no:number>')
.option('-y <confirm:boolean> 是否确认', false)
.action(async ({ adapter, message, options, prompt }, no) => {
const qa = await qaPlugin.jsondb.find<QAInfo[]>(`qa`, (_, index) => index === no - 1);
const qa = await qaPlugin.database.find<QAInfo[]>(`qa`, (_, index) => index === no - 1);
if (!qa) return `问答不存在`;
if (qa.authorId !== `${adapter.name}:${message.sender?.user_id}`) return `非作者本人(${qa.authorName})不可删除!`;
const isConfirm = options.confirm || (await prompt.confirm('确认删除吗?'));
if (!isConfirm) return '已取消删除';
await qaPlugin.jsondb.remove<QAInfo>('qa', qa);
await qaPlugin.database.remove<QAInfo>('qa', qa);
return `已删除问答:${no}`;
});
qaCommand.command('问答详情 <no:number>').action(async (_, no) => {
const qa = await qaPlugin.jsondb.find<QAInfo[]>(`qa`, (_, idx) => idx === no - 1);
const qa = await qaPlugin.database.find<QAInfo[]>(`qa`, (_, idx) => idx === no - 1);
if (!qa) return `问答不存在`;
return `问答${no}:\n${JSON.stringify(
Object.fromEntries(
Expand Down
11 changes: 6 additions & 5 deletions packages/plugins/schedule/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ declare module 'zhin' {
}
}
const schedulePlugin = new Plugin('定时任务');
schedulePlugin.required('database');
const scheduleManager = new ScheduleManager();
schedulePlugin.service('addTask', (cron: CronDescriptors, callback: Function) => {
return scheduleManager.addTask(cron, callback);
Expand All @@ -29,7 +30,7 @@ schedulePlugin.service('removeTask', no => {
return scheduleManager.removeTask(no);
});
const initialize = async () => {
const schedules = await schedulePlugin.jsondb.get<Schedule[]>('schedule', []);
const schedules = await schedulePlugin.database.get<Schedule[]>('schedule', []);
if (!schedules) return;
for (const schedule of schedules) {
addSchedule(schedule);
Expand All @@ -48,7 +49,7 @@ const addSchedule = (schedule: Schedule) => {
};
const scheduleCommand = schedulePlugin.command('定时模块');
scheduleCommand.command('定时列表').action(async ({ adapter, bot, message }) => {
const schedules = await schedulePlugin.jsondb.filter<Schedule[]>('schedule', schedule => {
const schedules = await schedulePlugin.database.filter<Schedule[]>('schedule', schedule => {
return (
schedule.adapter === adapter.name &&
schedule.bot_id === bot.unique_id &&
Expand Down Expand Up @@ -79,20 +80,20 @@ scheduleCommand.command('添加定时').action(async ({ adapter, prompt, bot, me
create_time: Date.now(),
message: message.toJSON(),
};
schedulePlugin.jsondb.push<Schedule>('schedule', schedule);
schedulePlugin.database.push<Schedule>('schedule', schedule);
addSchedule(schedule);
return '添加成功';
});
scheduleCommand
.command('删除定时 <no:number>')
.option('-c <confirm:boolean> 是否确认', false)
.action(async ({ prompt, options, bot, message }, no) => {
const schedule = await schedulePlugin.jsondb.get<Schedule>(`schedule.${no - 1}`);
const schedule = await schedulePlugin.database.get<Schedule>(`schedule.${no - 1}`);
if (!schedule) return '无此定时任务';
if (schedule.creator_id !== `${message.sender?.user_id}`) return `非作者本人(${schedule.creator_id})不可删除`;
const isConfirm = options.confirm || (await prompt.confirm('确认删除吗?'));
if (!isConfirm) return '已取消删除';
await schedulePlugin.jsondb.splice('schedule', no - 1, 1);
await schedulePlugin.database.splice('schedule', no - 1, 1);
scheduleManager.removeTask(no);
return '删除成功';
});
Expand Down
Loading

0 comments on commit 9d26ac5

Please sign in to comment.