torrent-online 1.5.1 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/wtui.js +17 -27
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "torrent-online",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "type": "module",
5
5
  "description": "Stream .torrent / magnet to VLC or browser — torrent streaming for macOS/Linux without a torrent client. Стрим торрентов в VLC или браузер.",
6
6
  "keywords": [
package/wtui.js CHANGED
@@ -275,7 +275,7 @@ function serveFile(req, res, file) {
275
275
  const TRANSLIT = { а:'a',б:'b',в:'v',г:'g',д:'d',е:'e',ё:'e',ж:'zh',з:'z',и:'i',й:'y',к:'k',л:'l',м:'m',н:'n',о:'o',п:'p',р:'r',с:'s',т:'t',у:'u',ф:'f',х:'kh',ц:'ts',ч:'ch',ш:'sh',щ:'shch',ъ:'',ы:'y',ь:'',э:'e',ю:'yu',я:'ya' };
276
276
  function translit(s) { return s.toLowerCase().split('').map(c => TRANSLIT[c] ?? c).join(''); }
277
277
 
278
- // RU->EN словарь популярных названий для TPB/1337x
278
+ // RU->EN словарь популярных названий для TPB
279
279
  const RU_EN = {
280
280
  'пацаны': 'the boys', 'во все тяжкие': 'breaking bad', 'лучше звонка сола': 'better call saul',
281
281
  'игра престолов': 'game of thrones', 'странные дела': 'stranger things', 'ведьмак': 'the witcher',
@@ -309,31 +309,21 @@ function ruToEn(q) {
309
309
  }
310
310
  function btihKey(mag) { const m = /btih:([0-9a-fA-F]{40}|[0-9a-fA-F]{32})/.exec(mag); return m ? m[1].toLowerCase() : mag.slice(0, 90); }
311
311
 
312
- async function search1337x(q) {
313
- const r = await fetch(`https://1337x.st/api/v1/search/${encodeURIComponent(q)}/1/1/1/0/`, {
314
- headers: { 'x-api-key': 'sk1337x73871873371873', 'user-agent': UA, accept: 'application/json' },
315
- signal: AbortSignal.timeout(9000),
316
- });
317
- const text = await r.text();
318
- if (!r.ok) throw new Error(`1337x: HTTP ${r.status}${/Just a moment/.test(text) ? ' (Cloudflare)' : ''}`);
319
- let j;
320
- try { j = JSON.parse(text); } catch { throw new Error('1337x: не JSON'); }
321
- const out = [];
322
- for (const it of j.data || []) {
323
- const mag = it.magnetLink || it.magnet_link || it.torrent_magnet;
324
- if (mag && mag.startsWith('magnet:'))
325
- out.push({ name: String(it.name || ''), mag, size: String(it.size || ''), seeds: Number(it.seeders) || 0, src: '1337x' });
326
- }
327
- return out;
328
- }
329
312
 
330
- async function searchTPB(q, host = 'https://tpb.party') {
331
- const r = await fetch(`${host}/search/${encodeURIComponent(q)}/0/99/0/`, {
332
- headers: { 'user-agent': UA },
333
- signal: AbortSignal.timeout(9000),
334
- });
335
- if (!r.ok) throw new Error(`TPB: HTTP ${r.status}`);
336
- const html = await r.text();
313
+ async function searchTPB(q, host = '') {
314
+ const hosts = ['https://tpb.party', 'https://piratebay.live'];
315
+ let html = '', lastErr = new Error('TPB: нет ответа');
316
+ for (const h of (host ? [host] : hosts)) {
317
+ try {
318
+ const r = await fetch(`${h}/search/${encodeURIComponent(q)}/0/99/0/`, {
319
+ headers: { 'user-agent': UA },
320
+ signal: AbortSignal.timeout(9000),
321
+ });
322
+ if (r.ok) { html = await r.text(); lastErr = null; break; }
323
+ lastErr = new Error(`TPB: HTTP ${r.status}`);
324
+ } catch (e) { lastErr = e; }
325
+ }
326
+ if (lastErr) throw lastErr;
337
327
  const out = [];
338
328
  for (const row of html.split('<tr>').slice(1)) {
339
329
  const magRaw = /href="(magnet:[^"]+)"/.exec(row)?.[1];
@@ -376,7 +366,6 @@ async function searchIndexers(q) {
376
366
  jobs.push(searchRutor(queries[0]).then(rs => results.push(...rs), e => notes.push(e.message)));
377
367
  for (const qq of queries) {
378
368
  jobs.push(searchTPB(qq).then(rs => results.push(...rs), e => notes.push(e.message)));
379
- jobs.push(search1337x(qq).then(rs => results.push(...rs), e => notes.push(e.message)));
380
369
  }
381
370
  await Promise.allSettled(jobs);
382
371
  const seen = new Set();
@@ -569,7 +558,7 @@ video{width:100vw;height:100vh;background:#000;display:block;margin:0}
569
558
  </style></head><body>
570
559
  <header>🦀 <b>TorrentOnline</b></header>
571
560
  <div class=wrap>
572
- <div class=search><input id=q placeholder="Поиск: пацаны 4 сезон · breaking bad · magnet:…" autocomplete=off><button id=go>Искать</button><button id=mag>+ magnet</button></div>
561
+ <div class=search><input id=q placeholder="Поиск: пацаны 4 сезон · breaking bad · magnet:…" autocomplete=off><button id=go>Искать</button><button id=mag>+ magnet</button><button id=tpath>+ .torrent файл</button></div>
573
562
  <div id=notes></div>
574
563
  <div id=results></div>
575
564
  <h3>Торренты</h3>
@@ -590,6 +579,7 @@ box.innerHTML=h;
590
579
  document.getElementById('go').onclick=doSearch;
591
580
  document.getElementById('q').addEventListener('keydown',function(e){if(e.key==='Enter')doSearch();});
592
581
  document.getElementById('mag').onclick=function(){var m=prompt('magnet:');if(m&&m.indexOf('magnet:')===0){api('/api/add',{source:m}).then(poll);}};
582
+ document.getElementById('tpath').onclick=function(){var p=prompt('Путь к .torrent, напр. /Users/you/Downloads/torrent.torrent');if(p&&p.trim()){api('/api/add',{source:p.trim()}).then(poll);}};
593
583
  function render(list){var box=document.getElementById('torrents');
594
584
  if(!list.length){box.innerHTML='<div class=note>Пусто. Найди торрент и кликни по строке.</div>';return;}
595
585
  box.innerHTML=list.map(function(t){