recycleactor commited on
Commit
0aacfda
Β·
verified Β·
1 Parent(s): 76e0f14

Upload turbo.js

Browse files
Files changed (1) hide show
  1. turbo.js +63 -59
turbo.js CHANGED
@@ -181,11 +181,64 @@ function extractMovieVoices(text) {
181
  }
182
 
183
  async function parseObrutEmbed(embedUrl, browser) {
184
- // obrut.show uses Cloudflare - need Puppeteer with anti-detection
185
- console.log('[turbo] parsing obrut embed with Puppeteer (Cloudflare bypass)');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  const page = await browser.newPage();
187
  try {
188
- // More realistic browser fingerprint
189
  await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
190
  await page.setExtraHTTPHeaders({
191
  'Accept-Language': 'ru-RU,ru;q=0.9,en;q=0.8',
@@ -216,7 +269,7 @@ async function parseObrutEmbed(embedUrl, browser) {
216
  }
217
  });
218
 
219
- console.log('[turbo] navigating to obrut embed:', embedUrl.substring(0, 80));
220
 
221
  await page.goto(embedUrl, {
222
  waitUntil: 'domcontentloaded',
@@ -244,74 +297,25 @@ async function parseObrutEmbed(embedUrl, browser) {
244
  console.log('[turbo] Puppeteer got HTML, len:', html.length, 'hasPlayer:', html.includes('new Player('));
245
 
246
  if (!html.includes('new Player(')) {
247
- console.log('[turbo] no Player() found after Cloudflare bypass');
248
  return null;
249
  }
250
 
251
  const pm = html.match(/new\s+Player\s*\(\s*"([A-Za-z0-9+/=]{20,})"/);
252
  if (!pm) {
253
- console.log('[turbo] Player() found but no base64 data');
254
  return null;
255
  }
256
 
257
  const text = getCleanText(pm[1]);
258
- const entries = extractEntries(text);
259
- const movieVoices = extractMovieVoices(text);
260
- console.log('[turbo] Puppeteer: entries=', entries.length, 'voices=', movieVoices.length);
261
 
262
- if (entries.length === 0 && movieVoices.length === 0) {
263
- console.log('[turbo] no data extracted, retrying with parallel requests...');
264
- // Fallback to parallel HTTP if Puppeteer got Player but no data
265
- } else {
266
- return { entries, movieVoices };
267
- }
268
  } finally {
269
  await page.close();
270
  }
271
-
272
- // Fallback: parallel HTTP requests (may work after Puppeteer warmed up the session)
273
- const BATCH_SIZE = 10;
274
- const MAX_BATCHES = 5;
275
- const mergedEntries = new Map();
276
- const mergedVoices = new Map();
277
-
278
- for (let batch = 0; batch < MAX_BATCHES; batch++) {
279
- const promises = Array.from({ length: BATCH_SIZE }, () =>
280
- fetchRaw(embedUrl, {
281
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36',
282
- 'referer': 'https://kinojump.com/',
283
- 'accept': 'text/html'
284
- }).then(html => {
285
- const pm = html.match(/new\s+Player\s*\(\s*"([A-Za-z0-9+/=]{20,})"/);
286
- if (!pm) return null;
287
- const text = getCleanText(pm[1]);
288
- return { entries: extractEntries(text), movieVoices: extractMovieVoices(text) };
289
- }).catch(() => null)
290
- );
291
-
292
- const results = await Promise.all(promises);
293
-
294
- for (const r of results) {
295
- if (!r) continue;
296
- for (const e of r.entries) {
297
- const key = e.voice + '|' + e.episode;
298
- if (!mergedEntries.has(key)) mergedEntries.set(key, e);
299
- }
300
- for (const v of r.movieVoices) {
301
- if (!mergedVoices.has(v.label)) mergedVoices.set(v.label, v);
302
- }
303
- }
304
-
305
- const e = mergedEntries.size, v = mergedVoices.size;
306
- console.log(`[turbo] batch ${batch + 1}: entries=${e} voices=${v}`);
307
- if (v >= 5) break;
308
- }
309
-
310
- const entries = Array.from(mergedEntries.values());
311
- const movieVoices = Array.from(mergedVoices.values());
312
-
313
- if (entries.length === 0 && movieVoices.length === 0) return null;
314
- return { entries, movieVoices };
315
  }
316
 
317
  // ── Build serial structure ────────────────────────────────────────────────────
 
181
  }
182
 
183
  async function parseObrutEmbed(embedUrl, browser) {
184
+ // obrut.show uses Cloudflare - use Cloudflare Worker as proxy to bypass IP blocking
185
+ const WORKER_URL = 'https://proxy.recycleactor.workers.dev/turbo/proxy';
186
+
187
+ console.log('[turbo] parsing obrut embed via Cloudflare Worker (bypass Cloudflare IP block)');
188
+
189
+ // Try worker proxy first (parallel requests for better data coverage)
190
+ const BATCH_SIZE = 10;
191
+ const MAX_BATCHES = 5;
192
+ const mergedEntries = new Map();
193
+ const mergedVoices = new Map();
194
+
195
+ for (let batch = 0; batch < MAX_BATCHES; batch++) {
196
+ const promises = Array.from({ length: BATCH_SIZE }, () =>
197
+ fetchRaw(WORKER_URL + '?url=' + encodeURIComponent(embedUrl), {
198
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36',
199
+ 'accept': 'text/html'
200
+ }).then(html => {
201
+ console.log('[turbo] worker response len:', html.length, 'hasPlayer:', html.includes('new Player('));
202
+ const pm = html.match(/new\s+Player\s*\(\s*"([A-Za-z0-9+/=]{20,})"/);
203
+ if (!pm) return null;
204
+ const text = getCleanText(pm[1]);
205
+ return { entries: extractEntries(text), movieVoices: extractMovieVoices(text) };
206
+ }).catch(e => {
207
+ console.log('[turbo] worker request failed:', e.message);
208
+ return null;
209
+ })
210
+ );
211
+
212
+ const results = await Promise.all(promises);
213
+
214
+ for (const r of results) {
215
+ if (!r) continue;
216
+ for (const e of r.entries) {
217
+ const key = e.voice + '|' + e.episode;
218
+ if (!mergedEntries.has(key)) mergedEntries.set(key, e);
219
+ }
220
+ for (const v of r.movieVoices) {
221
+ if (!mergedVoices.has(v.label)) mergedVoices.set(v.label, v);
222
+ }
223
+ }
224
+
225
+ const e = mergedEntries.size, v = mergedVoices.size;
226
+ console.log(`[turbo] batch ${batch + 1}: entries=${e} voices=${v}`);
227
+ if (v >= 5 || e >= 10) break;
228
+ }
229
+
230
+ const entries = Array.from(mergedEntries.values());
231
+ const movieVoices = Array.from(mergedVoices.values());
232
+
233
+ if (entries.length > 0 || movieVoices.length > 0) {
234
+ console.log('[turbo] worker proxy success: entries=', entries.length, 'voices=', movieVoices.length);
235
+ return { entries, movieVoices };
236
+ }
237
+
238
+ // Fallback: try Puppeteer if worker failed
239
+ console.log('[turbo] worker proxy failed, trying Puppeteer fallback');
240
  const page = await browser.newPage();
241
  try {
 
242
  await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
243
  await page.setExtraHTTPHeaders({
244
  'Accept-Language': 'ru-RU,ru;q=0.9,en;q=0.8',
 
269
  }
270
  });
271
 
272
+ console.log('[turbo] Puppeteer navigating to obrut embed:', embedUrl.substring(0, 80));
273
 
274
  await page.goto(embedUrl, {
275
  waitUntil: 'domcontentloaded',
 
297
  console.log('[turbo] Puppeteer got HTML, len:', html.length, 'hasPlayer:', html.includes('new Player('));
298
 
299
  if (!html.includes('new Player(')) {
300
+ console.log('[turbo] Puppeteer: no Player() found');
301
  return null;
302
  }
303
 
304
  const pm = html.match(/new\s+Player\s*\(\s*"([A-Za-z0-9+/=]{20,})"/);
305
  if (!pm) {
306
+ console.log('[turbo] Puppeteer: Player() found but no base64 data');
307
  return null;
308
  }
309
 
310
  const text = getCleanText(pm[1]);
311
+ const puppeteerEntries = extractEntries(text);
312
+ const puppeteerVoices = extractMovieVoices(text);
313
+ console.log('[turbo] Puppeteer: entries=', puppeteerEntries.length, 'voices=', puppeteerVoices.length);
314
 
315
+ return { entries: puppeteerEntries, movieVoices: puppeteerVoices };
 
 
 
 
 
316
  } finally {
317
  await page.close();
318
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  }
320
 
321
  // ── Build serial structure ────────────────────────────────────────────────────