mikmc5/bitsa
0
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 };