Add new file
This commit is contained in:
91
bots/handlers/room_handler.py
Normal file
91
bots/handlers/room_handler.py
Normal 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)
|
||||
Reference in New Issue
Block a user