#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import logging
import time
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
import yt_dlp
import asyncio
import re
from urllib.parse import urlparse

# Konfigurasi logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

# Token bot dari BotFather
TOKEN = "7512230737:AAHM2md1nUy7Bbhy79YYdbGMOiMF_glnQrk"

# Direktori untuk menyimpan file sementara
TEMP_DIRECTORY = "downloads"
os.makedirs(TEMP_DIRECTORY, exist_ok=True)

# Handler untuk perintah /start
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Mengirim pesan saat perintah /start diterima."""
    user = update.effective_user
    await update.message.reply_text(
        f"Halo {user.first_name}! 👋\n\n"
        f"Saya adalah bot converter MP3. Kirimkan saya link video/audio dari YouTube, TikTok, Instagram, atau platform lainnya, "
        f"dan saya akan mengkonversi dan mengirimkannya kembali dalam format MP3.\n\n"
        f"Gunakan perintah /help untuk melihat bantuan."
    )

# Handler untuk perintah /help
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Mengirim pesan bantuan saat perintah /help diterima."""
    await update.message.reply_text(
        "🎵 *MP3 Converter Bot* 🎵\n\n"
        "*Cara Penggunaan:*\n"
        "1. Kirim link video/audio dari YouTube, TikTok, Instagram, atau platform lainnya\n"
        "2. Tunggu bot mengunduh dan mengkonversi file\n"
        "3. Bot akan mengirimkan file MP3 hasil konversi\n\n"
        "*Platform yang Didukung:*\n"
        "- YouTube\n"
        "- TikTok\n"
        "- Instagram\n"
        "- SoundCloud\n"
        "- Facebook\n"
        "- Twitter/X\n"
        "- Dan banyak lagi\n\n"
        "*Perintah:*\n"
        "/start - Memulai bot\n"
        "/help - Menampilkan bantuan\n\n"
        "*Catatan:*\n"
        "- Ukuran file maksimal yang dapat dikirim adalah 50MB (batasan Telegram)\n"
        "- Waktu konversi tergantung pada ukuran dan durasi file",
        parse_mode='Markdown'
    )

# Fungsi untuk mendapatkan informasi platform dari URL
def get_platform_info(url):
    """Mendapatkan informasi platform dari URL."""
    parsed_url = urlparse(url)
    domain = parsed_url.netloc.lower()
    
    if 'youtube.com' in domain or 'youtu.be' in domain:
        return 'YouTube'
    elif 'tiktok.com' in domain:
        return 'TikTok'
    elif 'instagram.com' in domain:
        return 'Instagram'
    elif 'facebook.com' in domain or 'fb.com' in domain:
        return 'Facebook'
    elif 'twitter.com' in domain or 'x.com' in domain:
        return 'Twitter/X'
    elif 'soundcloud.com' in domain:
        return 'SoundCloud'
    else:
        return 'Media'

# Fungsi untuk mengunduh dan mengkonversi ke MP3
async def download_and_convert(url, output_path):
    """Mengunduh video/audio dari URL dan mengkonversi ke MP3."""
    platform = get_platform_info(url)
    
    # Konfigurasi yt-dlp berdasarkan platform
    ydl_opts = {
        'format': 'bestaudio/best',
        'outtmpl': output_path,
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }],
        'prefer_ffmpeg': True,
        'keepvideo': False,
        'noplaylist': True,  # Tidak mengunduh playlist, hanya satu video
        'quiet': False,
        'verbose': False,
        'no_warnings': False,
        'ignoreerrors': False,
        'geo_bypass': True,  # Mencoba bypass geo-restriction
        'extractor_retries': 3,  # Coba ulang ekstraksi 3 kali
        'socket_timeout': 30,  # Timeout 30 detik
        # Header browser yang lebih realistis untuk menghindari deteksi bot
        'http_headers': {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
            'Accept-Language': 'en-US,en;q=0.9,id;q=0.8',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
            'Referer': 'https://www.google.com/',
            'Sec-Fetch-Mode': 'navigate'
        }
    }
    
    # Tambahkan opsi khusus untuk platform tertentu
    if platform == 'YouTube':
        # Gunakan cookies jika tersedia
        cookies_file = 'youtube_cookies.txt'
        if os.path.exists(cookies_file):
            ydl_opts['cookiefile'] = cookies_file
            
    elif platform == 'TikTok':
        ydl_opts['cookiefile'] = 'tiktok_cookies.txt'  # File cookies untuk TikTok
        
    loop = asyncio.get_event_loop()
    
    def download():
        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            info = ydl.extract_info(url, download=True)
            return info
    
    # Jalankan download di thread terpisah untuk menghindari blocking
    info = await loop.run_in_executor(None, download)
    
    # Kembalikan path file MP3 yang dihasilkan dan informasi tambahan
    return {
        'file_path': f"{output_path}.mp3",
        'title': info.get('title', 'Audio'),
        'duration': info.get('duration', 0),
        'platform': platform,
        'uploader': info.get('uploader', 'Unknown'),
        'thumbnail': info.get('thumbnail', None)
    }

# Fungsi untuk memformat durasi
def format_duration(seconds):
    """Memformat durasi dalam detik menjadi format mm:ss atau hh:mm:ss."""
    if not seconds:
        return "Unknown duration"
    
    minutes, seconds = divmod(int(seconds), 60)
    hours, minutes = divmod(minutes, 60)
    
    if hours > 0:
        return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
    else:
        return f"{minutes:02d}:{seconds:02d}"

# Handler untuk URL
async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Menangani pesan yang berisi URL."""
    url = update.message.text.strip()
    
    # Periksa apakah pesan berisi URL yang valid
    url_pattern = re.compile(r'https?://\S+')
    if not url_pattern.match(url):
        await update.message.reply_text("❌ Mohon kirimkan URL yang valid.")
        return
    
    # Beri tahu pengguna bahwa proses sedang berjalan
    progress_message = await update.message.reply_text(
        f"⏳ Sedang memproses URL dari {get_platform_info(url)}...\n"
        f"Harap tunggu, ini mungkin memerlukan waktu beberapa menit."
    )
    
    start_time = time.time()
    
    try:
        # Buat nama file unik berdasarkan ID chat dan timestamp
        file_name = f"{TEMP_DIRECTORY}/{update.effective_chat.id}_{update.message.message_id}"
        
        # Unduh dan konversi file
        result = await download_and_convert(url, file_name)
        
        # Hitung waktu yang diperlukan
        elapsed_time = time.time() - start_time
        
        # Perbarui pesan progress
        await progress_message.edit_text(
            f"✅ Berhasil mengunduh dan mengkonversi!\n"
            f"Sedang mengirim file MP3... ({format_duration(elapsed_time)})"
        )
        
        # Format caption
        caption = (
            f"🎵 *{result['title']}*\n\n"
            f"📱 Platform: {result['platform']}\n"
            f"⏱️ Durasi: {format_duration(result['duration'])}\n"
            f"👤 Uploader: {result['uploader']}\n\n"
            f"✅ Berhasil dikonversi ke MP3!"
        )
        
        # Kirim file MP3 ke pengguna
        await update.message.reply_audio(
            audio=open(result['file_path'], 'rb'),
            title=result['title'],
            caption=caption,
            performer="MP3 Converter Bot",
            parse_mode='Markdown',
            duration=result['duration']
        )
        
        # Hapus pesan progress
        await progress_message.delete()
        
        # Hapus file sementara
        try:
            os.remove(result['file_path'])
            logger.info(f"File {result['file_path']} berhasil dihapus")
        except Exception as e:
            logger.error(f"Error saat menghapus file: {e}")
            
    except Exception as e:
        logger.error(f"Error: {e}")
        error_message = str(e)
        
        # Buat pesan error yang lebih user-friendly
        if "Video unavailable" in error_message:
            error_message = "Video tidak tersedia. Mungkin video telah dihapus atau bersifat privat."
        elif "sign in to confirm" in error_message.lower() or "not a bot" in error_message.lower():
            error_message = "YouTube meminta verifikasi bahwa Anda bukan bot. Coba video lain atau hubungi admin bot."
        elif "copyright" in error_message.lower():
            error_message = "Video ini memiliki masalah hak cipta dan tidak dapat diunduh."
        elif "ffmpeg" in error_message.lower():
            error_message = "Terjadi kesalahan saat mengkonversi audio. Coba lagi nanti."
        elif "network" in error_message.lower() or "timeout" in error_message.lower():
            error_message = "Terjadi masalah jaringan. Coba lagi nanti."
        
        await progress_message.edit_text(
            f"❌ Terjadi kesalahan saat mengunduh atau mengkonversi.\n\n"
            f"Detail: {error_message}\n\n"
            f"Silakan coba URL lain atau coba lagi nanti."
        )

# Fungsi untuk membuat file cookies kosong
def create_empty_cookies_files():
    """Membuat file cookies kosong untuk berbagai platform."""
    # Untuk YouTube
    with open('youtube_cookies.txt', 'w') as f:
        f.write("# Netscape HTTP Cookie File\n# This is a generated file! Do not edit.\n\n")
    logger.info("File youtube_cookies.txt berhasil dibuat")
    
    # Untuk TikTok
    with open('tiktok_cookies.txt', 'w') as f:
        f.write("# HTTP Cookie File\n")
    logger.info("File tiktok_cookies.txt berhasil dibuat")

def main() -> None:
    """Memulai bot."""
    # Buat file cookies kosong
    create_empty_cookies_files()
    
    # Buat aplikasi dan tambahkan handlers
    application = Application.builder().token(TOKEN).build()
    
    # Tambahkan handlers
    application.add_handler(CommandHandler("start", start))
    application.add_handler(CommandHandler("help", help_command))
    application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_url))
    
    # Log informasi startup
    logger.info("Bot MP3 Converter telah dimulai")
    
    # Mulai bot
    application.run_polling()

if __name__ == '__main__':
    main()
