-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Архитектура: Какой официально
оптимальный способ организации бота на VK-IO
#387
Comments
Не скажу что "официальный" подход, просто поделюсь личными предпочтениями и немного практической части. Общий дизайнЯ предпочитаю использовать подход monorepo для организации распределённых модулей (собственно его использует библиотека). Можно взять уже готовый шаблон для сервисов, и отделить реализацию бота от библиотеки с помощью абстракций (так как любое критическое изменения потребует большого внимания для его адаптирования). Так же по-хорошему стоит использовать виртуальные машины для идентичных условий в разработке и продакшене, здесь поможет например Docker. АрхитектураЗависимости бота должны быть явными, т.е. никаких добавлений "фич" с помощью одного импорта, иначе тут начнётся сущий кошмар отладки. Абстрактный код: // commands/random.ts
import { Command } from '@my-project/core';
import { getRandomIntegerInRange } from '@my-project/utils';
export const randomCommand = new Command({
slug: 'random',
aliases: [
'рандом',
'random'
],
description = 'рандмоное число в промежутке';
arguments: [
{
type: 'integer',
key: 'min',
label: 'минк/макс',
default: null
},
{
type: 'integer',
key: 'max',
label: 'минк/макс',
default: null
}
],
handler(context) {
// Работаем с аргументами, а не текстом
let { min = null, max = null } = context.commander.params;
if (min === null && max === null) {
min = 0;
max = 100;
} else if (max === null) {
max = min;
min = 0;
}
const result = getRandomIntegerInRange(min, max);
return context.answer({
text: `число в промежутке ${min} - ${max}: ${result}`
});
}
});
// commands/index.ts
export * from './random';
// bot.ts
import {
Bot,
SessionManager,
RedisSessionStorage,
RateLimitManager,
CommanderManager
} from '@my-project/core';
import * as commands from './commands';
const sessionManager = new SessionManager({
storage: new RedisSessionStorage({})
});
const rateLimitManager = new RateLimitManager({
maxPerSecond: 1
});
const commanderManager = new CommanderManager();
for (const command of Object.values(commands)) {
commanderManager.add(command);
}
const bot = new Bot({
// ...options
});
// Это может быть кастомная цепочка middleware в боте
bot.incoming.on('message', sessionManager.middleware);
bot.incoming.on('message', rateLimitManager.middleware);
bot.incoming.on('message', commanderManager.middleware);
bot.start()
.then(() => {
console.log('Bot started', error);
})
.catch((error: Error) => {
console.error('Error starting bot', error);
process.exit(1);
}); Важные вещи из кода выше:
export const dndCommand = new Command({
// ...
handler(context) {
return context.commander.enter('random', {
params: {
min: 1,
max: 20
}
});
}
});
ЗаключениеЭто подход я использовал в моих ботах, и он оказался вполне удобным для реализации от простых до сложных ботов. В лучшем случае пакет export { Bot, Command } from 'super-bot-library';
export { ViewerManager } from './middlewares'; В случаях изменений в библиотеке можно тогда будет заменить один из интерфейсов. Но никто не запрещает держать всё логику только для проекта. Есть ещё интересный вариант реализации логики бота на хуках, который применяется допустим в |
Спасибо, очень хороший и развёрнутый ответ. И я бы хотел попросить, тебя оставить issue открытым, чтобы другие люди тоже смогли прочитать |
Привет, смотрел твой разбор ботов на ютубе, и у них у всех была одна большая проблема: весь код - портянка на 5к строк. Поэтому у меня созрел вопрос: как ты видишь, что должен быть устроен проект с VK-IO. Потому что в нынешнем виде это либо портянка, либо индекс + конфиг + куча файлов, который выглядит примерно вот так:
И у него тоже есть проблемы:
Хотелось бы услышать твой ответ на это и дублирование его в очень явном виде в документацию, и возможно в
README.md
The text was updated successfully, but these errors were encountered: