Update index.js
Browse files
index.js
CHANGED
|
@@ -5,8 +5,7 @@ const PORT = process.env.PORT || 7860;
|
|
| 5 |
|
| 6 |
const MAX_MOVIE_SIZE_GB = 4;
|
| 7 |
const MAX_SERIES_SIZE_GB = 1.5;
|
| 8 |
-
const PER_SOURCE_LIMIT =
|
| 9 |
-
const LINKS_PER_QUALITY = 1;
|
| 10 |
const MIN_SEEDERS = 2;
|
| 11 |
const BLOCK_SIZELESS = true;
|
| 12 |
|
|
@@ -41,11 +40,7 @@ function qualitySortKey(q) {
|
|
| 41 |
|
| 42 |
function detectProvider(t) {
|
| 43 |
const m = t.match(/\[([^\]]+)\]/);
|
| 44 |
-
|
| 45 |
-
let prov = m[1].toLowerCase();
|
| 46 |
-
// Extract base name: "yts.bz" → "yts", "eztv.re" → "eztv"
|
| 47 |
-
const baseMatch = prov.match(/^([a-z]+)/);
|
| 48 |
-
return baseMatch ? baseMatch[1] : prov;
|
| 49 |
}
|
| 50 |
|
| 51 |
function providerSortKey(p) {
|
|
@@ -53,7 +48,9 @@ function providerSortKey(p) {
|
|
| 53 |
return i >= 0 ? i : PRIORITY_PROVIDERS.length;
|
| 54 |
}
|
| 55 |
|
|
|
|
| 56 |
function parseSizeGB(t, obj) {
|
|
|
|
| 57 |
if (t) {
|
| 58 |
const labeled = t.match(/(?:💾|📦|Size:|size:)\s*([\d.]+)\s*(GB|MB|TB)/i);
|
| 59 |
if (labeled) {
|
|
@@ -63,6 +60,7 @@ function parseSizeGB(t, obj) {
|
|
| 63 |
if (u === 'MB') return v / 1024;
|
| 64 |
}
|
| 65 |
}
|
|
|
|
| 66 |
if (obj && obj.size) {
|
| 67 |
const m = String(obj.size).match(/^([\d.]+)\s*(GB|MB|TB)$/i);
|
| 68 |
if (m) {
|
|
@@ -72,6 +70,7 @@ function parseSizeGB(t, obj) {
|
|
| 72 |
if (u === 'MB') return v / 1024;
|
| 73 |
}
|
| 74 |
}
|
|
|
|
| 75 |
if (obj && obj.description) {
|
| 76 |
const descMatch = String(obj.description).match(/\b([\d.]+)\s*(GB|MB|TB)\b/i);
|
| 77 |
if (descMatch) {
|
|
@@ -81,9 +80,11 @@ function parseSizeGB(t, obj) {
|
|
| 81 |
if (u === 'MB') return v / 1024;
|
| 82 |
}
|
| 83 |
}
|
|
|
|
| 84 |
return null;
|
| 85 |
}
|
| 86 |
|
|
|
|
| 87 |
function parseSizeBytes(t, obj) {
|
| 88 |
if (t) {
|
| 89 |
const labeled = t.match(/(?:💾|📦|Size:|size:)\s*([\d.]+)\s*(GB|MB|TB)/i);
|
|
@@ -274,13 +275,9 @@ function filterAndArrange(streams, isSeries) {
|
|
| 274 |
bucket.sort((a, b) => {
|
| 275 |
const pa = detectProvider(a.title || a.name || '');
|
| 276 |
const pb = detectProvider(b.title || a.name || '');
|
| 277 |
-
|
| 278 |
-
const skB = providerSortKey(pb);
|
| 279 |
-
if (skA !== skB) return skA - skB;
|
| 280 |
-
// If same priority level, sort alphabetically
|
| 281 |
-
return pa.localeCompare(pb);
|
| 282 |
});
|
| 283 |
-
picks.push(...bucket.slice(0,
|
| 284 |
}
|
| 285 |
result.push(...picks);
|
| 286 |
}
|
|
@@ -298,7 +295,7 @@ app.get('/manifest.json', (req, res) => {
|
|
| 298 |
id: 'org.ghostream.plus',
|
| 299 |
name: 'Ghostream+ 🚀',
|
| 300 |
description: 'Stream Everything You Want\nMade With 🤍 By Van',
|
| 301 |
-
version: '5.0.
|
| 302 |
resources: ['stream', 'subtitles'],
|
| 303 |
types: ['movie', 'series'],
|
| 304 |
idPrefixes: ['tt'],
|
|
|
|
| 5 |
|
| 6 |
const MAX_MOVIE_SIZE_GB = 4;
|
| 7 |
const MAX_SERIES_SIZE_GB = 1.5;
|
| 8 |
+
const PER_SOURCE_LIMIT = 3;
|
|
|
|
| 9 |
const MIN_SEEDERS = 2;
|
| 10 |
const BLOCK_SIZELESS = true;
|
| 11 |
|
|
|
|
| 40 |
|
| 41 |
function detectProvider(t) {
|
| 42 |
const m = t.match(/\[([^\]]+)\]/);
|
| 43 |
+
return m ? m[1].toLowerCase() : 'other';
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
}
|
| 45 |
|
| 46 |
function providerSortKey(p) {
|
|
|
|
| 48 |
return i >= 0 ? i : PRIORITY_PROVIDERS.length;
|
| 49 |
}
|
| 50 |
|
| 51 |
+
// Ultra‑strict size parser – only returns a value if it finds a true file size
|
| 52 |
function parseSizeGB(t, obj) {
|
| 53 |
+
// First, look for explicitly labelled sizes (with emoji or "Size:")
|
| 54 |
if (t) {
|
| 55 |
const labeled = t.match(/(?:💾|📦|Size:|size:)\s*([\d.]+)\s*(GB|MB|TB)/i);
|
| 56 |
if (labeled) {
|
|
|
|
| 60 |
if (u === 'MB') return v / 1024;
|
| 61 |
}
|
| 62 |
}
|
| 63 |
+
// If the object has a separate 'size' field, use it
|
| 64 |
if (obj && obj.size) {
|
| 65 |
const m = String(obj.size).match(/^([\d.]+)\s*(GB|MB|TB)$/i);
|
| 66 |
if (m) {
|
|
|
|
| 70 |
if (u === 'MB') return v / 1024;
|
| 71 |
}
|
| 72 |
}
|
| 73 |
+
// If the object has a description with a size, use it
|
| 74 |
if (obj && obj.description) {
|
| 75 |
const descMatch = String(obj.description).match(/\b([\d.]+)\s*(GB|MB|TB)\b/i);
|
| 76 |
if (descMatch) {
|
|
|
|
| 80 |
if (u === 'MB') return v / 1024;
|
| 81 |
}
|
| 82 |
}
|
| 83 |
+
// No size found anywhere – return null
|
| 84 |
return null;
|
| 85 |
}
|
| 86 |
|
| 87 |
+
// Same ultra‑strict logic for bytes
|
| 88 |
function parseSizeBytes(t, obj) {
|
| 89 |
if (t) {
|
| 90 |
const labeled = t.match(/(?:💾|📦|Size:|size:)\s*([\d.]+)\s*(GB|MB|TB)/i);
|
|
|
|
| 275 |
bucket.sort((a, b) => {
|
| 276 |
const pa = detectProvider(a.title || a.name || '');
|
| 277 |
const pb = detectProvider(b.title || a.name || '');
|
| 278 |
+
return providerSortKey(pa) - providerSortKey(pb);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
});
|
| 280 |
+
picks.push(...bucket.slice(0, PER_SOURCE_LIMIT));
|
| 281 |
}
|
| 282 |
result.push(...picks);
|
| 283 |
}
|
|
|
|
| 295 |
id: 'org.ghostream.plus',
|
| 296 |
name: 'Ghostream+ 🚀',
|
| 297 |
description: 'Stream Everything You Want\nMade With 🤍 By Van',
|
| 298 |
+
version: '5.0.6',
|
| 299 |
resources: ['stream', 'subtitles'],
|
| 300 |
types: ['movie', 'series'],
|
| 301 |
idPrefixes: ['tt'],
|