Files
fckbot/bots/handlers/room_handler.py
Markov Andrey 8485cc8bf0 Add new file
2026-06-30 12:36:20 +00:00

91 lines
4.3 KiB
Python
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.
# -*- 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)