@torrent-tv/proxy 2.15.2 → 2.15.3
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/package.json +1 -1
- package/services/torrent-pool.js +30 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 2.15.3
|
|
2
|
+
|
|
3
|
+
- **Fix**: A magnet whose swarm never answered no longer poisons the film for good. It leaves a torrent with the right infohash and no file list, and WebTorrent then refuses the same film opened from a `.torrent` as a duplicate — so the answer to every later attempt came from the entry that knows nothing: `Proxy playback plan request failed (404): File index was not found in torrent`, reproduced in a browser 2026-08-15, and no reload could clear it because the useless entry outlives them all. A source that carries the metadata now replaces one that lacks it.
|
|
4
|
+
|
|
1
5
|
## 2.15.2
|
|
2
6
|
|
|
3
7
|
- **Fix**: A segment request that can never be answered is answered as absent instead of being held for a minute. Changing audio track makes hls.js ask the new stream for segment #0 before anything else; the run was at #354, the repair reaches sixty segments back and no further, no seek was coming, and an encoder only moves forward — so the request was unanswerable from the moment it arrived, and holding it simply spent the player's own patience. Measured 2026-08-15: the track was made ready in 7.1 s at the viewer's position, and the viewer then watched a spinner for **63 s** — sixty of them the hold, the rest the player recovering after it failed. Deliberately narrower than the refusal 2.14.1 shipped and 2.14.2 withdrew: a request within the repair's reach, or one with a seek on its way, is still held, because for those the encoder is about to be moved there.
|
package/package.json
CHANGED
package/services/torrent-pool.js
CHANGED
|
@@ -438,6 +438,17 @@ export function fileDownloadedBytes(torrent, file) {
|
|
|
438
438
|
* File-level piece selection is tracked through a reference-count map so
|
|
439
439
|
* that only files with at least one active stream cause downloading.
|
|
440
440
|
*/
|
|
441
|
+
/**
|
|
442
|
+
* Whether what we are about to add is a magnet — a name for content, with no
|
|
443
|
+
* file list in it — rather than a .torrent, which carries one.
|
|
444
|
+
*
|
|
445
|
+
* @param {string | Buffer} torrentId
|
|
446
|
+
* @returns {boolean}
|
|
447
|
+
*/
|
|
448
|
+
function isMagnetSource(torrentId) {
|
|
449
|
+
return typeof torrentId === "string" && /^magnet:\?/i.test(torrentId.trim());
|
|
450
|
+
}
|
|
451
|
+
|
|
441
452
|
export class TorrentPool {
|
|
442
453
|
/**
|
|
443
454
|
* In-flight `client.add()` promises keyed by the same key as `torrents`.
|
|
@@ -989,6 +1000,25 @@ export class TorrentPool {
|
|
|
989
1000
|
const dupMatch = /duplicate torrent ([0-9a-f]{40})/i.exec(message);
|
|
990
1001
|
if (dupMatch) {
|
|
991
1002
|
const existing = this.client.torrents.find((t) => t?.infoHash === dupMatch[1]);
|
|
1003
|
+
// A torrent already here but WITHOUT metadata is not an answer to a
|
|
1004
|
+
// request that carries metadata. A magnet whose swarm never answered
|
|
1005
|
+
// leaves exactly that: an entry with the right infohash, no file
|
|
1006
|
+
// list, and no way to get one. The same film opened from a .torrent
|
|
1007
|
+
// then collides with it and is refused as a duplicate — measured
|
|
1008
|
+
// 2026-08-15 in a browser, "File index was not found in torrent", and
|
|
1009
|
+
// no reload could ever fix it because the poisoned entry outlives
|
|
1010
|
+
// every attempt. The one that knows the files wins.
|
|
1011
|
+
if (existing && !existing.ready && !isMagnetSource(torrentId)) {
|
|
1012
|
+
logger.info(
|
|
1013
|
+
`torrent-pool: replacing ${dupMatch[1].slice(0, 8)} — it was added from a magnet that never ` +
|
|
1014
|
+
"found peers, and this source carries the metadata it lacks"
|
|
1015
|
+
);
|
|
1016
|
+
existing.destroy({ destroyStore: false }, () => {
|
|
1017
|
+
this.#pending.delete(key);
|
|
1018
|
+
resolve(this.getTorrent(sourceType, source));
|
|
1019
|
+
});
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
992
1022
|
if (existing) {
|
|
993
1023
|
const settle = () => {
|
|
994
1024
|
this.torrents.set(key, existing);
|