Watcher, Cron, Event Handler
Watcher — наблюдатель за сообщениями
Что это? Watcher реагирует на ЛЮБОЕ сообщение по regex-шаблону, а не только на команды с префиксом.
Важно: Watcher'ы запускаются ТОЛЬКО если:
- Сообщение НЕ является командой (не начинается с .)
- Сообщение НЕ обрабатывается FSM
Порядок обработки:
1. Команды (.ping)
2. FSM (если активно)
3. Watcher'ы
Сигнатура Watcher
regex— строка с регулярным выражениемmatch— то что нашлось по regex
Примеры
Авто-реакция на "спасибо"
@loader.watcher(r"(?:^|\s)(?:спс|спасибо|thx|thanks)(?:$|\s)")
async def auto_thanks(self, mx, event, match):
await event.react("❤️")
Авто-конвертация валют
import re
@loader.watcher(r"(\d+(?:\.\d+)?)\s*(\$|€|₽|rub|usd|eur)", flags=re.IGNORECASE)
async def auto_convert(self, mx, event, match):
amount = match.group(1)
currency = match.group(2).lower()
# ... конвертация
Про match
Что передаётся в match:
- Если regex имеет именованные группы (?P<name>...) → match.groupdict()
- Если regex имеет обычные группы → match.groups() или match.group(1)
- Если нет групп → match.group(0)
С именованными группами
@loader.watcher(r"перевести (?P<amount>\d+) (?P<currency>\w+)")
async def converter(self, mx, event, match: dict):
# match = {"amount": "100", "currency": "usd"}
amount = match["amount"]
currency = match["currency"]
Без групп
@loader.watcher(r"привет")
async def on_hello(self, mx, event, match: str):
# match = "привет"
await utils.answer(mx, "И тебе привет!", event=event)
Особенности Watcher'ов
- Все watcher'ы запускаются если regex совпадает. Если 5 модулей имеют watcher на одно и то же — запустятся все 5.
- Асинхронно: Запускаются через
asyncio.create_task() - НЕ блокируют другие watcher'ы и команды
- Нет порядка: Не гарантируется какой watcher запустится раньше
Event Handler — любые события Matrix
Реагирует не только на сообщения, но на ЛЮБЫЕ события Matrix:
from mautrix.types import EventType
@loader.on(EventType.ROOM_MEMBER)
async def on_member(self, mx, event):
"""Кто-то вошёл/вышел из комнаты"""
if event.content.membership == "join":
await utils.answer(mx, "Привет!", event=event)
Популярные EventType:
- EventType.ROOM_MESSAGE — новое сообщение
- EventType.ROOM_MEMBER — вступление/выход/приглашение
- EventType.ROOM_NAME — изменено название комнаты
- EventType.ROOM_TOPIC — изменён топик
- EventType.REACTION — добавлена реакция
- EventType.ROOM_ENCRYPTED — зашифрованное сообщение
Cron — периодические задачи
Выполняется автоматически по расписанию. Не зависит от сообщений.
@loader.cron("30m")
async def every_half_hour(self, mx):
"""Каждые 30 минут"""
self.log.info("Прошло 30 минут!")
Поддерживаемые форматы:
| Формат | Пример | Интервал |
|---|---|---|
N s |
60s |
60 секунд |
N m |
30m |
30 минут |
N h |
2h |
2 часа |
| Cron выражение | */5 * * * * |
каждые 5 минут |
| Cron выражение | 0 * * * * |
каждый час |
Fallback: Если формат непонятный — используется 60s.
Примеры Cron
Каждые 5 минут (cron)
@loader.cron("*/5 * * * *")
async def check_status(self, mx):
"""Проверять статус каждые 5 минут"""
try:
data = await utils.request("https://api.example.com/status")
self.log.info(f"Status: {data}")
except Exception as e:
self.log.error(f"Check failed: {e}")
Часовой бэкап
Особенности Cron
- Запускается при старте: Первое выполнение сразу при загрузке модуля
- Останавливается при выгрузке: Когда модуль удаляют — cron останавливается
- Параметры: Только
(self, mx)— нетevent - Не перекрываются: Если задача выполняется дольше интервала — следующая запустится по расписанию
Для обычных людей: Простыми словами что это такое — смотри Ключевые концепции.