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

84 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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`:
```python
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`.
**Решение:** перед сравнением срезается ресурс:
```python
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>`:
```python
if msg["delay"]["stamp"]:
return # историческое сообщение, пропускаем
```
---
## 7. Логирование
Добавлено логирование на ключевых этапах обработки команд в `command_handler.py`:
- `INFO` — распознанная команда (`room_jid`, `caller_jid`, команда, аргумент)
- `INFO` — отклонение по правам (не-админ пытается выполнить команду)
- `DEBUG` — входящее сообщение, реальный JID, результат проверки прав
- `WARNING` — некорректный ввод (команда без обязательного аргумента, неверный интервал)