4.8 KiB
Update 1 — Исправления и дополнения к design.md
Документ фиксирует решения, принятые в ходе реализации и отладки, которые не описаны в design.md.
1. Запуск event loop (main.py)
Проблема: в примере из design.md используется bot.process(forever=True) — это API sleekxmpp, которого нет в slixmpp.
Решение: slixmpp — asyncio-native библиотека. Точка входа:
setup()— async-функция, собирает все зависимостиmain()— синхронная, создаёт event loop вручную черезasyncio.new_event_loop()connection.connect()ставит соединение в очередьloop.run_forever()держит бота живым
2. Обработка XMPP-сообщений (connection.py)
Проблема: в slixmpp событие message срабатывает для всех типов stanza, включая groupchat. Регистрация обоих событий (message + groupchat_message) на один обработчик вызывала двойную обработку каждого сообщения из комнаты.
Решение: один обработчик _on_message зарегистрирован только на событие message. Внутри — явная диспетчеризация по msg["type"]:
chat→ фильтр по собственному bare JIDgroupchat→ фильтр по нику бота (отражённые сервером собственные сообщения)- прочие типы → игнорируются
3. leave_muc не является корутиной
Проблема: muc.leave_muc() в slixmpp — синхронный метод. await muc.leave_muc(...) падал с TypeError: object NoneType can't be used in 'await' expression.
Решение: убран await у вызова leave_muc.
4. Получение реального JID участника MUC (command_handler.py)
Проблема: msg.get_plugin("xep_0045") вызывался на объекте стансы, а не на ClientXMPP. Метод всегда возвращал None, из-за чего caller_jid был None для всех участников → все команды, требующие прав админа, молча отбрасывались.
Решение:
- Добавлен порт
MucJidResolverвdomain/admin/ports.py:class MucJidResolver(ABC): def get_real_jid(self, room_jid: str, nick: str) -> str | None: ... JabberConnectionреализуетMucJidResolverчерезself.plugin["xep_0045"].get_jid_property(...)CommandHandlerпринимаетjid_resolver: MucJidResolverи использует его
5. Сравнение JID при проверке прав (command_handler.py)
Проблема: xep_0045 возвращает полный JID с ресурсом (user@server/resource), а в таблице rooms хранится bare JID (user@server). Сравнение room.admin_jid == caller_jid всегда давало False.
Решение: перед сравнением срезается ресурс:
caller_bare = caller_jid.split("/")[0]
return room.admin_jid == caller_bare
6. Воспроизведение истории при входе в комнату (command_handler.py)
Проблема: при входе бота в MUC-комнату XMPP-сервер воспроизводит историю сообщений (XEP-0091/XEP-0203). Все старые команды (! help, ! subscribe, ...) обрабатывались заново пакетом.
Решение: в начале _handle_room добавлена проверка наличия элемента <delay>:
if msg["delay"]["stamp"]:
return # историческое сообщение, пропускаем
7. Логирование
Добавлено логирование на ключевых этапах обработки команд в command_handler.py:
INFO— распознанная команда (room_jid,caller_jid, команда, аргумент)INFO— отклонение по правам (не-админ пытается выполнить команду)DEBUG— входящее сообщение, реальный JID, результат проверки правWARNING— некорректный ввод (команда без обязательного аргумента, неверный интервал)