@torrent-tv/proxy 2.55.6 → 2.55.7
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/CHANGELOG.md +4 -0
- package/bin/cli.js +5 -0
- package/package.json +1 -1
- package/server.js +9 -1
- package/services/data-channel-handler.js +27 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 2.55.7
|
|
2
|
+
|
|
3
|
+
- **Fix**: The subtitle push subscription is now recorded under the torrent pool's own key, not the browser's registry key — the two are different strings whenever a source was added by a `.torrent` file (a `.torrent` and a magnet for the same film are different request bytes, hashed into different registry keys, but the SAME infohash) and were silently different in every other case too: a registry key is `sha1(sourceType:source)`, one per API session; the pool's key is `torrent:<infohash>`, deliberately shared across a magnet and a `.torrent` for the same content (item 10). The diagnostic logging added in 2.55.6 caught it directly, field case 2026-08-22: cues were found and logged repeatedly, and every push answered `found no subscribed channel` — the subscription and the publish had never been able to agree on a key, for any torrent, since the push feature shipped in 2.55.5. `data-channel-handler.js` now resolves the browser's registry key through `sourceRegistry` to `(sourceType, source)` and runs it through the same `deriveSourceKey` the pool itself uses, at the one point both keys are in hand — the subscribe intercept, before the request is even forwarded.
|
|
4
|
+
|
|
1
5
|
## 2.55.6
|
|
2
6
|
|
|
3
7
|
- **Chore**: Every step of the subtitle push chain now logs on success, not only on failure. Field report 2026-08-22, playing `Minions.and.Monsters.1080p.mkv`: a track was switched on over a minute after the seed fetch found nothing (`bytes=7`, an empty `WEBVTT` — expected, the torrent had barely started), and no cues appeared. The proxy log carried no evidence either way — `warmActiveFiles` posted `Event.SUBTITLE_CUES_READY` silently, `publishSubtitleCues` sent (or found no subscriber for) a push silently, and `subscribeSubtitles` registered a channel silently. Confirmed separately by reading WebTorrent's own source that `verified` fires on every live piece completion (`_markVerified` inside `store.put`'s callback in `torrent.js`, not only at startup), so the event source itself is real; what could not be told apart without these lines is subscription, discovery, and delivery. Logs now name each: `subtitle push: channel subscribed to …`, `… cue(s) found, posting to main thread`, `… sent N cue(s) … to M/T channel(s)` (or `found no subscribed channel`).
|
package/bin/cli.js
CHANGED
|
@@ -300,6 +300,7 @@ try {
|
|
|
300
300
|
});
|
|
301
301
|
app = started.app;
|
|
302
302
|
actualPort = started.port;
|
|
303
|
+
const sourceRegistry = started.sourceRegistry;
|
|
303
304
|
const directBaseUrl = explicitBaseUrl || `http://${bindHost}:${actualPort}`;
|
|
304
305
|
|
|
305
306
|
// A native fault writes the whole address space out — 4.18 GB each on the
|
|
@@ -421,6 +422,10 @@ try {
|
|
|
421
422
|
dataChannelHandler = createDataChannelHandler({
|
|
422
423
|
proxyPort: actualPort,
|
|
423
424
|
onLog: (message) => logger.info(message),
|
|
425
|
+
// Resolves a browser's registry sourceKey to the torrent pool's own key
|
|
426
|
+
// (the content's infohash) so the subtitle push subscription and the
|
|
427
|
+
// pool's own publish agree on what a source is called. See server.js.
|
|
428
|
+
sourceRegistry,
|
|
424
429
|
// Lets a stuck send queue ask the transport what it is doing. Late-bound:
|
|
425
430
|
// the manager is created below, with this handler already in hand.
|
|
426
431
|
getTransportSnapshot: (sessionId) => webRtcManager?.getTransportSnapshot(sessionId) ?? null
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -290,6 +290,14 @@ export async function startProxyServer({
|
|
|
290
290
|
await app.listen({ host, port: selectedPort });
|
|
291
291
|
return {
|
|
292
292
|
app,
|
|
293
|
-
port: selectedPort
|
|
293
|
+
port: selectedPort,
|
|
294
|
+
// The browser only ever knows a source by its REGISTRY key (a hash of the
|
|
295
|
+
// raw request bytes, scoped to one API session) — never the torrent
|
|
296
|
+
// pool's own key (the content's infohash, shared across a magnet and a
|
|
297
|
+
// `.torrent` naming the same film). The subtitle push subscription is
|
|
298
|
+
// recorded from a browser request and published from the pool's side, so
|
|
299
|
+
// resolving one into the other is what lets the two ends agree on what
|
|
300
|
+
// they are both calling "sourceKey".
|
|
301
|
+
sourceRegistry
|
|
294
302
|
};
|
|
295
303
|
}
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
|
|
44
44
|
/** @import { DataChannel } from 'node-datachannel' */
|
|
45
45
|
|
|
46
|
+
import { deriveSourceKey } from "./torrent-source-key.js";
|
|
47
|
+
|
|
46
48
|
/**
|
|
47
49
|
* Configuration for the data channel handler.
|
|
48
50
|
*
|
|
@@ -299,7 +301,7 @@ export function encodeFrame(idBytes, bytes, done) {
|
|
|
299
301
|
return frame;
|
|
300
302
|
}
|
|
301
303
|
|
|
302
|
-
export function createDataChannelHandler({ proxyPort, onLog, getTransportSnapshot }) {
|
|
304
|
+
export function createDataChannelHandler({ proxyPort, onLog, getTransportSnapshot, sourceRegistry }) {
|
|
303
305
|
/**
|
|
304
306
|
* Channels currently interested in one file's subtitle cues, keyed by
|
|
305
307
|
* `sourceKey:fileIndex`. Populated the moment a browser asks for an
|
|
@@ -579,13 +581,34 @@ export function createDataChannelHandler({ proxyPort, onLog, getTransportSnapsho
|
|
|
579
581
|
// this walks incrementally). `fileIndex` alone would also scope this to
|
|
580
582
|
// the wrong grain for the real case — a torrent can carry several playable
|
|
581
583
|
// files — so the pair is what a push is ever addressed to.
|
|
584
|
+
//
|
|
585
|
+
// The browser's `sourceKey` is a REGISTRY key — a hash of the raw request
|
|
586
|
+
// bytes, one per (magnet-or-.torrent, this API session). The torrent pool
|
|
587
|
+
// publishes under its OWN key — the content's infohash, deliberately the
|
|
588
|
+
// SAME for a magnet and a `.torrent` naming the same film, so the two
|
|
589
|
+
// share one swarm (item 10). The two are different strings for the same
|
|
590
|
+
// torrent whenever a source was added by its `.torrent` file (a `.torrent`
|
|
591
|
+
// and a magnet are different request bytes, same infohash) — subscribing
|
|
592
|
+
// under the registry key found no publisher for that reason, not because
|
|
593
|
+
// nothing was ever read: field case 2026-08-22, cues were found and
|
|
594
|
+
// logged, every push answered "found no subscribed channel". Resolved to
|
|
595
|
+
// the pool's key here, the one place both are in hand.
|
|
582
596
|
if (path === "/api/subtitles" && typeof query === "string") {
|
|
583
597
|
const params = new URLSearchParams(query);
|
|
584
|
-
const
|
|
598
|
+
const registrySourceKey = params.get("sourceKey");
|
|
585
599
|
const fileIndex = Number(params.get("fileIndex"));
|
|
586
600
|
const hasTrackIndex = params.get("trackIndex") !== null && params.get("trackIndex") !== "";
|
|
587
|
-
if (
|
|
588
|
-
|
|
601
|
+
if (registrySourceKey && Number.isInteger(fileIndex) && hasTrackIndex) {
|
|
602
|
+
const record = sourceRegistry?.get(registrySourceKey);
|
|
603
|
+
if (record) {
|
|
604
|
+
try {
|
|
605
|
+
const poolSourceKey = await deriveSourceKey(record.sourceType, record.source);
|
|
606
|
+
subscribeSubtitles(poolSourceKey, fileIndex, channel);
|
|
607
|
+
} catch (error) {
|
|
608
|
+
log(`[dc] subtitle push: could not resolve ${registrySourceKey.slice(0, 8)} to a pool key: ` +
|
|
609
|
+
`${error instanceof Error ? error.message : error}`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
589
612
|
}
|
|
590
613
|
}
|
|
591
614
|
|