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