Closed AndreiDrang closed 5 years ago
С какой проблемы вы столкнулись? Текущая система используется для того, чтобы полученные события можно было обрабатывать - не только подбирать по тексту, но и проверять какие-либо критерии, модифицировать события для последующих обработчиков и т.д.
Окей.
Естественно, это хотелось бы делать, с наименьшим количеством костылей, поэтому я выбрал путь создания декораторов, но не вышло.
Возможно есть способ задать какой-то дополнительный "предобработчик" для плагинов, в котором можно вызывать проверки и в зависимости от результата обращаться к плагинам или нет?
Я не думаю, что система, в которой получится реализовать регистрацию плагинов не сможет быть гибкой, ведь дам всё так же можно будет задать дополнительные параметры(прикреплённые документы, переменные и т.д.)
Я не вижу никаких проблем. Можно сделать отдельный плагин, который будет проверять событие - заблокирован его инициатор или нет и т.д. Например, плагин из примера "prefix.py" делает именно это, но проверяет не отправителя сообщений, а наличие префикса.
С таймаутами немного интереснее. Можно добавить декоратор для функций-обработчиков, который будет проверять время и т.д. Так-же можно и создать отдельный плагин, который будет отмечать время использования команд и предотвращать использование без кулдауна, но это действительно будет достаточно костыльно.
В итоге, во-первых, предложенная модель наоборот никак не решает вопросы, которые подняты в этом вопросе. Во-вторых, использование декораторов - логичное и эргономичное решение, которому ничего, в общем-то не мешает (на сколько я могу судить).
С блокировкой Вас понял, действительно, можно создать плагин на подобии префикса и всё на этом.
предложенная модель наоборот никак не решает вопросы
Почему же? Бот вызывает нужный плагин, на плагине висит декоратор, в котором происходит заданная магия и тут либо плагин срабатывает, либо нет. И другие плагины не трогаются.
Я привёл два самых свежих примера, возможно были ещё вопросы, но из них как-то выбирались.
Ладно, спасибо за ответы.
Декораторы сейчас возможны в полной мере, не важно, от куда и как был передан контроль обработчику, вы, как разработчик, всегда можете добавить свой код перед или после обработки. Это справедливо для любого проекта на python вообще и ваше предложение рассказывает о БД, которая не относится к поднятому вопросу.
В версии kutana 2.0.0 будет использоваться сигнатура функции-обработчика, чтобы передавать нужные аргументы - поэтому там надо будет поработать над надёжным получением ожидаемых аргументов. Но для версии <2.0.0 никаких проблем даже теоретически нет. С самого начала этот разговор ведётся так, будто то, о чём вы говорите невозможно, когда никаких препятсвий нет.
Легко сделать декоратор, который будет проверять что-то перед основных обработчиком. Этот декоратор может как прекратить обработку события, так и пропустить только конкретный обработчик, на котором он висит.
вы, как разработчик, всегда можете добавить свой код перед или после обработки
Не хотелось лезть в ядро и переделывать его под себя.
С самого начала этот разговор ведётся так, будто то, о чём вы говорите невозможно, когда никаких препятсвий нет.
Потому как я искал различные способы решения вопросов, и простого, не костыльного, не нашёл.
ваше предложение рассказывает о БД, которая не относится к поднятому вопросу
На мой взгляд, это взаимосвязано, т.к. столкнулся стем, что мой декоратор, перед плагином обрабатывается n-раз и по этой причине логика с тайм-аутами не работала как надо, к примеру.
Я не говорю, что надо лезть в ядро. Функции-обработчики - это просто функции. В python не состовляет труда сделать декоратор. Вот пример работающего декоратора для реализации кулдауна без костылей, без изменения ядра.
from kutana import Plugin
import time
plugin = Plugin(name="Echo")
COOLDOWNS = {}
def with_cooldown(cooldown_name, cooldown=10):
def decorator(coro):
async def wrapper(*args, **kwargs):
now = time.time()
if now - COOLDOWNS.get(cooldown_name, 0) < cooldown:
await args[2].reply(
"Cooldown left: {}s".format(
10 - now + COOLDOWNS[cooldown_name]
)
)
return
COOLDOWNS[cooldown_name] = now
return await coro(*args, **kwargs)
return wrapper
return decorator
@plugin.on_startswith_text("echo")
@with_cooldown("cooldown_name", 10)
async def on_echo(message, attachments, env):
await env.reply("{}".format(env.body))
Пример работы:
Думаю мне стоит подчеркнуть, что для того, чтобы декораторы работали на версии 2.0.0, необходимо будет использовать functools.wraps
.
Я примерно такой же декоратор и писал. Только у меня ещё учитывается время последней активности юзера(хранится в БД). И обновляется, после запроса(успешного или нет). Пришлось разносить логику этой проверки по разным плагинам/декораторам.
Вы не переживайте, все вопросы которые я задал - я решил/реализовал. Просто рассчитывал на более простое(на мой взгляд) и легковесное(для бота) решение.
Декоратор прямолинейно проверяет - прошло время или нет, и если нет - не выполняет обработчик. Можно добавить в этот код запрос в БД и проверку ответа функции. Как можно упросить подобный подход?
Для реализации своей системы плагинов можно работать напрямую с Executor - создать свои обработчики прямо для событий. Обработчики будут получать события и окружение, а вы сможете релизовать любой подход для поиска ответов на запросы пользователей.
На сколько я понимаю, сейчас принцип работы ядра при выборе плагина примерно следующий - проходится по всем плагинам, пока не найдёт плагин с нужной командой, если нашёл - выполнил, если не нашёл - не выполнил ничего.
Expected Behavior
Как насчёт, такого варианта работы:
LIKE/ILIKE
всяких), ну а дальше действовать, как и сейчас - вначале вызывать те плагины, которые помечены для предварительного вызова, а потом уже тот, для которого пришла команда.Actual Behavior
Я так понимаю, для этого потребуется немного переработать ядро.
Context
Столкнулся с проблемой, когда хотел для плагинов добавить просто свои декораторы, оказалось что перед тем как добраться до нужного плагина, вызываются все мои декораторы, которые находятся у предыдущих плагинов. И, на сколько я знаю, подобный принцип регистрации плагинов в ядре присутствует у многих систем(в которых реализована модульность), к примеру Odoo.
P.S. Если в реализации потребуется помощь - готов заняться этим.
Спасибо.