This commit is contained in:
Andrey Kondratev
2025-09-09 15:39:28 +05:00
parent 3b2d5ece24
commit d4debf9b63
33 changed files with 1274 additions and 9585 deletions

163
backend/bot.py Normal file
View File

@@ -0,0 +1,163 @@
import os
from typing import Optional
from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, WebAppInfo
from telegram.ext import Application, CommandHandler, MessageHandler, filters
import httpx
from .database import Database, User
class QuixoticBot:
def __init__(self, token: str, web_app_url: str, database: Database):
self.token = token
self.web_app_url = web_app_url
self.db = database
self.bot = Bot(token=token)
self.application = Application.builder().token(token).build()
self.setup_handlers()
def setup_handlers(self):
"""Setup bot command and message handlers"""
# Command handlers
self.application.add_handler(CommandHandler("start", self.start_command))
self.application.add_handler(CommandHandler("help", self.help_command))
# Message handlers
self.application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, self.handle_message))
async def start_command(self, update, context):
"""Handle /start command"""
user = update.effective_user
chat_id = update.effective_chat.id
# Save or update user in database
try:
db_user = await self.db.get_user_by_telegram_id(str(user.id))
if not db_user:
await self.db.add_user(
telegram_id=str(user.id),
username=user.username,
first_name=user.first_name,
last_name=user.last_name,
language_code=user.language_code
)
except Exception as e:
print(f"Database error in start command: {e}")
# Create inline keyboard with web app button
keyboard = [
[InlineKeyboardButton(
"🎵 Open Quixotic",
web_app=WebAppInfo(url=self.web_app_url)
)]
]
reply_markup = InlineKeyboardMarkup(keyboard)
welcome_text = (
f"👋 Welcome to Quixotic, {user.first_name}!\n\n"
"🎵 Search and download music from SoundCloud\n"
"🚀 Fast MP3 conversion\n"
"📱 Easy-to-use interface\n\n"
"Click the button below to get started!"
)
await context.bot.send_message(
chat_id=chat_id,
text=welcome_text,
reply_markup=reply_markup
)
async def help_command(self, update, context):
"""Handle /help command"""
help_text = (
"🎵 *Quixotic Bot Help*\n\n"
"*Commands:*\n"
"/start - Start the bot and open the music app\n"
"/help - Show this help message\n\n"
"*How to use:*\n"
"1. Click 'Open Quixotic' to launch the web app\n"
"2. Search for your favorite songs\n"
"3. Convert and download as MP3\n"
"4. Music files will be sent directly to this chat\n\n"
"*Features:*\n"
"• SoundCloud music search\n"
"• High-quality MP3 conversion\n"
"• Fast downloads\n"
"• Search history tracking\n\n"
"Enjoy your music! 🎶"
)
await update.message.reply_text(
help_text,
parse_mode='Markdown'
)
async def handle_message(self, update, context):
"""Handle text messages"""
# For now, just respond with instructions to use the web app
keyboard = [
[InlineKeyboardButton(
"🎵 Open Quixotic",
web_app=WebAppInfo(url=self.web_app_url)
)]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text(
"Use the web app to search and download music! 🎵",
reply_markup=reply_markup
)
async def send_audio_file(self, chat_id: int, audio_url: str, title: str,
performer: Optional[str] = None, thumbnail: Optional[str] = None):
"""Send audio file to user"""
try:
print(f"📤 Sending audio to chat {chat_id}")
# Download the audio file first
async with httpx.AsyncClient() as client:
response = await client.get(audio_url)
response.raise_for_status()
audio_data = response.content
# Send audio
await self.bot.send_audio(
chat_id=chat_id,
audio=audio_data,
title=title,
performer=performer or "Unknown Artist",
duration=None, # Let Telegram figure it out
caption=f"🎵 {title}" + (f" by {performer}" if performer else ""),
thumbnail=thumbnail if thumbnail else None
)
print(f"✅ Audio sent successfully to chat {chat_id}")
except Exception as e:
print(f"❌ Failed to send audio to chat {chat_id}: {e}")
# Send error message
error_message = (
"❌ Failed to send audio file. "
"The file might be too large or temporarily unavailable."
)
try:
await self.bot.send_message(chat_id=chat_id, text=error_message)
except Exception as msg_error:
print(f"❌ Failed to send error message: {msg_error}")
raise e
async def start_polling(self):
"""Start bot polling"""
print("🤖 Starting bot polling...")
await self.application.initialize()
await self.application.start()
await self.application.updater.start_polling()
async def close(self):
"""Close bot application"""
if self.application:
await self.application.stop()
await self.application.shutdown()
print("🤖 Bot closed")