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