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.
- package/package.json +1 -1
- package/wtui.js +17 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "torrent-online",
|
|
3
|
-
"version": "1.5.
|
|
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
|
|
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 = '
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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){
|