diff --git a/js/app.js b/js/app.js index a1fb40ff..6ebb0f13 100644 --- a/js/app.js +++ b/js/app.js @@ -5,7 +5,8 @@ import { nostrClient } from "./nostr.js"; import { torrentClient } from "./webtorrent.js"; import { isDevMode } from "./config.js"; import { isWhitelistEnabled } from "./config.js"; -import { normalizeAndAugmentMagnet, safeDecodeMagnet } from "./magnetUtils.js"; +import { safeDecodeMagnet } from "./magnetUtils.js"; +import { normalizeAndAugmentMagnet } from "./magnet.js"; import { deriveTorrentPlaybackConfig } from "./playbackUtils.js"; import { initialWhitelist, @@ -1092,7 +1093,6 @@ class bitvidApp { const xs = xsEl?.value.trim() || ""; const thumbnail = thumbEl?.value.trim() || ""; const description = descEl?.value.trim() || ""; - const sanitizedHostedUrl = url; const formData = { version: 2, @@ -1106,26 +1106,17 @@ class bitvidApp { }; if (!formData.title || (!formData.url && !formData.magnet)) { - this.showError("Please provide a title and at least one of URL or Magnet."); + this.showError( + "Please add a title plus either a hosted video URL or a magnet link." + ); return; } - const webSeedCandidates = []; - if (ws) { - webSeedCandidates.push(ws); - } - if (sanitizedHostedUrl) { - webSeedCandidates.push(sanitizedHostedUrl); - } - - const magnetAugmentation = normalizeAndAugmentMagnet(formData.magnet, { - webSeed: webSeedCandidates, - torrentUrl: xs, - logger: (message) => this.log(message), + formData.magnet = normalizeAndAugmentMagnet(formData.magnet, { + ws, + xs, }); - formData.magnet = magnetAugmentation.magnet; - try { await nostrClient.publishVideo(formData, this.pubkey); diff --git a/js/magnet.js b/js/magnet.js new file mode 100644 index 00000000..2f5934e9 --- /dev/null +++ b/js/magnet.js @@ -0,0 +1,19 @@ +import { WSS_TRACKERS } from "./constants.js"; +import { normalizeAndAugmentMagnet as normalizeLegacy } from "./magnetUtils.js"; + +export function normalizeAndAugmentMagnet(rawValue, { ws = "", xs = "" } = {}) { + const trimmedInput = typeof rawValue === "string" ? rawValue.trim() : ""; + const trimmedWs = typeof ws === "string" ? ws.trim() : ""; + const trimmedXs = typeof xs === "string" ? xs.trim() : ""; + + const webSeeds = trimmedWs ? [trimmedWs] : []; + + const result = normalizeLegacy(trimmedInput, { + webSeed: webSeeds, + torrentUrl: trimmedXs, + xs: trimmedXs, + extraTrackers: WSS_TRACKERS, + }); + + return result.magnet; +} diff --git a/tests/magnet-utils.test.mjs b/tests/magnet-utils.test.mjs index ac313f47..6d0aad55 100644 --- a/tests/magnet-utils.test.mjs +++ b/tests/magnet-utils.test.mjs @@ -1,6 +1,7 @@ import assert from "node:assert/strict"; import { WSS_TRACKERS } from "../js/constants.js"; import { normalizeAndAugmentMagnet, safeDecodeMagnet } from "../js/magnetUtils.js"; +import { normalizeAndAugmentMagnet as formNormalize } from "../js/magnet.js"; function getParamValues(magnet, key) { const parsed = new URL(magnet); @@ -111,4 +112,42 @@ function getParamValues(magnet, key) { ); })(); +(function testFormHelperAugmentsWsXsAndDecodesXt() { + const infoHash = "abcdef0123456789abcdef0123456789abcdef01"; + const encodedMagnet = `magnet:?xt=urn%3Abtih%3A${infoHash}`; + const normalized = formNormalize(encodedMagnet, { + ws: "https://cdn.example.com/video-base/", + xs: "https://cdn.example.com/video.torrent", + }); + const parsed = new URL(normalized); + assert.equal( + parsed.searchParams.get("xt"), + `urn:btih:${infoHash}`, + "Form helper should decode encoded xt payloads" + ); + assert.deepEqual( + parsed.searchParams.getAll("ws"), + ["https://cdn.example.com/video-base/"], + "Expected ws hint to be appended" + ); + assert.deepEqual( + parsed.searchParams.getAll("xs"), + ["https://cdn.example.com/video.torrent"], + "Expected xs hint to be appended" + ); +})(); + +(function testFormHelperSkipsInsecureWsOnHttpsOrigin() { + const infoHash = "0123456789abcdef0123456789abcdef01234567"; + const normalized = formNormalize(`magnet:?xt=urn:btih:${infoHash}`, { + ws: "http://cdn.example.com/video-base/", + }); + const parsed = new URL(normalized); + assert.equal( + parsed.searchParams.getAll("ws").length, + 0, + "HTTP ws value should be skipped on HTTPS origins" + ); +})(); + console.log("magnet-utils tests passed");