#!/usr/bin/env python3
"""
Test de téléchargement d'une vidéo Instagram en utilisant la technique exacte de cobalt.tools
"""

import subprocess
import json
import logging
import os
import time
import re
import random
import string
        # Headers pour le CDN Instagram avec plus de crédibilité
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.9',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
            'Referer': 'https://www.instagram.com/',
            'Origin': 'https://www.instagram.com',
            'Sec-Ch-Ua': '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
            'Sec-Ch-Ua-Mobile': '?0',
            'Sec-Ch-Ua-Platform': '"Windows"',
            'Sec-Fetch-Dest': 'document',
            'Sec-Fetch-Mode': 'navigate',
            'Sec-Fetch-Site': 'none',
            'Sec-Fetch-User': '?1',
            'Upgrade-Insecure-Requests': '1',
            'DNT': '1'.parse import urlencode

# Configuration du logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

def extract_post_id(url):
    """Extrait l'ID du post Instagram depuis l'URL"""
    patterns = [
        r'instagram\.com/p/([^/]+)',
        r'instagram\.com/reel/([^/]+)',
    ]
    for pattern in patterns:
        match = re.search(pattern, url)
        if match:
            return match.group(1).split('/')[0]
    return None

def get_video_url(url):
    """Récupère l'URL de la vidéo en utilisant la technique de cobalt.tools"""
    
    post_id = extract_post_id(url)
    if not post_id:
        logger.error("❌ URL Instagram invalide")
        return None
        
    try:
        # 1. Récupérer la page HTML du post
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.9',
            'Cache-Control': 'no-cache',
            'Dnt': '1',
            'Pragma': 'no-cache',
            'Sec-Ch-Ua': '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
            'Sec-Ch-Ua-Mobile': '?0',
            'Sec-Ch-Ua-Platform': '"macOS"',
            'Sec-Fetch-Dest': 'document',
            'Sec-Fetch-Mode': 'navigate',
            'Sec-Fetch-Site': 'none',
            'Sec-Fetch-User': '?1',
            'Upgrade-Insecure-Requests': '1'
        }
        
        # Headers spécifiques pour simuler un vrai navigateur
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.9',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1',
            'Sec-Ch-Ua': '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
            'Sec-Ch-Ua-Mobile': '?0',
            'Sec-Ch-Ua-Platform': '"Windows"',
            'Sec-Fetch-Dest': 'document',
            'Sec-Fetch-Mode': 'navigate',
            'Sec-Fetch-Site': 'none',
            'Sec-Fetch-User': '?1',
            'DNT': '1'
        }
        
        html_cmd = [
            'curl',
            f'https://www.instagram.com/reel/{post_id}/',
            '--cookie', 'ig_did=1234; csrftoken=5678; sessionid=9012',  # Cookies bidons mais requis
        ]
        
        # Ajouter les headers à la commande curl
        for header, value in headers.items():
            html_cmd.extend(['-H', f'{header}: {value}'])
            
        # Ajouter les options de curl
        html_cmd.extend([
            '--compressed',
            '-s',
            '-L',
            '-A', headers['User-Agent']  # User-Agent explicite
        ])
        ]
        
        logger.debug("Récupération de la page du post...")
        process = subprocess.Popen(html_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        
        if process.returncode != 0:
            logger.error(f"❌ Erreur lors de la récupération de la page: {stderr.decode()}")
            return None
            
        html_content = stdout.decode()
        
        # 2. Chercher l'URL de la vidéo dans le HTML
        try:
            # D'abord chercher dans les données JSON-LD
            json_ld_match = re.search(r'<script type="application/ld\+json">(.+?)</script>', html_content)
            if json_ld_match:
                try:
                    json_ld = json.loads(json_ld_match.group(1))
                    if 'contentUrl' in json_ld:
                        logger.debug("URL trouvée dans JSON-LD")
                        return json_ld['contentUrl']
                except json.JSONDecodeError:
                    pass

            # Ensuite chercher dans le contenu de la page
            video_matches = [
                # Format standard
                re.search(r'"video_url":"([^"]+)"', html_content),
                # Format reel
                re.search(r'"video_versions":\[{"type":\d+,"width":\d+,"height":\d+,"url":"([^"]+)"', html_content),
                # Format meta
                re.search(r'<meta property="og:video" content="([^"]+)"', html_content),
                # Format dash manifest
                re.search(r'"dash_manifest":"[^"]*BaseURL>([^<]+)<', html_content)
            ]

            for match in video_matches:
                if match:
                    video_url = match.group(1).replace('\\u0026', '&').replace('\\/', '/')
                    logger.debug(f"URL vidéo trouvée : {video_url}")
                    return video_url

            logger.error("❌ URL vidéo non trouvée dans le HTML")
            logger.debug("Contenu HTML :")
            logger.debug(html_content[:1000] + "...")  # Afficher le début du HTML pour debug
            return None
            
        except Exception as e:
            logger.error(f"❌ Erreur lors de l'extraction de l'URL: {str(e)}")
            return None
            
        try:
            shared_data = json.loads(shared_data_match.group(1))
            logger.debug("SharedData trouvé")
            
            # Trouver l'ID numérique du média
            media_id = None
            
            # Parcourir les données pour trouver l'ID
            entry_data = shared_data.get('entry_data', {})
            post_page = entry_data.get('PostPage', [{}])[0]
            media = post_page.get('graphql', {}).get('shortcode_media', {})
            
            if media:
                media_id = media.get('id')
            
            if not media_id:
                logger.error("❌ ID du média non trouvé")
                return None
                
            logger.debug(f"ID du média trouvé: {media_id}")
            
            # Maintenant faire la requête à l'API mobile avec l'ID
            api_url = f"https://i.instagram.com/api/v1/media/{media_id}/info/"
            
            api_headers = {
                'User-Agent': 'Instagram 76.0.0.15.395 Android (24/7.0; 640dpi; 1440x2560; samsung; SM-G930F; herolte; samsungexynos8890; en_US; 138226743)',
                'Accept': '*/*',
                'Accept-Language': 'en-US',
                'Accept-Encoding': 'gzip, deflate',
                'X-IG-Capabilities': '3brTvw==',
                'X-IG-Connection-Type': 'WIFI',
                'X-IG-App-ID': '567067343352427',  # ID d'app Instagram Android
                'X-FB-HTTP-Engine': 'Liger',
                'X-IG-WWW-Claim': '0'
            }
            
            api_cmd = [
                'curl',
                api_url,
                '-H', f'User-Agent: {api_headers["User-Agent"]}',
                '-H', f'Accept: {api_headers["Accept"]}',
                '-H', f'Accept-Language: {api_headers["Accept-Language"]}',
                '-H', f'X-IG-Capabilities: {api_headers["X-IG-Capabilities"]}',
                '-H', f'X-IG-Connection-Type: {api_headers["X-IG-Connection-Type"]}',
                '-H', f'X-IG-App-ID: {api_headers["X-IG-App-ID"]}',
                '-H', f'X-FB-HTTP-Engine: {api_headers["X-FB-HTTP-Engine"]}',
                '-H', f'X-IG-WWW-Claim: {api_headers["X-IG-WWW-Claim"]}',
                '--compressed',
                '-s'
            ]
            
            logger.debug("Requête à l'API mobile...")
            process = subprocess.Popen(api_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout, stderr = process.communicate()
            
            if process.returncode != 0:
                logger.error(f"❌ Erreur lors de la requête API: {stderr.decode()}")
                return None
                
            try:
                api_data = json.loads(stdout)
                logger.debug("Réponse API reçue")
                
                # Trouver la meilleure version de la vidéo
                if 'items' in api_data and api_data['items']:
                    video_versions = api_data['items'][0].get('video_versions', [])
                    if video_versions:
                        # Trier par largeur pour avoir la meilleure qualité
                        best_version = max(video_versions, key=lambda x: x.get('width', 0))
                        video_url = best_version.get('url')
                        
                        if video_url:
                            return video_url
            except json.JSONDecodeError:
                logger.error("❌ Erreur de parsing de la réponse API")
                
            # Plan B : chercher directement dans le HTML
            url_match = re.search(r'"video_url":"([^"]+)"', html_content)
            if url_match:
                video_url = url_match.group(1).replace('\\u0026', '&')
                return video_url
                
            logger.error("❌ URL vidéo non trouvée")
            return None
                    
            return video_url
            
        except json.JSONDecodeError:
            logger.error("❌ Erreur de parsing des données JSON")
            return None
            
    except Exception as e:
        logger.error(f"❌ Erreur: {str(e)}")
        return None

def download_video(video_url, output_dir="downloads"):
    """Télécharge la vidéo avec les bons headers"""
    
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
        
    output_file = os.path.join(output_dir, f"video_{int(time.time())}.mp4")
    
    try:
        # Headers spécifiques pour le CDN Instagram
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
            'Accept': 'video/webm,video/mp4,video/*;q=0.9',
            'Accept-Language': 'en-US,en;q=0.9',
            'Range': 'bytes=0-',
            'Referer': 'https://www.instagram.com/',
            'Origin': 'https://www.instagram.com',
            'Sec-Fetch-Dest': 'video',
            'Sec-Fetch-Mode': 'no-cors',
            'Sec-Fetch-Site': 'cross-site'
        }
        
        cmd = [
            'curl',
            video_url,
            '-L',  # Suivre les redirections
            '-o', output_file
        ]
        
        # Ajouter les headers
        for header, value in headers.items():
            cmd.extend(['-H', f'{header}: {value}'])
            
        logger.info("🔄 Téléchargement de la vidéo...")
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        
        if process.returncode == 0 and os.path.exists(output_file):
            if os.path.getsize(output_file) > 0:
                logger.info(f"✅ Vidéo téléchargée: {output_file}")
                return output_file
            else:
                logger.error("❌ Fichier téléchargé vide")
                os.remove(output_file)
                return None
        else:
            logger.error(f"❌ Erreur lors du téléchargement: {stderr.decode()}")
            return None
            
    except Exception as e:
        logger.error(f"❌ Erreur: {str(e)}")
        if os.path.exists(output_file):
            os.remove(output_file)
        return None

def download_instagram_video(url):
    """Télécharge une vidéo Instagram comme le fait cobalt.tools"""
    
    logger.info(f"🔄 Téléchargement depuis Instagram: {url}")
    
    # 1. Obtenir l'URL de la vidéo
    video_url = get_video_url(url)
    if not video_url:
        logger.error("❌ Impossible de récupérer l'URL de la vidéo")
        return None
        
    logger.info("✅ URL vidéo trouvée")
    logger.debug(f"URL vidéo: {video_url}")
    
    # 2. Télécharger la vidéo
    return download_video(video_url)

if __name__ == "__main__":
    url = "https://www.instagram.com/reel/DMpc37-tJdF/"
    result = download_instagram_video(url)
    
    if result:
        print(f"\n✅ Vidéo téléchargée avec succès: {result}")
    else:
        print("\n❌ Échec du téléchargement")
