Add new file

This commit is contained in:
Markov Andrey
2026-06-30 12:36:20 +00:00
parent a4c1276e2b
commit 8485cc8bf0

View File

@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
"""
Обработчик MUC комнат (Multi-User Chat).
- Автоматический вход по приглашению (даже если бот перезагружен комната сохраняется в БД).
- Периодическая проверка присутствия в комнатах и переподключение при необходимости.
- Сохранение JID комнат в PostgreSQL для восстановления после рестарта.
ВНИМАНИЕ: Все JID комнат должны храниться и сравниваться как строки (bare JID),
чтобы избежать ошибок типов при работе с asyncpg и slixmpp.
"""
import logging
import asyncio
logger = logging.getLogger(__name__)
class RoomHandler:
"""Управление комнатами: приглашения, реджоин, сохранение в БД."""
def __init__(self, bot):
self.bot = bot
async def accept_invite(self, inv):
"""
Обработчик события groupchat_invite.
Автоматически входит в комнату, добавляет её в список rooms и сохраняет в БД.
Аргументы:
inv: объект приглашения (содержит атрибуты 'room' или 'from')
"""
room = inv.get('room', inv.get('from'))
if not room:
logger.warning("Приглашение не содержит идентификатора комнаты")
return
# Преобразуем в строку bare JID (без ресурса)
if hasattr(room, 'bare'):
room_str = room.bare
else:
room_str = str(room)
logger.info(f"Приглашение в комнату {room_str}, входим.")
# Если комната ещё не в списке бота добавляем
if room_str not in self.bot.rooms:
self.bot.rooms.append(room_str)
# Входим в MUC-комнату
await self.bot.plugin['xep_0045'].join_muc(room_str, self.bot.boundjid.user)
async def rejoin_loop(self):
"""
Бесконечный цикл переподключения к комнатам.
Проверяет, в каких комнатах бот состоит, и если его нет переподключается.
"""
while True:
await asyncio.sleep(60)
# Получаем список комнат, где бот присутствует
joined_rooms = set()
try:
if hasattr(self.bot.plugin['xep_0045'], 'get_joined_rooms'):
joined_rooms = set(self.bot.plugin['xep_0045'].get_joined_rooms())
else:
joined_rooms = {str(r) for r in self.bot.plugin['xep_0045'].rooms.keys()}
except Exception as e:
logger.debug(f"Ошибка получения списка комнат: {e}")
continue
for room in self.bot.rooms:
if room not in joined_rooms:
logger.info(f"Попытка повторного входа в комнату {room}...")
try:
await self.bot.plugin['xep_0045'].join_muc(room, self.bot.boundjid.user)
await asyncio.sleep(1)
except Exception as e:
logger.error(f"Ошибка входа в {room}: {e}")
async def on_kicked(self, presence):
"""Обработчик события, когда бота исключают из комнаты."""
room = presence['from'].bare
logger.info(f"Бот был исключён из комнаты {room}")
if room in self.bot.rooms:
self.bot.rooms.remove(room)
async def on_banned(self, presence):
"""Обработчик события, когда бота банят в комнате."""
room = presence['from'].bare
logger.info(f"Бот был забанен в комнате {room}")
if room in self.bot.rooms:
self.bot.rooms.remove(room)