Валидаторы
Валидаторы в использовании представляют собой просто висящие декораторы над реакциями (Важно: они должны быть выше декоратора Reaction
) и на каждое подходящее событие проверяют, подходит ли команда по более конкретным условиям, например, попадает ли текстовая команда пользователя под шаблон заданной, зашел ли пользователь в беседу, или же вышел, имеет ли пользователь права на эту команду и прочее. Вместо того, чтобы городить кучу if'ов, достаточно просто повесить декоратор с нужными настройками. Помимо всего остального, валидаторы могут быть вызваны в async, и они всегда имеют одинаковый набор необходимых аргументов, что делает их совместимой с любой реакцией
Example
Команда сработает, если ее имя одно из names
и префикс один из prefs
, т.е. это валидные вызовы команды:
/info
!info
/инфо
!инфо
import vkquick as vq
@vq.Cmd(
names=["info", "инфо"],
prefs=["!", "/"]
)
@vq.Reaction("message_new")
def info(sender: vq.Sender()):
return f"Your name is {sender.fn} and last name is {sender.ln}"
Example
Команда сработает, если пользователь вышел из беседы
import vkquick as vq
@vq.Action("chat_leave_user")
@vq.Reaction("message_new")
def leave_chat():
return f"Someone left us!"
Валидаторы из коробки¶
Все валидаторы можно получить, обращаясь к модулю vkquick
, т.е. vq.Cmd
, vq.Action
Cmd
¶
Обработчик текстовой команды. Принимает в себя следующие аргументы при инициализации:
Поле | Тип | Значение по умолчанию | Описание |
---|---|---|---|
prefs |
List[str] | Нет префиксов | Возможные префиксы команды. Стоят в самом ее начале |
names |
str | Нет имен. Да, в совокупности с пустым префиксом и отсутствием аргументов это бесполезный валидатор. Можете смело убирать его в таком кейсе | Возможные имена команды. Идут вплотную к префиксу |
sensetive |
bool | False | Должна ли команда быть чувствительной к регистру символов |
argline |
str | По умолчанию не используется | Изначально все аргументы команды разделяются r"\s+" , но вы можете в корне поменять схему линии аргументов, используя ленивую интерполяцию. Например, пользователь должен ввести имя какого-то человека и через двоеточие число (/com Bob:56 ). Реакция будет выглядеть как на примере ниже |
Пример использовани параметра argline
import vkquick as vq
@vq.Cmd(
prefs=["/"],
names=["com"],
argline="\s+{name}:{num}"
)
@vq.Reaction("message_new")
def com(name: vq.Word(), num: int):
...
О получении аргументов команды¶
Наверно, самая важная и самая актуальная тема. Если вы обратили внимание на пример выше, то заметили новый vq.Word
и внезапно built-it класс int
. И так, как же это работает
Для того, чтобы указать, что у команды есть какой-то аргумент (какое-то упоминание, число и прочее), нужно использовать соответствующий класс, унаследованный от vq.CommandArgument
, в аннотациях. Например, команда, принимающая слово и число будет выглядеть так
import vkquick as vq
@vq.Cmd(names=["foo"])
@vq.Reaction("message_new")
def foo(val: vq.Word(), num: vq.Integer()):
return f"{val=} {num=}"
Пример вызова | Возвращаемое значение |
---|---|
/foo abcde 456 |
val='abcde' num=456 |
/foo fiz123z 456789 |
val='fiz123z' num=456789 |
Note
Заметьте, что vq.Integer
сразу вернул число, посколько строка обернулась в поле factory. О нем чуть ниже
Я думаю, что достаточно очевидно, как этим пользоваться — просто обозначаешь нужные аргументы нужными типами (о них ниже). Но что насчет payload-типов? Вы можете без проблем использовать и то, и другое в аргументах функции. vkquick поймет, что для чего. Например, код выше, но с использованием vq.Sender()
import vkquick as vq
@vq.Cmd(names=["foo"])
@vq.Reaction("message_new")
def foo(val: vq.Word(), num: vq.Integer(), sender: vq.Sender()):
return f"{sender.fn}, {val=} {num=}"
Теперь команда при ответе добавит имя отправителя в начале сообщения
И, конечно же, слово и число — не единственные типы. Вот они по порядку, слева направо: ворд, интегер, юзверьменьшион...
Имя | Фабрика, в которую обернется значение | Регулярные выражение | Описание |
---|---|---|---|
Integer |
int |
\d+ |
Целое число. Можете использовать int в аннотациях (что-то на подобие аллиасного типа). Эффект тот же. Скобки ставить тогда не нужно |
String |
str |
.+ |
Строка, состоящая как из пробельных, так и непробельных символов. Как и с Integer , для этого типа можно использовать str (тоже без скобок) |
Word |
str |
\S+ |
Слово, содержащее любые символы, кроме пробельных. Тобишь foo , foo123 , &foo)90 — слова, а вот foo bar — нет, это уже 2 слова |
List |
list |
- | Список каких-либо CommandArgument . Принимает аргументы: sep для разделителя, по умолчанию (?:\s*,\s*|\s+) , min_ (1) и max_ (не ограничено, Ellipsis ) для минимального и максимального количества элементов. Вы также можете просто обернуть тип в квадратные скобки, и он будет списковым, тобишь [int] — это аналог List(Integer()) |
UserMention |
User |
\[id\d+\|.+?\] |
Упоминание пользователя. Работает исключительно на упоминание, тобишь ни ссылки, ни просто цифры ID не сработают (скорее всего такая поддержка будет чуть позже). Принимает в себя поля‘ для по‘ля fields метода users.get , т.к. возвращает объект пользователя |
Literal |
str |
- | Своего рода Enum, аналог typing.Literal , т.е. набор определенных значений. Например, Literal("foo", "bar") означает (?:foo|bar) |
Custom |
- | - | Делает тип по регулярному выржанию из первого аргумента и фабрике из второго |
Optional |
- | - | Делает тип опциональным. Принимает заменитель, который будет возвращен в случае, если пользователь не передал аргумент в тексте |
Warning
vq.CommandArgument
(все типы из таблицы) всегда должны быть инстансами, тобишь всегда иметь скобки в аннотациях
Note
names
, prefs
и argline
поддерживают синтаксис регулярных выражений, поэтому будьте аккуратны, если используете, например, +
не как квантификатор, а как символ, тобишь вместо prefs=["+"]
нужно prefs=["\+"]
Зачем нужны префиксы для команд?
Префиксы для команды спасают от нежелательных и случайных вызовов команд. Более того, уникальный префикс является некой отличительной чертой ваше бота ;P
Но не перемудрите. Префиксный символ должен быть легко печатаем на клавиатуре и компуктеров, и мобильников
Кастомный аргумент для текстовой команды¶
Чтобы создать свой собственный Cmd-тип, унаследуйтесь от vq.CommandArgument
и определите следующее:
- Поле
rexp
, содержащее регулярное выражение, которому соотвествует тип. Если регулярка динамична, укажите""
, но при этом вам нужно будет определить инициализатор, в котром укажетеself.rexp
- Callable поле/метод (async/sync)
factory
, которое принимает один аргумент — строковое представление аргумента из текста, и, соответственно, возвращает нужный тип. Используйте его в своемprepare
. Сделано для совместимсоти с типомList
- Async/sync метод
prepare
, который вызывается у аргумента перед тем, как тот попадет вызов. Должен вернуть соответствующее значение (оберните его вfactory
) Принимает следующие поляargname
: Имя аргумента, на которое будет привязано значениеevent
: Событие LongPoll, с которым был связан вызов реакцииfunc
: Reaction-объект вашего обработчикаbin_stack
: Пустышка для дополнительных промежуточных полей. Используйте для испобежания гонки данных.
Примеры типов можно найти тут
Action¶
Принимает в себя *список обрабатываемых event.object.message.action.type
(Приглашение в беседу, выход, закрепление сообщения и прочее)
Todo
Планируюется добавить быстрое получение пользователя из member_id
ChatOnly¶
Сообщение пользователя должно быть отправленно только в беседе
DirectOnly¶
Сообщение пользователя должно быть отправленно только в лс
Кастомный валидатор¶
Для кастомного валидатора нужно унаследоваться от vq.Validator
и определить async/sync метод isvalid
(он вызывается для проверки для проверки валидности команды), принимающий следующие параметры
event
: Событие LongPollcom
: Объект командыbin_stack
: Поле, присутствующее только среди проверки одной реакции на валидность и подготовки аргументов. Помогает избегать гонку данных
После чего внутри функции указать return
'ы, возвращающие следующие кортежы
True
/False
, в зависимости от того, валидна ли реакция- Описание-подсказка, используемое в дебаггере для отображения состояния валидатора