163 lines
5.9 KiB
Python
163 lines
5.9 KiB
Python
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") |