CoolFace
Apppublic

mikmc5/bitsa

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
solid.js168 linesDownload Raw Back to root
1const SITE_CONFIG = {2    baseUrl: 'https://bitsearch.to',3    fallbackUrls: [4        'https://bitsearch.st',5        'https://bitsearch.eu'6    ]7};8 9// Helper function to fetch Cinemeta metadata (optional, for movie details)10async function getCinemetaMetadata(imdbId) {11    try {12        if (!imdbId.startsWith('tt')) {13            return null;14        }15 16        console.log(`\n๐ŸŽฌ Fetching Cinemeta data for ${imdbId}`);17        const response = await fetch(`https://v3-cinemeta.strem.io/meta/movie/${imdbId}.json`);18        if (!response.ok) throw new Error('Failed to fetch from Cinemeta');19        const data = await response.json();20        console.log('โœ… Found:', data.meta.name);21        return data;22    } catch (error) {23        console.error('โŒ Cinemeta error:', error);24        return null;25    }26}27 28// Timeout function to prevent hanging requests29async function fetchWithTimeout(url, options = {}, timeout = 30000) {30    const controller = new AbortController();31    const timeoutId = setTimeout(() => controller.abort(), timeout);32 33    try {34        const response = await fetch(url, {35            ...options,36            signal: controller.signal,37            headers: {38                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',39                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9',40                'Accept-Language': 'en-US,en;q=0.9',41                ...options.headers42            }43        });44        clearTimeout(timeoutId);45        return response;46    } catch (error) {47        clearTimeout(timeoutId);48        throw error;49    }50}51 52// Parse the file size from a string (e.g., "1.2 GB")53function parseSize(sizeStr) {54    if (!sizeStr) return 0;55    const match = sizeStr.match(/([\d.]+)\s*(B|KB|MB|GB|TB)/i);56    if (!match) return 0;57 58    const [, value, unit] = match;59    const multipliers = {60        'B': 1,61        'KB': 1024,62        'MB': 1024 * 1024,63        'GB': 1024 * 1024 * 1024,64        'TB': 1024 * 1024 * 1024 * 102465    };66 67    return parseFloat(value) * multipliers[unit.toUpperCase()];68}69 70// Parse search results from HTML71function parseSearchResults(html) {72    if (!html) {73        console.log('No HTML content to parse');74        return [];75    }76 77    const results = [];78    const searchResults = html.match(/<li class="card search-result my-2">[\s\S]*?<\/li>/g) || [];79 80    for (const result of searchResults) {81        try {82            const titleMatch = result.match(/class="title w-100 truncate"><a[^>]*>([^<]+)<\/a>/);83            const magnetMatch = result.match(/href="(magnet:[^"]+)"/);84            const sizeMatch = result.match(/alt="Size"[^>]*>([^<]+)<\/div>/);85            const seedersMatch = result.match(/alt="Seeder"[^>]*>[^<]*<font[^>]*>(\d+)<\/font>/);86            const leechersMatch = result.match(/alt="Leecher"[^>]*>[^<]*<font[^>]*>(\d+)<\/font>/);87            const categoryMatch = result.match(/class="category">([^<]+)<\/a>/);88            const dateMatch = result.match(/alt="Date"[^>]*>([^<]+)<\/div>/);89 90            if (titleMatch && magnetMatch) {91                const title = titleMatch[1].trim();92                const quality = extractQuality(title);93                const size = sizeMatch ? sizeMatch[1].trim() : 'Unknown';94 95                results.push({96                    title,97                    magnetLink: magnetMatch[1],98                    quality,99                    size,100                    source: 'BitSearch',101                    seeders: seedersMatch ? parseInt(seedersMatch[1]) : 0,102                    leechers: leechersMatch ? parseInt(leechersMatch[1]) : 0,103                    category: categoryMatch ? categoryMatch[1].trim() : 'Unknown',104                    uploadDate: dateMatch ? dateMatch[1].trim() : '',105                    mainFileSize: parseSize(size)106                });107            }108        } catch (error) {109            console.error('Error parsing result:', error);110        }111    }112 113    return results;114}115 116// Extract the video quality from the title (e.g., "1080p", "4k")117function extractQuality(title) {118    if (!title) return '';119    const qualityMatch = title.match(/\b(2160p|1080p|720p|4k|uhd|hdr|dv|blu[- ]?ray)\b/i);120    return qualityMatch ? qualityMatch[1].toLowerCase().replace(/[- ]/g, '') : '';121}122 123// Search for torrents while ignoring the year in the search query124async function searchTorrents(searchQuery, type = 'movie') {125    if (!searchQuery) {126        console.log('No search query provided');127        return [];128    }129 130    // Step 1: Remove year-like patterns (e.g., "2021", "2022") from the search query131    const queryWithoutYear = searchQuery.replace(/\s*(\d{4})\s*/g, '').trim();132 133    console.log('\n๐Ÿ”„ Searching BitSearch for:', queryWithoutYear);134    135    try {136        const formattedQuery = queryWithoutYear.replace(/\s+/g, '+').toLowerCase();137        const url = `${SITE_CONFIG.baseUrl}/search?q=${encodeURIComponent(formattedQuery)}&sort=size&category=1&subcat=2&order=desc`;138 139        console.log('Request URL:', url);140 141        const response = await fetchWithTimeout(url);142        if (!response.ok) {143            throw new Error(`Search request failed: ${response.status}`);144        }145 146        const html = await response.text();147        const results = parseSearchResults(html);148        console.log(`โœ… Found ${results.length} raw results`);149 150        // Sort results based on quality and seeders151        results.sort((a, b) => {152            const qualityOrder = { '2160p': 5, '4k': 5, 'hdr': 4, 'dv': 4, '1080p': 3, '720p': 2 };153            const aQuality = qualityOrder[a.quality] || 0;154            const bQuality = qualityOrder[b.quality] || 0;155            156            if (aQuality !== bQuality) {157                return bQuality - aQuality;158            }159            return b.seeders - a.seeders;160        });161 162        return results;163    } catch (error) {164        console.error('โŒ Error searching BitSearch:', error);165        return [];166    }167}168export { searchTorrents };