jabnews/docs/update-1.md
2026-03-23 00:59:47 +03:00

4.8 KiB
Raw Permalink Blame History

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 JID
  • groupchat → фильтр по нику бота (отражённые сервером собственные сообщения)
  • прочие типы → игнорируются

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 — некорректный ввод (команда без обязательного аргумента, неверный интервал)