calculus / src /yourbittorrent.js
no1b4me's picture
Upload 15 files
ea5d04f verified
raw
history blame
8.38 kB
import readTorrent from 'read-torrent';
import { promisify } from 'util';
const readTorrentPromise = promisify(readTorrent);
const SITE_CONFIG = {
baseUrl: 'https://yourbittorrent.com',
fallbackUrls: [
'https://yourbittorrent2.com'
]
};
async function getCinemetaMetadata(imdbId) {
try {
console.log(`\n🎬 Fetching Cinemeta data for ${imdbId}`);
const response = await fetch(`https://v3-cinemeta.strem.io/meta/movie/${imdbId}.json`);
if (!response.ok) throw new Error('Failed to fetch from Cinemeta');
const data = await response.json();
console.log('✅ Found:', data.meta.name);
return data;
} catch (error) {
console.error('❌ Cinemeta error:', error);
return null;
}
}
async function fetchWithTimeout(url, options = {}, timeout = 30000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
...options,
signal: controller.signal
});
clearTimeout(timeoutId);
return response;
} catch (error) {
clearTimeout(timeoutId);
throw error;
}
}
async function downloadAndParseTorrent(url) {
try {
console.log('Downloading torrent from:', url);
const options = {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': '*/*',
}
};
const torrentInfo = await readTorrentPromise(url, options);
// Check if any of the files are video files
const hasVideoFiles = torrentInfo.files?.some(file => {
const filePath = Array.isArray(file.path) ? file.path.join('/') : file.path;
return /\.(mp4|mkv|avi|mov|wmv)$/i.test(filePath);
});
if (!hasVideoFiles) {
console.log('No video files found');
return null;
}
// Find main video file
const videoFiles = torrentInfo.files.filter(file => {
const filePath = Array.isArray(file.path) ? file.path.join('/') : file.path;
return /\.(mp4|mkv|avi|mov|wmv)$/i.test(filePath);
}).sort((a, b) => b.length - a.length);
const mainFile = videoFiles[0];
const mainFilePath = Array.isArray(mainFile.path) ? mainFile.path.join('/') : mainFile.path;
const magnetUri = `magnet:?xt=urn:btih:${torrentInfo.infoHash}` +
`&dn=${encodeURIComponent(torrentInfo.name)}` +
(torrentInfo.announce ? torrentInfo.announce.map(tr => `&tr=${encodeURIComponent(tr)}`).join('') : '');
return {
magnetLink: magnetUri,
filename: mainFilePath,
torrentName: torrentInfo.name,
infoHash: torrentInfo.infoHash,
mainFileSize: mainFile.length
};
} catch (error) {
console.error('Error downloading/parsing torrent:', error);
return null;
}
}
async function searchTorrents(imdbId) {
console.log('\n🔄 Searching YourBittorrent for IMDB:', imdbId);
try {
const metadata = await getCinemetaMetadata(imdbId);
if (!metadata?.meta) {
throw new Error('Failed to get movie metadata');
}
const movieName = metadata.meta.name.replace(/[&]/g, '').trim();
const searchQuery = `${movieName} ${new Date(metadata.meta.released).getFullYear()}`;
console.log('Searching for:', searchQuery);
const formattedQuery = searchQuery
.replace(/[\\s]+/g, '-')
.toLowerCase();
const url = `${SITE_CONFIG.baseUrl}/?v=&c=movies&q=${encodeURIComponent(formattedQuery)}`;
console.log('Request URL:', url);
const response = await fetchWithTimeout(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9',
'Accept-Language': 'en-US,en;q=0.9'
}
});
if (!response.ok) {
throw new Error(`Search request failed: ${response.status}`);
}
const html = await response.text();
const results = parseSearchResults(html);
console.log(`Found ${results.length} raw results`);
// Process each result through read-torrent
const streams = await Promise.all(results.map(async result => {
try {
if (!result.magnetLink) return null;
const torrentInfo = await downloadAndParseTorrent(result.magnetLink);
if (!torrentInfo) return null;
return {
magnetLink: torrentInfo.magnetLink,
filename: torrentInfo.filename,
websiteTitle: result.title,
quality: extractQuality(result.title),
size: result.size,
source: 'YourBittorrent',
seeders: parseInt(result.seeders) || 0,
leechers: parseInt(result.leechers) || 0,
mainFileSize: torrentInfo.mainFileSize
};
} catch (error) {
console.error('Error processing result:', error);
return null;
}
}));
const validStreams = streams.filter(Boolean);
const movieYear = new Date(metadata.meta.released).getFullYear().toString();
const searchTerms = movieName.toLowerCase().split(' ');
const filteredStreams = validStreams.filter(stream => {
const streamTitle = stream.websiteTitle.toLowerCase();
const hasYear = streamTitle.includes(movieYear);
const hasAllTerms = searchTerms.every(term =>
streamTitle.includes(term.toLowerCase())
);
return hasYear && hasAllTerms;
});
console.log(`Found ${filteredStreams.length} relevant streams after filtering`);
filteredStreams.sort((a, b) => {
const qualityOrder = { '2160p': 4, '4k': 4, '1080p': 3, '720p': 2 };
const qualityDiff = (qualityOrder[b.quality] || 0) - (qualityOrder[a.quality] || 0);
if (qualityDiff === 0) {
return b.seeders - a.seeders;
}
return qualityDiff;
});
return filteredStreams;
} catch (error) {
console.error('❌ Error searching YourBittorrent:', error);
for (const fallbackUrl of SITE_CONFIG.fallbackUrls) {
try {
SITE_CONFIG.baseUrl = fallbackUrl;
return await searchTorrents(imdbId);
} catch (fallbackError) {
console.error(`Fallback ${fallbackUrl} also failed:`, fallbackError);
}
}
return [];
}
}
function parseSearchResults(html) {
const results = [];
const rows = html.match(/<tr class="table-default">[\s\S]*?<\/tr>/g) || [];
for (const row of rows) {
try {
const titleMatch = row.match(/href="\/torrent\/.*?">(.*?)<\/a>/);
const sizeMatch = row.match(/<td.*?>\s*([\d.]+\s*[KMGT]B)\s*<\/td>/);
const seedersMatch = row.match(/<td.*?>\s*(\d+)\s*<\/td>/);
const leechersMatch = row.match(/<td.*?>\s*(\d+)\s*<\/td>/);
if (titleMatch) {
const downloadId = row.match(/\/torrent\/(\d+)\//)?.[1];
results.push({
title: titleMatch[1],
size: sizeMatch?.[1] || 'Unknown',
seeders: seedersMatch?.[1] || '0',
leechers: leechersMatch?.[1] || '0',
magnetLink: downloadId ?
`${SITE_CONFIG.baseUrl}/down/${downloadId}.torrent` :
null
});
}
} catch (error) {
console.error('Error parsing result row:', error);
}
}
return results;
}
function extractQuality(title) {
const qualityMatch = title.match(/\b(2160p|1080p|720p|4k|uhd)\b/i);
return qualityMatch ? qualityMatch[1].toLowerCase() : '';
}
export { searchTorrents };