{"version":3,"sources":["../utils.js","../index.js"],"sourcesContent":["/**\n * YtDlp Extractor Utilities\n * Helper functions for the custom YtDlp-Youtubei hybrid extractor\n */\n\nconst { exec } = require('child_process');\nconst { promisify } = require('util');\nconst fs = require('fs');\nconst path = require('path');\nconst { Innertube } = require('youtubei.js');\n\nconst execAsync = promisify(exec);\n\n/**\n * Initialize YouTube service\n */\nlet innertube = null;\nlet lastCookies = null;\n\nconst initializeYouTube = async (options = {}) => {\n    // Check if we need to reinitialize due to different cookies\n    const currentCookies = options.cookies;\n    const needsReinit = !innertube || (currentCookies !== lastCookies);\n\n    if (needsReinit) {\n        try {\n            const initOptions = {};\n\n            // Add cookies if provided\n            if (options.cookies) {\n                // Handle different cookie formats\n                if (typeof options.cookies === 'string') {\n                    // If it's a string, assume it's in Netscape format or raw cookie string\n                    initOptions.cookie = options.cookies;\n                } else {\n                    // If it's already an object or array, pass it directly\n                    initOptions.cookie = options.cookies;\n                }\n            }\n\n            // Add client configuration if provided\n            if (options.client) {\n                initOptions.client_name = options.client;\n            }\n\n            // Add additional options for better private content access\n            initOptions.enable_session_cache = true;\n\n            // Close existing instance if reinitializing\n            if (innertube) {\n                try {\n                    await innertube.session.signOut();\n                } catch (e) {\n                    // Ignore sign out errors\n                }\n            }\n\n            innertube = await Innertube.create(initOptions);\n            lastCookies = currentCookies;\n        } catch (error) {\n            console.error('❌ Failed to initialize YouTube service for extractor:', error);\n            // Don't throw here, return null to allow fallback\n            innertube = null;\n        }\n    }\n    return innertube;\n};\n\n/**\n * Check if a string is a valid URL\n */\nconst isValidUrl = (string) => {\n    try {\n        new URL(string);\n        return true;\n    } catch (_) {\n        return false;\n    }\n};\n\n/**\n * Check if URL is a YouTube URL\n */\nconst isYouTubeUrl = (url) => {\n    const youtubeRegex = /^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtu\\.be|m\\.youtube\\.com)/i;\n    return youtubeRegex.test(url);\n};\n\n/**\n * Check if URL is a YouTube playlist URL\n */\nconst isYouTubePlaylistUrl = (url) => {\n    const playlistRegex = /[?&]list=([a-zA-Z0-9_-]+)/;\n    return isYouTubeUrl(url) && playlistRegex.test(url);\n};\n\n/**\n * Extract playlist ID from YouTube URL\n */\nconst extractYouTubePlaylistId = (url) => {\n    const regex = /[?&]list=([a-zA-Z0-9_-]+)/;\n    const match = url.match(regex);\n    return match ? match[1] : null;\n};\n\n/**\n * Extract video ID from YouTube URL\n */\nconst extractYouTubeId = (url) => {\n    const regex = /(?:youtube\\.com\\/(?:[^\\/]+\\/.+\\/|(?:v|e(?:mbed)?)\\/|.*[?&]v=)|youtu\\.be\\/)([^\"&?\\/\\s]{11})/;\n    const match = url.match(regex);\n    return match ? match[1] : null;\n};\n\n/**\n * Search YouTube using youtubei.js\n */\nconst searchYouTube = async (query, limit = 1, options = {}) => {\n    try {\n        const yt = await initializeYouTube(options);\n        if (!yt) {\n            throw new Error('YouTube service not available');\n        }\n\n        // Add timeout to prevent hanging\n        const searchPromise = yt.search(query, { type: 'video' });\n        const timeoutPromise = new Promise((_, reject) =>\n            setTimeout(() => reject(new Error('YouTube search timeout')), 10000)\n        );\n\n        const searchResults = await Promise.race([searchPromise, timeoutPromise]);\n\n        if (!searchResults.videos || searchResults.videos.length === 0) {\n            return [];\n        }\n\n        const results = searchResults.videos.slice(0, limit).map(video => ({\n            id: video.id,\n            title: video.title?.text || 'Unknown Title',\n            duration: video.duration?.text || 'Unknown',\n            thumbnail: video.thumbnails?.[0]?.url || null,\n            url: `https://www.youtube.com/watch?v=${video.id}`,\n            author: video.author?.name || 'Unknown Artist',\n            views: video.view_count?.text || '0'\n        }));\n\n        return results;\n    } catch (error) {\n        console.error('YouTube search error:', error);\n        return [];\n    }\n};\n\n/**\n * Get YouTube playlist information and tracks\n */\nconst getYouTubePlaylist = async (playlistId, options = {}) => {\n    try {\n        // Check if this is a YouTube Mix playlist (starts with RD)\n        if (playlistId.startsWith('RD')) {\n            // For Mix playlists, we need to use a different approach\n            // Extract the seed video ID from the Mix playlist ID\n            let seedVideoId = null;\n            if (playlistId.length > 2) {\n                seedVideoId = playlistId.substring(2); // Remove 'RD' prefix\n            }\n\n            if (!seedVideoId || seedVideoId.length !== 11) {\n                throw new Error('Invalid YouTube Mix playlist ID format');\n            }\n\n            // For Mix playlists, we'll get the seed video and generate related tracks\n            // This is a workaround since Mix playlists are dynamically generated\n            const yt = await initializeYouTube(options);\n            if (!yt) {\n                throw new Error('YouTube service not available');\n            }\n\n            try {\n                // Get the seed video info\n                const seedVideo = await yt.getInfo(seedVideoId);\n                if (!seedVideo) {\n                    throw new Error('Seed video not found');\n                }\n\n                // Create a basic playlist structure with the seed video\n                const tracks = [{\n                    id: seedVideoId,\n                    title: seedVideo.basic_info?.title || 'Unknown Title',\n                    duration: seedVideo.basic_info?.duration?.text || 'Unknown',\n                    thumbnail: seedVideo.basic_info?.thumbnail?.[0]?.url || null,\n                    url: `https://www.youtube.com/watch?v=${seedVideoId}`,\n                    author: seedVideo.basic_info?.author || 'Unknown Artist',\n                    views: seedVideo.basic_info?.view_count || '0'\n                }];\n\n                // Try to get related videos to simulate the Mix\n                if (seedVideo.watch_next_feed) {\n                    const relatedVideos = seedVideo.watch_next_feed\n                        .filter(item => item.type === 'CompactVideo' && item.id && item.title)\n                        .slice(0, 19) // Get up to 19 more videos (20 total)\n                        .map(video => ({\n                            id: video.id,\n                            title: video.title?.text || 'Unknown Title',\n                            duration: video.duration?.text || 'Unknown',\n                            thumbnail: video.thumbnails?.[0]?.url || null,\n                            url: `https://www.youtube.com/watch?v=${video.id}`,\n                            author: video.author?.name || 'Unknown Artist',\n                            views: video.view_count?.text || '0'\n                        }));\n\n                    tracks.push(...relatedVideos);\n                }\n\n                return {\n                    id: playlistId,\n                    title: `Mix - ${seedVideo.basic_info?.title || 'Unknown'}`,\n                    description: 'YouTube Mix playlist (auto-generated)',\n                    thumbnail: seedVideo.basic_info?.thumbnail?.[0]?.url || null,\n                    author: 'YouTube',\n                    url: `https://www.youtube.com/playlist?list=${playlistId}`,\n                    tracks: tracks\n                };\n            } catch (mixError) {\n                console.error('Mix playlist generation error:', mixError);\n                throw new Error('Unable to access Mix playlist. This may be a private or unavailable Mix.');\n            }\n        }\n\n        const yt = await initializeYouTube(options);\n        if (!yt) {\n            throw new Error('YouTube service not available');\n        }\n\n        // Add timeout for playlist requests\n        const playlistPromise = yt.getPlaylist(playlistId);\n        const timeoutPromise = new Promise((_, reject) =>\n            setTimeout(() => reject(new Error('Playlist request timeout')), 15000)\n        );\n\n        const playlist = await Promise.race([playlistPromise, timeoutPromise]);\n\n        if (!playlist) {\n            throw new Error('Playlist not found or inaccessible');\n        }\n\n        // Check if playlist is accessible\n        if (!playlist.videos && !playlist.items) {\n            throw new Error('Playlist is private or unavailable. Please check your authentication.');\n        }\n\n        const tracks = [];\n\n        // Handle different playlist response formats\n        const videos = playlist.videos || playlist.items || [];\n\n        if (videos.length === 0) {\n            return {\n                id: playlistId,\n                title: playlist.info?.title || playlist.title?.text || 'Unknown Playlist',\n                description: playlist.info?.description || playlist.description?.text || '',\n                thumbnail: playlist.info?.thumbnails?.[0]?.url || playlist.thumbnails?.[0]?.url || null,\n                author: playlist.info?.author?.name || playlist.author?.name || 'Unknown',\n                url: `https://www.youtube.com/playlist?list=${playlistId}`,\n                tracks: []\n            };\n        }\n\n        // Process videos in batches to avoid overwhelming the API\n        const batchSize = 10;\n\n        for (let i = 0; i < videos.length; i += batchSize) {\n            const batch = videos.slice(i, i + batchSize);\n            const batchPromises = batch.map(async (video) => {\n                try {\n                    // Handle different video object formats\n                    const videoId = video.id || video.video_id;\n                    const title = video.title?.text || video.title || 'Unknown Title';\n                    const author = video.author?.name || video.channel?.name || 'Unknown Artist';\n                    const duration = video.duration?.text || video.duration || 'Unknown';\n                    const thumbnail = video.thumbnails?.[0]?.url || video.thumbnail?.url || null;\n                    const views = video.view_count?.text || video.views || '0';\n\n                    if (!videoId) {\n                        return null;\n                    }\n\n                    return {\n                        id: videoId,\n                        title: title,\n                        duration: duration,\n                        thumbnail: thumbnail,\n                        url: `https://www.youtube.com/watch?v=${videoId}`,\n                        author: author,\n                        views: views\n                    };\n                } catch (error) {\n                    return null;\n                }\n            });\n\n            const batchResults = await Promise.allSettled(batchPromises);\n            const validResults = batchResults\n                .filter(result => result.status === 'fulfilled' && result.value !== null)\n                .map(result => result.value);\n\n            tracks.push(...validResults);\n        }\n\n        return {\n            id: playlistId,\n            title: playlist.info?.title || playlist.title?.text || 'Unknown Playlist',\n            description: playlist.info?.description || playlist.description?.text || '',\n            thumbnail: playlist.info?.thumbnails?.[0]?.url || playlist.thumbnails?.[0]?.url || null,\n            author: playlist.info?.author?.name || playlist.author?.name || 'Unknown',\n            url: `https://www.youtube.com/playlist?list=${playlistId}`,\n            tracks: tracks\n        };\n    } catch (error) {\n        console.error('YouTube playlist error:', error);\n\n        // Provide more specific error messages\n        if (error.message.includes('unviewable') || error.message.includes('private')) {\n            throw new Error('This playlist is private or requires authentication. Please check your YouTube cookies.');\n        } else if (error.message.includes('timeout')) {\n            throw new Error('Playlist request timed out. Please try again.');\n        } else if (error.message.includes('not found')) {\n            throw new Error('Playlist not found. Please check the playlist ID.');\n        }\n\n        throw error;\n    }\n};\n\n/**\n * Get YouTube video metadata using youtubei.js\n */\nconst getYouTubeMetadata = async (videoId, options = {}) => {\n    try {\n        const yt = await initializeYouTube(options);\n        if (!yt) {\n            throw new Error('YouTube service not available');\n        }\n\n        const info = await yt.getInfo(videoId);\n        if (!info) {\n            throw new Error('Video not found');\n        }\n\n        // Better duration handling - try multiple sources\n        let duration = 'Unknown';\n        if (info.basic_info?.duration) {\n            if (typeof info.basic_info.duration === 'object') {\n                // If duration is an object with seconds property\n                if (info.basic_info.duration.seconds) {\n                    duration = formatDuration(info.basic_info.duration.seconds);\n                } else if (info.basic_info.duration.text) {\n                    duration = info.basic_info.duration.text;\n                }\n            } else if (typeof info.basic_info.duration === 'number') {\n                // If duration is a number (seconds)\n                duration = formatDuration(info.basic_info.duration);\n            } else if (typeof info.basic_info.duration === 'string') {\n                // If duration is already a string\n                duration = info.basic_info.duration;\n            }\n        }\n\n        // Better thumbnail handling\n        let thumbnail = null;\n        if (info.basic_info?.thumbnail) {\n            if (Array.isArray(info.basic_info.thumbnail) && info.basic_info.thumbnail.length > 0) {\n                // Get the highest quality thumbnail\n                const thumbnails = info.basic_info.thumbnail;\n                thumbnail = thumbnails[thumbnails.length - 1]?.url || thumbnails[0]?.url;\n            } else if (typeof info.basic_info.thumbnail === 'string') {\n                thumbnail = info.basic_info.thumbnail;\n            }\n        }\n\n        return {\n            id: videoId,\n            title: info.basic_info?.title || 'Unknown Title',\n            duration: duration,\n            thumbnail: thumbnail,\n            url: `https://www.youtube.com/watch?v=${videoId}`,\n            author: info.basic_info?.author || 'Unknown Artist',\n            views: info.basic_info?.view_count || 0,\n            description: info.basic_info?.short_description || ''\n        };\n    } catch (error) {\n        console.error('YouTube metadata error:', error);\n        return null;\n    }\n};\n\n/**\n * Get related tracks for autoplay functionality\n */\nconst getRelatedTracks = async (videoId, options = {}, limit = 10) => {\n    try {\n        const yt = await initializeYouTube(options);\n        if (!yt) {\n            throw new Error('YouTube service not available');\n        }\n\n        const info = await yt.getInfo(videoId);\n        if (!info || !info.watch_next_feed) {\n            return [];\n        }\n\n        // Get related videos from watch next feed\n        const relatedVideos = info.watch_next_feed.filter(item =>\n            item.type === 'CompactVideo' && item.id && item.title\n        ).slice(0, limit);\n\n        return relatedVideos.map(video => ({\n            id: video.id,\n            title: video.title?.text || 'Unknown Title',\n            duration: video.duration?.text || 'Unknown',\n            thumbnail: video.thumbnails?.[0]?.url || null,\n            url: `https://www.youtube.com/watch?v=${video.id}`,\n            author: video.author?.name || 'Unknown Artist',\n            views: video.view_count?.text || '0'\n        }));\n    } catch (error) {\n        console.error('YouTube related tracks error:', error);\n        return [];\n    }\n};\n\n/**\n * Get streaming URL using yt-dlp with optimizations\n */\nconst getStreamingUrl = async (url, ytdlpPath, quality = 'bestaudio[ext=m4a]/bestaudio[ext=webm]/bestaudio', cookies = null) => {\n    try {\n        if (!fs.existsSync(ytdlpPath)) {\n            throw new Error(`yt-dlp binary not found at: ${ytdlpPath}`);\n        }\n\n        // Optimized command for faster extraction and better compatibility\n        const optimizedArgs = [\n            '-f', quality,\n            '--get-url',\n            '--no-playlist',\n            '--no-warnings',\n            '--no-check-certificates',\n            '--prefer-insecure',\n            '--skip-download',\n            '--no-call-home',\n            '--no-cache-dir',\n            '--socket-timeout', '10',\n            '--retries', '3',\n            '--fragment-retries', '3'\n        ];\n\n        // Add cookies if provided for YouTube authentication\n        if (cookies && typeof cookies === 'string' && cookies.trim()) {\n            // Create a temporary cookies file for yt-dlp\n            const tempCookiesFile = path.join(__dirname, 'temp_cookies.txt');\n            try {\n                // Convert browser cookies to Netscape format\n                const netscapeCookies = convertToNetscapeFormat(cookies);\n                fs.writeFileSync(tempCookiesFile, netscapeCookies);\n                optimizedArgs.push('--cookies', tempCookiesFile);\n            } catch (cookieError) {\n                // Proceed without cookies if conversion fails\n            }\n        }\n\n        const command = `\"${ytdlpPath}\" ${optimizedArgs.join(' ')} \"${url}\"`;\n\n        const { stdout, stderr } = await execAsync(command, {\n            timeout: 15000, // Reduced timeout for faster response\n            maxBuffer: 1024 * 1024, // 1MB buffer should be enough for URL\n            encoding: 'utf8',\n            windowsHide: true // Hide console window on Windows\n        });\n\n        // Clean up temporary cookies file\n        if (cookies) {\n            const tempCookiesFile = path.join(__dirname, 'temp_cookies.txt');\n            try {\n                if (fs.existsSync(tempCookiesFile)) {\n                    fs.unlinkSync(tempCookiesFile);\n                }\n            } catch (cleanupError) {\n                // Ignore cleanup errors\n            }\n        }\n\n        if (stderr && !stdout) {\n            throw new Error(`yt-dlp error: ${stderr}`);\n        }\n\n        const streamUrl = stdout.trim();\n        if (!streamUrl || !streamUrl.startsWith('http')) {\n            throw new Error('Invalid streaming URL returned');\n        }\n\n        return streamUrl;\n    } catch (error) {\n        console.error('yt-dlp streaming error:', error.message);\n        throw error;\n    }\n};\n\n/**\n * Get YouTube metadata using yt-dlp for consistency\n */\nconst getYouTubeMetadataWithYtDlp = async (videoId, ytdlpPath, cookies = null) => {\n    let tempCookiesFile = null;\n\n    try {\n        if (!fs.existsSync(ytdlpPath)) {\n            throw new Error(`yt-dlp binary not found at: ${ytdlpPath}`);\n        }\n\n        const url = `https://www.youtube.com/watch?v=${videoId}`;\n\n        // Optimized command arguments for faster metadata extraction\n        const args = [\n            '-J',\n            '--no-playlist',\n            '--no-warnings',\n            '--no-check-certificates',\n            '--skip-download',\n            '--no-call-home',\n            '--no-cache-dir',\n            '--socket-timeout', '15',\n            '--retries', '1',\n            '--fragment-retries', '1',\n            '--extractor-retries', '1'\n        ];\n\n        // Add cookies if provided\n        if (cookies) {\n            tempCookiesFile = path.join(__dirname, `temp_cookies_metadata_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.txt`);\n            try {\n                // Convert cookies to Netscape format if needed\n                const netscapeCookies = convertToNetscapeFormat(cookies);\n                fs.writeFileSync(tempCookiesFile, netscapeCookies);\n                args.push('--cookies', tempCookiesFile);\n            } catch (cookieError) {\n                console.warn('Failed to write cookies for metadata, continuing without:', cookieError.message);\n                tempCookiesFile = null;\n            }\n        }\n\n        const command = `\"${ytdlpPath}\" ${args.join(' ')} \"${url}\"`;\n\n        const { stdout, stderr } = await execAsync(command, {\n            timeout: 30000, // Increased timeout to 30 seconds\n            maxBuffer: 2 * 1024 * 1024, // Increased buffer to 2MB\n            windowsHide: true, // Hide console window on Windows\n            killSignal: 'SIGKILL' // Use SIGKILL instead of SIGTERM for more reliable termination\n        });\n\n        if (stderr && !stdout) {\n            throw new Error(`yt-dlp metadata error: ${stderr}`);\n        }\n\n        if (!stdout || stdout.trim() === '') {\n            throw new Error('yt-dlp returned empty response');\n        }\n\n        let info;\n        try {\n            info = JSON.parse(stdout);\n        } catch (parseError) {\n            throw new Error(`Failed to parse yt-dlp JSON response: ${parseError.message}`);\n        }\n\n        // Validate essential fields\n        if (!info.id && !info.display_id) {\n            throw new Error('Invalid video data: missing video ID');\n        }\n\n        return {\n            id: videoId,\n            title: info.title || info.fulltitle || 'Unknown Title',\n            duration: info.duration ? formatDuration(info.duration) : 'Unknown',\n            thumbnail: info.thumbnail || (info.thumbnails && info.thumbnails[0] ? info.thumbnails[0].url : null),\n            url: `https://www.youtube.com/watch?v=${videoId}`,\n            author: info.uploader || info.channel || info.uploader_id || 'Unknown Artist',\n            views: info.view_count || 0,\n            description: info.description || ''\n        };\n    } catch (error) {\n        console.error('yt-dlp YouTube metadata error:', error);\n        throw error;\n    } finally {\n        // Clean up temporary cookies file\n        if (tempCookiesFile) {\n            try {\n                if (fs.existsSync(tempCookiesFile)) {\n                    fs.unlinkSync(tempCookiesFile);\n                }\n            } catch (cleanupError) {\n                // Ignore cleanup errors\n            }\n        }\n    }\n};\n\n/**\n * Get basic info using yt-dlp (fallback for non-YouTube sites)\n */\nconst getBasicInfo = async (url, ytdlpPath) => {\n    try {\n        if (!fs.existsSync(ytdlpPath)) {\n            throw new Error(`yt-dlp binary not found at: ${ytdlpPath}`);\n        }\n\n        const command = `\"${ytdlpPath}\" -J --flat-playlist --no-warnings \"${url}\"`;\n        const { stdout, stderr } = await execAsync(command, {\n            timeout: 15000, // Reduced timeout\n            maxBuffer: 1024 * 1024, // 1MB buffer\n            windowsHide: true // Hide console window on Windows\n        });\n\n        if (stderr && !stdout) {\n            throw new Error(`yt-dlp info error: ${stderr}`);\n        }\n\n        const info = JSON.parse(stdout);\n\n        return {\n            id: info.id || 'unknown',\n            title: info.title || info.fulltitle || 'Unknown Title',\n            duration: info.duration ? formatDuration(info.duration) : 'Unknown',\n            thumbnail: info.thumbnail || null,\n            url: info.webpage_url || url,\n            author: info.uploader || info.channel || 'Unknown Artist',\n            description: info.description || ''\n        };\n    } catch (error) {\n        console.error('yt-dlp info error:', error);\n        throw error;\n    }\n};\n\n/**\n * Format duration from seconds to readable format\n */\nconst formatDuration = (seconds) => {\n    if (!seconds || isNaN(seconds)) return 'Unknown';\n\n    const hours = Math.floor(seconds / 3600);\n    const minutes = Math.floor((seconds % 3600) / 60);\n    const secs = Math.floor(seconds % 60);\n\n    if (hours > 0) {\n        return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n    } else {\n        return `${minutes}:${secs.toString().padStart(2, '0')}`;\n    }\n};\n\n/**\n * Check if yt-dlp can handle the URL\n */\nconst canExtract = async (url, ytdlpPath) => {\n    try {\n        if (!fs.existsSync(ytdlpPath)) {\n            return false;\n        }\n\n        const command = `\"${ytdlpPath}\" --simulate --quiet \"${url}\"`;\n        await execAsync(command, {\n            timeout: 10000,\n            windowsHide: true // Hide console window on Windows\n        });\n        return true;\n    } catch (error) {\n        return false;\n    }\n};\n\n/**\n * Validate URL format and accessibility\n */\nconst validateUrl = (url) => {\n    if (!url || typeof url !== 'string') {\n        return false;\n    }\n\n    // Check if it's a valid URL\n    if (!isValidUrl(url)) {\n        return false;\n    }\n\n    // Check for common unsupported protocols\n    const unsupportedProtocols = ['file:', 'ftp:', 'mailto:'];\n    const protocol = new URL(url).protocol;\n    if (unsupportedProtocols.includes(protocol)) {\n        return false;\n    }\n\n    return true;\n};\n\n/**\n * Create a standardized track object\n */\nconst createTrackObject = (info, source = 'yt-dlp') => {\n    return {\n        title: info.title || 'Unknown Title',\n        author: info.author || 'Unknown Artist',\n        duration: info.duration || 'Unknown',\n        url: info.url,\n        thumbnail: info.thumbnail || null,\n        source: source,\n        raw: info\n    };\n};\n\n/**\n * Convert browser cookies to Netscape format for yt-dlp\n */\nconst convertToNetscapeFormat = (browserCookies) => {\n    try {\n        // Netscape format header\n        let netscapeCookies = '# Netscape HTTP Cookie File\\n';\n        netscapeCookies += '# This is a generated file! Do not edit.\\n\\n';\n\n        // Split cookies by semicolon and process each one\n        const cookies = browserCookies.split(';').map(cookie => cookie.trim());\n\n        for (const cookie of cookies) {\n            if (!cookie || !cookie.includes('=')) continue;\n\n            const [name, ...valueParts] = cookie.split('=');\n            const value = valueParts.join('='); // Handle values that contain '='\n\n            if (!name || !value) continue;\n\n            // Netscape format: domain, domain_specified, path, secure, expires, name, value\n            // For YouTube cookies, we'll use these defaults:\n            const domain = '.youtube.com';\n            const domainSpecified = 'TRUE';\n            const path = '/';\n            const secure = name.includes('Secure') ? 'TRUE' : 'FALSE';\n            const expires = '0'; // Session cookie\n\n            netscapeCookies += `${domain}\\t${domainSpecified}\\t${path}\\t${secure}\\t${expires}\\t${name.trim()}\\t${value.trim()}\\n`;\n        }\n\n        return netscapeCookies;\n    } catch (error) {\n        // Fallback: return original cookies\n        return browserCookies;\n    }\n};\n\nmodule.exports = {\n    initializeYouTube,\n    isValidUrl,\n    isYouTubeUrl,\n    isYouTubePlaylistUrl,\n    extractYouTubeId,\n    extractYouTubePlaylistId,\n    searchYouTube,\n    getYouTubePlaylist,\n    getYouTubeMetadata,\n    getYouTubeMetadataWithYtDlp,\n    getRelatedTracks,\n    getStreamingUrl,\n    getBasicInfo,\n    formatDuration,\n    canExtract,\n    validateUrl,\n    createTrackObject,\n    convertToNetscapeFormat\n};\n","/**\n * YtDlp-Youtubei Hybrid Extractor\n * Uses yt-dlp for consistent metadata and streaming, with youtubei.js for search/playlists\n * Supports both YouTube search queries and direct URLs from various sites\n *\n * Options:\n * - preferYtdlpMetadata: boolean (default: true) - Whether to prefer yt-dlp for YouTube metadata\n * - ytdlpPath: string - Path to yt-dlp binary\n * - streamQuality: string - Quality selector for streaming\n * - enableYouTubeSearch: boolean (default: true) - Enable YouTube search functionality\n * - enableDirectUrls: boolean (default: true) - Enable direct URL handling\n * - youtubeiOptions: object - Options for youtubei.js (cookies, client)\n */\n\nconst { BaseExtractor, Track, Playlist } = require('discord-player');\nconst {\n    isValidUrl,\n    isYouTubeUrl,\n    isYouTubePlaylistUrl,\n    extractYouTubeId,\n    extractYouTubePlaylistId,\n    searchYouTube,\n    getYouTubePlaylist,\n    getYouTubeMetadata,\n    getYouTubeMetadataWithYtDlp,\n    getRelatedTracks,\n    getStreamingUrl,\n    getBasicInfo,\n    canExtract,\n    validateUrl\n} = require('./utils');\n\nclass YtDlpExtractor extends BaseExtractor {\n    static identifier = 'ytdlp-extractor';\n\n    constructor(context, options) {\n        super(context, options);\n\n        // Configuration\n        this.ytdlpPath = options.ytdlpPath;\n        this.priority = options.priority || 100;\n        this.enableYouTubeSearch = options.enableYouTubeSearch !== false;\n        this.enableDirectUrls = options.enableDirectUrls !== false;\n        this.streamQuality = options.streamQuality || 'bestaudio[ext=m4a]/bestaudio[ext=webm]/bestaudio';\n        this.preferYtdlpMetadata = options.preferYtdlpMetadata !== false; // Default to true for consistency\n\n        // YouTubei options\n        this.youtubeiOptions = {\n            cookies: options.youtubeiOptions?.cookies || null,\n            client: options.youtubeiOptions?.client || null\n        };\n\n        // Supported protocols for direct URLs\n        this.protocols = ['http:', 'https:'];\n\n        this.debug('YtDlp Extractor initialized');\n    }\n\n    /**\n     * Activate the extractor\n     */\n    async activate() {\n        this.debug('Activating YtDlp Extractor');\n\n        // Verify yt-dlp binary exists\n        const fs = require('fs');\n        if (!fs.existsSync(this.ytdlpPath)) {\n            throw new Error(`yt-dlp binary not found at: ${this.ytdlpPath}`);\n        }\n\n        this.debug('YtDlp Extractor activated successfully');\n    }\n\n    /**\n     * Deactivate the extractor\n     */\n    async deactivate() {\n        this.debug('YtDlp Extractor deactivated');\n    }\n\n    /**\n     * Validate if this extractor can handle the query\n     */\n    async validate(query, type) {\n        try {\n            this.debug(`Validating query: ${query}, type: ${type}`);\n\n            // Handle direct URLs\n            if (isValidUrl(query)) {\n                if (!this.enableDirectUrls) {\n                    this.debug('Direct URLs disabled');\n                    return false;\n                }\n\n                // Always handle YouTube URLs (including playlists) if YouTube search is enabled\n                if (isYouTubeUrl(query) && this.enableYouTubeSearch) {\n                    this.debug('YouTube URL detected and enabled');\n                    return true;\n                }\n\n                // Check if yt-dlp can handle other URLs (with timeout)\n                this.debug('Checking if yt-dlp can extract URL');\n                const canHandle = await canExtract(query, this.ytdlpPath);\n                return canHandle;\n            }\n\n            // Handle search queries - accept all if YouTube search is enabled\n            if (this.enableYouTubeSearch) {\n                this.debug('Search query accepted');\n                return true;\n            }\n\n            this.debug('Query not supported');\n            return false;\n        } catch (error) {\n            this.debug(`Validation error: ${error.message}`);\n            return false;\n        }\n    }\n\n    /**\n     * Handle the query and return track information\n     */\n    async handle(query, context) {\n        try {\n            this.debug(`Handling query: ${query}`);\n            \n            if (isValidUrl(query)) {\n                return await this.handleDirectUrl(query, context);\n            } else {\n                return await this.handleSearchQuery(query, context);\n            }\n        } catch (error) {\n            this.debug(`Handle error: ${error.message}`);\n            return this.createResponse(null, []);\n        }\n    }\n\n    /**\n     * Handle direct URL queries\n     */\n    async handleDirectUrl(url, context) {\n        try {\n            if (!validateUrl(url)) {\n                throw new Error('Invalid URL format');\n            }\n\n            if (isYouTubeUrl(url)) {\n                // Check if it's a playlist URL\n                if (isYouTubePlaylistUrl(url)) {\n                    return await this.handleYouTubePlaylist(url, context);\n                }\n\n                // Handle single video\n                const videoId = extractYouTubeId(url);\n                if (!videoId) {\n                    throw new Error('Could not extract YouTube video ID');\n                }\n\n                // Get YouTube metadata with configurable preference and fallback\n                let trackInfo;\n                let metadataSource;\n\n                if (this.preferYtdlpMetadata) {\n                    // Try yt-dlp first, fallback to youtubei.js\n                    metadataSource = 'yt-dlp';\n                    try {\n                        const cookies = this.youtubeiOptions?.cookies || null;\n                        this.debug(`Attempting to get metadata using yt-dlp for video: ${videoId}`);\n                        trackInfo = await getYouTubeMetadataWithYtDlp(videoId, this.ytdlpPath, cookies);\n                        this.debug(`Successfully got metadata using yt-dlp`);\n                    } catch (ytdlpError) {\n                        this.debug(`yt-dlp metadata failed: ${ytdlpError.message}`);\n                        this.debug(`Falling back to youtubei.js for metadata`);\n                        metadataSource = 'youtubei.js';\n\n                        try {\n                            trackInfo = await getYouTubeMetadata(videoId, this.youtubeiOptions);\n                            if (trackInfo) {\n                                this.debug(`Successfully got metadata using youtubei.js fallback`);\n                            }\n                        } catch (youtubeiError) {\n                            this.debug(`youtubei.js metadata also failed: ${youtubeiError.message}`);\n                            trackInfo = null;\n                        }\n                    }\n                } else {\n                    // Try youtubei.js first, fallback to yt-dlp\n                    metadataSource = 'youtubei.js';\n                    try {\n                        this.debug(`Attempting to get metadata using youtubei.js for video: ${videoId}`);\n                        trackInfo = await getYouTubeMetadata(videoId, this.youtubeiOptions);\n                        if (trackInfo) {\n                            this.debug(`Successfully got metadata using youtubei.js`);\n                        } else {\n                            throw new Error('youtubei.js returned null');\n                        }\n                    } catch (youtubeiError) {\n                        this.debug(`youtubei.js metadata failed: ${youtubeiError.message}`);\n                        this.debug(`Falling back to yt-dlp for metadata`);\n                        metadataSource = 'yt-dlp';\n\n                        try {\n                            const cookies = this.youtubeiOptions?.cookies || null;\n                            trackInfo = await getYouTubeMetadataWithYtDlp(videoId, this.ytdlpPath, cookies);\n                            if (trackInfo) {\n                                this.debug(`Successfully got metadata using yt-dlp fallback`);\n                            }\n                        } catch (ytdlpError) {\n                            this.debug(`yt-dlp metadata also failed: ${ytdlpError.message}`);\n                            trackInfo = null;\n                        }\n                    }\n                }\n\n                if (!trackInfo) {\n                    throw new Error('Could not get YouTube metadata from either yt-dlp or youtubei.js');\n                }\n\n                // Add metadata source info to raw data\n                trackInfo.metadataSource = metadataSource;\n\n                const track = new Track(this, {\n                    title: trackInfo.title,\n                    author: trackInfo.author,\n                    duration: trackInfo.duration,\n                    url: trackInfo.url,\n                    thumbnail: trackInfo.thumbnail,\n                    source: 'ytdlp-extractor',\n                    raw: trackInfo,\n                    requestedBy: context.requestedBy,\n                    queryType: 'arbitrary'\n                });\n\n                return this.createResponse(null, [track]);\n            } else {\n                // Use yt-dlp for other sites\n                const trackInfo = await getBasicInfo(url, this.ytdlpPath);\n\n                const track = new Track(this, {\n                    title: trackInfo.title,\n                    author: trackInfo.author,\n                    duration: trackInfo.duration,\n                    url: trackInfo.url,\n                    thumbnail: trackInfo.thumbnail,\n                    source: 'ytdlp-extractor',\n                    raw: trackInfo,\n                    requestedBy: context.requestedBy,\n                    queryType: 'arbitrary'\n                });\n\n                return this.createResponse(null, [track]);\n            }\n        } catch (error) {\n            this.debug(`Direct URL error: ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Handle YouTube playlist URLs\n     */\n    async handleYouTubePlaylist(url, context) {\n        try {\n            const playlistId = extractYouTubePlaylistId(url);\n            if (!playlistId) {\n                throw new Error('Could not extract playlist ID');\n            }\n\n            const playlistInfo = await getYouTubePlaylist(playlistId, this.youtubeiOptions);\n            if (!playlistInfo || !playlistInfo.tracks || playlistInfo.tracks.length === 0) {\n                throw new Error('Could not get playlist information or playlist is empty');\n            }\n\n            // Create playlist object\n            const playlist = new Playlist(this, {\n                title: playlistInfo.title,\n                description: playlistInfo.description,\n                thumbnail: playlistInfo.thumbnail,\n                type: 'playlist',\n                source: 'ytdlp-extractor',\n                author: {\n                    name: playlistInfo.author,\n                    url: null\n                },\n                tracks: [],\n                id: playlistId,\n                url: playlistInfo.url,\n                rawPlaylist: playlistInfo\n            });\n\n            // Create tracks\n            const tracks = playlistInfo.tracks.map(trackData => {\n                const track = new Track(this, {\n                    title: trackData.title,\n                    author: trackData.author,\n                    duration: trackData.duration,\n                    url: trackData.url,\n                    thumbnail: trackData.thumbnail,\n                    source: 'ytdlp-extractor',\n                    raw: trackData,\n                    requestedBy: context.requestedBy,\n                    queryType: 'arbitrary',\n                    playlist: playlist\n                });\n                return track;\n            });\n\n            playlist.tracks = tracks;\n            return this.createResponse(playlist, tracks);\n        } catch (error) {\n            this.debug(`YouTube playlist error: ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Handle search queries (YouTube only)\n     */\n    async handleSearchQuery(query, context) {\n        try {\n            if (!this.enableYouTubeSearch) {\n                throw new Error('YouTube search is disabled');\n            }\n\n            const searchResults = await searchYouTube(query, 1, this.youtubeiOptions);\n            if (!searchResults || searchResults.length === 0) {\n                return this.createResponse(null, []);\n            }\n\n            const result = searchResults[0];\n\n            // Create track with YouTube URL that will be passed to yt-dlp for streaming\n            const track = new Track(this, {\n                title: result.title,\n                author: result.author,\n                duration: result.duration,\n                url: result.url, // This YouTube URL will be used by yt-dlp for streaming\n                thumbnail: result.thumbnail,\n                source: 'ytdlp-extractor',\n                raw: {\n                    ...result,\n                    originalQuery: query,\n                    searchMethod: 'youtubei'\n                },\n                requestedBy: context.requestedBy,\n                queryType: 'youtubeSearch'\n            });\n\n            return this.createResponse(null, [track]);\n        } catch (error) {\n            this.debug(`Search query error: ${error.message}`);\n            // Return empty response instead of throwing to prevent crashes\n            return this.createResponse(null, []);\n        }\n    }\n\n    /**\n     * Get streaming URL for a track\n     */\n    async stream(info) {\n        try {\n            this.debug(`Getting stream for: ${info.title || info.raw?.title || 'Unknown'}`);\n\n            // Use the URL from the track info\n            const url = info.url || info.raw?.url;\n            if (!url) {\n                throw new Error('No URL found in track info');\n            }\n\n            // Get fresh streaming URL each time to avoid expiration\n            // Pass cookies to yt-dlp for authentication if available\n            const cookies = this.youtubeiOptions?.cookies || null;\n            const streamUrl = await getStreamingUrl(url, this.ytdlpPath, this.streamQuality, cookies);\n\n            if (!streamUrl || !streamUrl.startsWith('http')) {\n                throw new Error('Invalid streaming URL returned');\n            }\n\n            this.debug(`Stream URL obtained successfully`);\n\n            // Return the stream URL directly - discord-player will handle it\n            return streamUrl;\n        } catch (error) {\n            this.debug(`Stream error: ${error.message}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Get related tracks for autoplay functionality\n     */\n    async getRelatedTracks(track, history) {\n        try {\n            this.debug(`Getting related tracks for: ${track.title}`);\n\n            // Only work with YouTube tracks for now\n            if (!isYouTubeUrl(track.url)) {\n                this.debug('Non-YouTube track, no related tracks available');\n                return this.createResponse(null, []);\n            }\n\n            const videoId = extractYouTubeId(track.url);\n            if (!videoId) {\n                this.debug('Could not extract video ID');\n                return this.createResponse(null, []);\n            }\n\n            // Get related tracks using YouTube's recommendation system\n            let relatedTracks = await getRelatedTracks(videoId, this.youtubeiOptions, 10);\n\n            // If no related tracks found, try search-based approach\n            if (!relatedTracks || relatedTracks.length === 0) {\n                this.debug('No related tracks from YouTube API, trying search-based approach');\n\n                // Use track author for search\n                if (track.author && track.author !== 'Unknown Artist') {\n                    const searchQuery = `${track.author} music`;\n                    relatedTracks = await searchYouTube(searchQuery, 5, this.youtubeiOptions);\n                }\n            }\n\n            // Filter out tracks that are already in history\n            const historyUrls = new Set(\n                history.tracks.toArray().map(t => t.url)\n            );\n\n            const filteredTracks = relatedTracks.filter(trackData =>\n                !historyUrls.has(trackData.url) && trackData.url !== track.url\n            );\n\n            if (filteredTracks.length === 0) {\n                this.debug('No new related tracks found after filtering');\n                return this.createResponse(null, []);\n            }\n\n            // Create Track objects\n            const tracks = filteredTracks.slice(0, 5).map(trackData => {\n                const relatedTrack = new Track(this, {\n                    title: trackData.title,\n                    author: trackData.author,\n                    duration: trackData.duration,\n                    url: trackData.url,\n                    thumbnail: trackData.thumbnail,\n                    source: 'ytdlp-extractor',\n                    raw: {\n                        ...trackData,\n                        relatedTo: track.url,\n                        autoplay: true\n                    },\n                    requestedBy: track.requestedBy,\n                    queryType: 'autoplay'\n                });\n                return relatedTrack;\n            });\n\n            this.debug(`Found ${tracks.length} related tracks`);\n            return this.createResponse(null, tracks);\n        } catch (error) {\n            this.debug(`Related tracks error: ${error.message}`);\n            return this.createResponse(null, []);\n        }\n    }\n\n    /**\n     * Bridge functionality for other extractors\n     */\n    async bridge(track, sourceExtractor) {\n        try {\n            // If the source extractor is not this one, try to get stream\n            if (sourceExtractor?.identifier !== this.identifier) {\n                const streamUrl = await this.stream(track);\n                return { stream: streamUrl, type: 'arbitrary' };\n            }\n\n            return null;\n        } catch (error) {\n            this.debug(`Bridge error: ${error.message}`);\n            return null;\n        }\n    }\n\n    /**\n     * Create bridge query for track search\n     */\n    createBridgeQuery(track) {\n        return `${track.author} - ${track.title}`;\n    }\n}\n\nmodule.exports = { YtDlpExtractor };\n"],"mappings":"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","names":["yt","tracks","_a","_b","_c","_d","_e","_f","_g","_h","path"]}