Update index.js
Browse files
index.js
CHANGED
|
@@ -129,24 +129,12 @@ function processStreams(streams, type) {
|
|
| 129 |
const maxSize = type === 'series' ? MAX_SIZE_GB_SERIES : MAX_SIZE_GB_MOVIE;
|
| 130 |
|
| 131 |
const filtered = streams.filter(s => {
|
| 132 |
-
if (!s.infoHash && !s.url)
|
| 133 |
-
|
| 134 |
-
return false;
|
| 135 |
-
}
|
| 136 |
-
if (s._provider && !ALLOWED_PROVIDERS.includes(s._provider.toLowerCase())) {
|
| 137 |
-
console.log(`[processStreams] Filtering out provider: ${s._provider}`);
|
| 138 |
-
return false;
|
| 139 |
-
}
|
| 140 |
const q = s._quality || getQuality(s.title || s.name || '');
|
| 141 |
-
if (!q || !ALLOWED_QUALITIES.includes(q))
|
| 142 |
-
console.log(`[processStreams] Filtering out quality: ${q}`);
|
| 143 |
-
return false;
|
| 144 |
-
}
|
| 145 |
const sizeGB = s._sizeGB ?? getSizeGB(s);
|
| 146 |
-
if (sizeGB !== null && sizeGB > maxSize)
|
| 147 |
-
console.log(`[processStreams] Filtering out oversized: ${sizeGB}GB > ${maxSize}GB`);
|
| 148 |
-
return false;
|
| 149 |
-
}
|
| 150 |
return true;
|
| 151 |
});
|
| 152 |
|
|
@@ -156,10 +144,7 @@ function processStreams(streams, type) {
|
|
| 156 |
const unique = filtered.filter(s => {
|
| 157 |
const key = (s.infoHash || '').toLowerCase();
|
| 158 |
if (!key) return true;
|
| 159 |
-
if (seen.has(key))
|
| 160 |
-
console.log(`[processStreams] Deduping: ${key}`);
|
| 161 |
-
return false;
|
| 162 |
-
}
|
| 163 |
seen.add(key);
|
| 164 |
return true;
|
| 165 |
});
|
|
@@ -283,7 +268,7 @@ async function scrapeSubsPlease(title, season, episode) {
|
|
| 283 |
}
|
| 284 |
|
| 285 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 286 |
-
// APIBAY SCRAPER (
|
| 287 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 288 |
async function scrapeAPIBay(title, year, season, episode) {
|
| 289 |
if (!title) return [];
|
|
@@ -296,10 +281,25 @@ async function scrapeAPIBay(title, year, season, episode) {
|
|
| 296 |
}
|
| 297 |
|
| 298 |
console.log(`[APIBay] π Searching: ${query}`);
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
|
| 304 |
console.log(`[APIBay] π‘ Response type: ${typeof data}, is array: ${Array.isArray(data)}`);
|
| 305 |
|
|
@@ -309,7 +309,7 @@ async function scrapeAPIBay(title, year, season, episode) {
|
|
| 309 |
}
|
| 310 |
|
| 311 |
const streams = [];
|
| 312 |
-
for (const item of data) {
|
| 313 |
if (!item.info_hash || !item.name) continue;
|
| 314 |
|
| 315 |
const magnet = `magnet:?xt=urn:btih:${item.info_hash.toLowerCase()}&dn=${encodeURIComponent(item.name)}${TR}`;
|
|
@@ -339,7 +339,7 @@ async function scrapeAPIBay(title, year, season, episode) {
|
|
| 339 |
}
|
| 340 |
|
| 341 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 342 |
-
// TORRENTS.CSV SCRAPER
|
| 343 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 344 |
async function scrapeTorrentsCSV(title, year, season, episode) {
|
| 345 |
if (!title) return [];
|
|
@@ -353,23 +353,35 @@ async function scrapeTorrentsCSV(title, year, season, episode) {
|
|
| 353 |
|
| 354 |
console.log(`[Torrents.csv] π Searching: ${query}`);
|
| 355 |
const { data } = await axios.get(
|
| 356 |
-
`https://torrents-csv.com/service/search?q=${encodeURIComponent(query)}`,
|
| 357 |
-
{ timeout:
|
| 358 |
);
|
| 359 |
|
| 360 |
-
console.log(`[Torrents.csv] π‘ Response type: ${typeof data}
|
| 361 |
|
| 362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
console.log(`[Torrents.csv] β No results or invalid format`);
|
| 364 |
return [];
|
| 365 |
}
|
| 366 |
|
| 367 |
const streams = [];
|
| 368 |
-
for (const item of
|
| 369 |
if (!item.infohash || !item.name) continue;
|
| 370 |
|
| 371 |
const magnet = `magnet:?xt=urn:btih:${item.infohash.toLowerCase()}&dn=${encodeURIComponent(item.name)}${TR}`;
|
| 372 |
-
const sizeGB = item.size ? item.size / 1073741824 : null;
|
| 373 |
const sizeStr = sizeGB ? sizeGB.toFixed(2) + ' GB' : 'N/A';
|
| 374 |
const langLine = getLangLine(item.name || '');
|
| 375 |
const seeders = item.seeders || 0;
|
|
@@ -574,7 +586,5 @@ app.get('/', (req, res) => {
|
|
| 574 |
app.listen(PORT, '0.0.0.0', () => {
|
| 575 |
console.log(`\n${'='.repeat(70)}`);
|
| 576 |
console.log(`β
VanStreams+ Running on port ${PORT}`);
|
| 577 |
-
console.log(`π http://localhost:${PORT}/`);
|
| 578 |
-
console.log(`π Diagnostics: http://localhost:${PORT}/diag/series/tt1234567:1:1`);
|
| 579 |
console.log(`${'='.repeat(70)}\n`);
|
| 580 |
});
|
|
|
|
| 129 |
const maxSize = type === 'series' ? MAX_SIZE_GB_SERIES : MAX_SIZE_GB_MOVIE;
|
| 130 |
|
| 131 |
const filtered = streams.filter(s => {
|
| 132 |
+
if (!s.infoHash && !s.url) return false;
|
| 133 |
+
if (s._provider && !ALLOWED_PROVIDERS.includes(s._provider.toLowerCase())) return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
const q = s._quality || getQuality(s.title || s.name || '');
|
| 135 |
+
if (!q || !ALLOWED_QUALITIES.includes(q)) return false;
|
|
|
|
|
|
|
|
|
|
| 136 |
const sizeGB = s._sizeGB ?? getSizeGB(s);
|
| 137 |
+
if (sizeGB !== null && sizeGB > maxSize) return false;
|
|
|
|
|
|
|
|
|
|
| 138 |
return true;
|
| 139 |
});
|
| 140 |
|
|
|
|
| 144 |
const unique = filtered.filter(s => {
|
| 145 |
const key = (s.infoHash || '').toLowerCase();
|
| 146 |
if (!key) return true;
|
| 147 |
+
if (seen.has(key)) return false;
|
|
|
|
|
|
|
|
|
|
| 148 |
seen.add(key);
|
| 149 |
return true;
|
| 150 |
});
|
|
|
|
| 268 |
}
|
| 269 |
|
| 270 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 271 |
+
// APIBAY SCRAPER (WITH RETRY & PROXY)
|
| 272 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 273 |
async function scrapeAPIBay(title, year, season, episode) {
|
| 274 |
if (!title) return [];
|
|
|
|
| 281 |
}
|
| 282 |
|
| 283 |
console.log(`[APIBay] π Searching: ${query}`);
|
| 284 |
+
|
| 285 |
+
// Try direct first, then with proxy if 403
|
| 286 |
+
let data;
|
| 287 |
+
try {
|
| 288 |
+
const res = await axios.get(
|
| 289 |
+
`https://apibay.org/q.php?q=${encodeURIComponent(query)}&cat=208`,
|
| 290 |
+
{ timeout: 8000, headers: { 'User-Agent': UA } }
|
| 291 |
+
);
|
| 292 |
+
data = res.data;
|
| 293 |
+
} catch (e) {
|
| 294 |
+
if (e.response?.status === 403) {
|
| 295 |
+
console.log(`[APIBay] 403 - Trying with proxy...`);
|
| 296 |
+
const proxyUrl = `https://corsproxy.io/?url=${encodeURIComponent(`https://apibay.org/q.php?q=${encodeURIComponent(query)}&cat=208`)}`;
|
| 297 |
+
const res = await axios.get(proxyUrl, { timeout: 10000, headers: { 'User-Agent': UA } });
|
| 298 |
+
data = res.data;
|
| 299 |
+
} else {
|
| 300 |
+
throw e;
|
| 301 |
+
}
|
| 302 |
+
}
|
| 303 |
|
| 304 |
console.log(`[APIBay] π‘ Response type: ${typeof data}, is array: ${Array.isArray(data)}`);
|
| 305 |
|
|
|
|
| 309 |
}
|
| 310 |
|
| 311 |
const streams = [];
|
| 312 |
+
for (const item of data.slice(0, 15)) {
|
| 313 |
if (!item.info_hash || !item.name) continue;
|
| 314 |
|
| 315 |
const magnet = `magnet:?xt=urn:btih:${item.info_hash.toLowerCase()}&dn=${encodeURIComponent(item.name)}${TR}`;
|
|
|
|
| 339 |
}
|
| 340 |
|
| 341 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 342 |
+
// TORRENTS.CSV SCRAPER (FIXED FOR NEW API FORMAT)
|
| 343 |
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 344 |
async function scrapeTorrentsCSV(title, year, season, episode) {
|
| 345 |
if (!title) return [];
|
|
|
|
| 353 |
|
| 354 |
console.log(`[Torrents.csv] π Searching: ${query}`);
|
| 355 |
const { data } = await axios.get(
|
| 356 |
+
`https://torrents-csv.com/service/search?q=${encodeURIComponent(query)}&limit=15`,
|
| 357 |
+
{ timeout: 8000, headers: { 'User-Agent': UA } }
|
| 358 |
);
|
| 359 |
|
| 360 |
+
console.log(`[Torrents.csv] π‘ Response type: ${typeof data}`);
|
| 361 |
|
| 362 |
+
// Handle different response formats
|
| 363 |
+
let torrents = [];
|
| 364 |
+
if (Array.isArray(data)) {
|
| 365 |
+
torrents = data;
|
| 366 |
+
} else if (data && typeof data === 'object' && data.torrents && Array.isArray(data.torrents)) {
|
| 367 |
+
torrents = data.torrents;
|
| 368 |
+
} else if (data && typeof data === 'object' && data.results && Array.isArray(data.results)) {
|
| 369 |
+
torrents = data.results;
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
console.log(`[Torrents.csv] Parsed torrents array: ${torrents.length} items`);
|
| 373 |
+
|
| 374 |
+
if (!torrents || torrents.length === 0) {
|
| 375 |
console.log(`[Torrents.csv] β No results or invalid format`);
|
| 376 |
return [];
|
| 377 |
}
|
| 378 |
|
| 379 |
const streams = [];
|
| 380 |
+
for (const item of torrents) {
|
| 381 |
if (!item.infohash || !item.name) continue;
|
| 382 |
|
| 383 |
const magnet = `magnet:?xt=urn:btih:${item.infohash.toLowerCase()}&dn=${encodeURIComponent(item.name)}${TR}`;
|
| 384 |
+
const sizeGB = item.size_bytes ? item.size_bytes / 1073741824 : (item.size ? item.size / 1073741824 : null);
|
| 385 |
const sizeStr = sizeGB ? sizeGB.toFixed(2) + ' GB' : 'N/A';
|
| 386 |
const langLine = getLangLine(item.name || '');
|
| 387 |
const seeders = item.seeders || 0;
|
|
|
|
| 586 |
app.listen(PORT, '0.0.0.0', () => {
|
| 587 |
console.log(`\n${'='.repeat(70)}`);
|
| 588 |
console.log(`β
VanStreams+ Running on port ${PORT}`);
|
|
|
|
|
|
|
| 589 |
console.log(`${'='.repeat(70)}\n`);
|
| 590 |
});
|