174 lines
7.2 KiB
Python
174 lines
7.2 KiB
Python
import re
|
||
import os
|
||
import time
|
||
from .download_audio_services import get_downloader
|
||
|
||
class CommandHandler:
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
self.commands = self._register_commands()
|
||
|
||
def _register_commands(self):
|
||
"""Регистрация всех доступных команд"""
|
||
return {
|
||
"help": {
|
||
"handler": self.cmd_help,
|
||
"description": "Показать справку по командам",
|
||
"public": True
|
||
},
|
||
"ping": {
|
||
"handler": self.cmd_ping,
|
||
"description": "Проверить работоспособность бота",
|
||
"public": True
|
||
},
|
||
"mp3": {
|
||
"handler": self.cmd_mp3,
|
||
"description": f"Скачать аудио из YouTube. Использование: {self.bot.config['command_prefix']} mp3 <url>",
|
||
"public": True
|
||
},
|
||
# Здесь можно добавлять новые команды
|
||
}
|
||
|
||
def generate_help_text(self, detailed=False):
|
||
"""Генерация текста справки"""
|
||
if detailed:
|
||
text = f"**Полная справка по командам бота**\n\nВсе команды начинаются с `{self.bot.config['command_prefix']}`:\n"
|
||
for cmd, info in self.commands.items():
|
||
if info.get("public", False):
|
||
text += f"\n• `{self.bot.config['command_prefix']} {cmd}` - {info['description']}"
|
||
text += "\n\nБот игнорирует сообщения без префикса команды."
|
||
return text
|
||
|
||
return (
|
||
f"Привет! Я бот PingPong. Для взаимодействия используйте команды "
|
||
f"с префиксом `{self.bot.config['command_prefix']}`. "
|
||
f"Напишите `{self.bot.config['command_prefix']} help` для получения полной справки."
|
||
)
|
||
|
||
# --- Обработчики команд ---
|
||
async def cmd_help(self, room_id, event, args):
|
||
await self.bot.send_text(room_id, self.generate_help_text(detailed=True))
|
||
async def cmd_ping(self, room_id, event, args):
|
||
await self.bot.send_text(room_id, "pong")
|
||
|
||
async def cmd_mp3(self, room_id, event, args):
|
||
"""Обработчик команды mp3"""
|
||
if not args:
|
||
await self.bot.send_text(
|
||
room_id,
|
||
"❌ Укажите URL видео. Например: `/media mp3 https://www.youtube.com/watch?v=...`"
|
||
)
|
||
return
|
||
|
||
url = args.strip()
|
||
download_config = self.bot.config.get('download_audio', {})
|
||
downloader_config = None
|
||
|
||
# Определяем загрузчик для URL
|
||
|
||
downloader = None
|
||
for service, config in download_config.get('services', {}).items():
|
||
if config.get('enabled', False):
|
||
downloader_config = config
|
||
dl_class = get_downloader(service)
|
||
if dl_class:
|
||
downloader = dl_class()
|
||
if downloader.is_supported_url(url):
|
||
break
|
||
else:
|
||
downloader = None
|
||
downloader_config = None
|
||
|
||
if not downloader:
|
||
await self.bot.send_text(room_id, "❌ Этот сервис не поддерживается.")
|
||
return
|
||
|
||
# Уведомляем о начале загрузки
|
||
await self.bot.send_text(room_id, "⏳ Начинаю загрузку... Это может занять несколько минут.")
|
||
|
||
try:
|
||
# Запускаем загрузку
|
||
file_path, title_or_error, duration = await downloader.download_audio(url, downloader_config)
|
||
|
||
if not file_path:
|
||
raise Exception(title_or_error or "Ошибка загрузки")
|
||
|
||
# Простой метод отправки файла
|
||
with open(file_path, 'rb') as f:
|
||
# Получаем размер файла
|
||
file_size = os.path.getsize(file_path)
|
||
|
||
# Загружаем файл на сервер Matrix
|
||
mime_type = "audio/mpeg"
|
||
response, _ = await self.bot.client.upload(
|
||
f,
|
||
content_type=mime_type,
|
||
filename=f"{title_or_error}.mp3"
|
||
)
|
||
|
||
# Формируем сообщение с аудио
|
||
audio_content = {
|
||
"body": f"{title_or_error}.mp3",
|
||
"info": {
|
||
"mimetype": mime_type,
|
||
"size": file_size,
|
||
"duration": duration or 0 # Можно оставить 0, если длительность неизвестна
|
||
},
|
||
"msgtype": "m.audio",
|
||
"url": response.content_uri,
|
||
}
|
||
|
||
# Отправляем сообщение
|
||
await self.bot.client.room_send(
|
||
room_id,
|
||
message_type="m.room.message",
|
||
content=audio_content
|
||
)
|
||
|
||
await self.bot.send_text(room_id, "✅ Готово! Аудио отправлено.")
|
||
|
||
except Exception as e:
|
||
error_msg = f"⚠️ Ошибка при загрузке: {str(e)}"
|
||
await self.bot.send_text(room_id, error_msg)
|
||
print(f"[ERROR] MP3 download failed: {str(e)}")
|
||
|
||
finally:
|
||
# Очистка временных файлов
|
||
if file_path and os.path.exists(file_path):
|
||
try:
|
||
os.remove(file_path)
|
||
except:
|
||
pass
|
||
|
||
|
||
|
||
# --- Обработка входящих команд ---
|
||
async def process_command(self, room_id, event):
|
||
"""Обработка и выполнение команд"""
|
||
msg = event.body.strip()
|
||
command_prefix = self.bot.config["command_prefix"]
|
||
|
||
# Проверяем префикс команды
|
||
if not msg.startswith(command_prefix):
|
||
return
|
||
|
||
# Извлекаем команду и аргументы
|
||
cmd_parts = re.split(r'\s+', msg[len(command_prefix):].strip(), maxsplit=1)
|
||
command = cmd_parts[0].lower()
|
||
args = cmd_parts[1] if len(cmd_parts) > 1 else ""
|
||
|
||
# Ищем обработчик команды
|
||
cmd_info = self.commands.get(command)
|
||
if not cmd_info:
|
||
await self.bot.send_text(
|
||
room_id,
|
||
f"Неизвестная команда. Используйте `{command_prefix} help` для справки."
|
||
)
|
||
return
|
||
|
||
try:
|
||
# Выполняем команду
|
||
await cmd_info["handler"](room_id, event, args)
|
||
except Exception as e:
|
||
print(f"[ERROR] Command '{command}' failed: {str(e)}")
|
||
await self.bot.send_text(room_id, "⚠️ Произошла ошибка при выполнении команды") |