diff --git a/js/constants.js b/js/constants.js index 515b4c20..c92d95ea 100644 --- a/js/constants.js +++ b/js/constants.js @@ -145,7 +145,6 @@ export const DEFAULT_TRUST_SEED_NPUBS = SANITIZED_DEFAULT_TRUST_SEED_NPUBS; const DEFAULT_FLAGS = Object.freeze({ URL_FIRST_ENABLED: true, // try URL before magnet in the player - ACCEPT_LEGACY_V1: true, // accept v1 magnet-only notes FEATURE_WATCH_HISTORY_V2: true, FEATURE_PUBLISH_NIP71: false, FEATURE_HASHTAG_PREFERENCES: false, @@ -165,7 +164,6 @@ const runtimeFlags = (() => { } const initial = { URL_FIRST_ENABLED: DEFAULT_FLAGS.URL_FIRST_ENABLED, - ACCEPT_LEGACY_V1: DEFAULT_FLAGS.ACCEPT_LEGACY_V1, FEATURE_WATCH_HISTORY_V2: DEFAULT_FLAGS.FEATURE_WATCH_HISTORY_V2, FEATURE_PUBLISH_NIP71: DEFAULT_FLAGS.FEATURE_PUBLISH_NIP71, FEATURE_HASHTAG_PREFERENCES: DEFAULT_FLAGS.FEATURE_HASHTAG_PREFERENCES, @@ -188,11 +186,6 @@ export let URL_FIRST_ENABLED = coerceBoolean( DEFAULT_FLAGS.URL_FIRST_ENABLED ); -export let ACCEPT_LEGACY_V1 = coerceBoolean( - runtimeFlags.ACCEPT_LEGACY_V1, - DEFAULT_FLAGS.ACCEPT_LEGACY_V1 -); - export let FEATURE_WATCH_HISTORY_V2 = coerceBoolean( runtimeFlags.FEATURE_WATCH_HISTORY_V2, DEFAULT_FLAGS.FEATURE_WATCH_HISTORY_V2 @@ -248,17 +241,6 @@ Object.defineProperty(runtimeFlags, "URL_FIRST_ENABLED", { }, }); -Object.defineProperty(runtimeFlags, "ACCEPT_LEGACY_V1", { - configurable: true, - enumerable: true, - get() { - return ACCEPT_LEGACY_V1; - }, - set(next) { - ACCEPT_LEGACY_V1 = coerceBoolean(next, DEFAULT_FLAGS.ACCEPT_LEGACY_V1); - }, -}); - Object.defineProperty(runtimeFlags, "FEATURE_WATCH_HISTORY_V2", { configurable: true, enumerable: true, @@ -386,7 +368,6 @@ Object.defineProperty(runtimeFlags, "TRUSTED_SPAM_HIDE_THRESHOLD", { // Ensure the runtime object reflects the sanitized defaults immediately. runtimeFlags.URL_FIRST_ENABLED = URL_FIRST_ENABLED; -runtimeFlags.ACCEPT_LEGACY_V1 = ACCEPT_LEGACY_V1; runtimeFlags.FEATURE_WATCH_HISTORY_V2 = FEATURE_WATCH_HISTORY_V2; runtimeFlags.FEATURE_PUBLISH_NIP71 = FEATURE_PUBLISH_NIP71; runtimeFlags.FEATURE_HASHTAG_PREFERENCES = FEATURE_HASHTAG_PREFERENCES; @@ -403,11 +384,6 @@ export function setUrlFirstEnabled(next) { return URL_FIRST_ENABLED; } -export function setAcceptLegacyV1(next) { - runtimeFlags.ACCEPT_LEGACY_V1 = next; - return ACCEPT_LEGACY_V1; -} - export function getWatchHistoryV2Enabled() { return FEATURE_WATCH_HISTORY_V2 === true; } @@ -439,7 +415,6 @@ export function setHashtagPreferencesEnabled(next) { export function resetRuntimeFlags() { setUrlFirstEnabled(DEFAULT_FLAGS.URL_FIRST_ENABLED); - setAcceptLegacyV1(DEFAULT_FLAGS.ACCEPT_LEGACY_V1); setWatchHistoryV2Enabled(DEFAULT_FLAGS.FEATURE_WATCH_HISTORY_V2); setHashtagPreferencesEnabled(DEFAULT_FLAGS.FEATURE_HASHTAG_PREFERENCES); setTrustSeedsEnabled(DEFAULT_FLAGS.FEATURE_TRUST_SEEDS); diff --git a/js/nostr/nip71.js b/js/nostr/nip71.js index 249d5fe4..9935642e 100644 --- a/js/nostr/nip71.js +++ b/js/nostr/nip71.js @@ -1,5 +1,4 @@ -import { ACCEPT_LEGACY_V1 } from "../constants.js"; -import { deriveTitleFromEvent, magnetFromText } from "../videoEventUtils.js"; +import { deriveTitleFromEvent } from "../videoEventUtils.js"; import { extractMagnetHints } from "../magnet.js"; import { devLogger } from "../utils/logger.js"; import { getCachedNostrTools } from "./toolkit.js"; @@ -1313,51 +1312,12 @@ export function convertEventToVideo(event = {}) { if (trimmed.toLowerCase().startsWith("magnet:?")) { return trimmed; } - const extracted = magnetFromText(trimmed); - return extracted ? extracted.trim() : ""; + return ""; }; let magnet = normalizeMagnetCandidate(directMagnetRaw); let rawMagnet = magnet ? directMagnetRaw : ""; - if (!magnet && ACCEPT_LEGACY_V1) { - const inlineMagnet = normalizeMagnetCandidate(rawContent); - if (inlineMagnet) { - magnet = inlineMagnet; - } - - if (!magnet) { - outer: for (const tag of tags) { - if (!Array.isArray(tag) || tag.length < 2) { - continue; - } - - const key = - typeof tag[0] === "string" ? tag[0].trim().toLowerCase() : ""; - - const startIndex = key === "magnet" ? 1 : 0; - for (let i = startIndex; i < tag.length; i += 1) { - const candidate = normalizeMagnetCandidate(tag[i]); - if (candidate) { - magnet = candidate; - break outer; - } - } - } - } - - if (!magnet) { - const recoveredFromRaw = magnetFromText(rawContent); - if (recoveredFromRaw) { - magnet = safeTrim(recoveredFromRaw); - } - } - } - - if (!rawMagnet && magnet) { - rawMagnet = magnet; - } - const url = directUrl; if (!url && !magnet) { @@ -1411,11 +1371,6 @@ export function convertEventToVideo(event = {}) { } let title = safeTrim(derivedTitle); - if (!title && ACCEPT_LEGACY_V1 && (magnet || infoHash)) { - title = infoHash - ? `Legacy Video ${infoHash.slice(0, 8)}` - : "Legacy BitTorrent Video"; - } if (!title) { const reason = parseError @@ -1430,7 +1385,7 @@ export function convertEventToVideo(event = {}) { version = rawVersion === undefined ? 2 : 1; } - if (version < 2 && !ACCEPT_LEGACY_V1) { + if (version < 2) { return { id: event.id, invalid: true, diff --git a/js/videoEventUtils.js b/js/videoEventUtils.js index d084ffb3..159bf2de 100644 --- a/js/videoEventUtils.js +++ b/js/videoEventUtils.js @@ -6,7 +6,6 @@ */ const MAGNET_URI_PATTERN = /^magnet:\?/i; const HEX_INFO_HASH_PATTERN = /\b[0-9a-f]{40}\b/gi; -const LEGACY_MAGNET_PATTERN = /magnet:\?xt=urn:btih:[0-9a-z]{40,}[^\s"'<>]*/i; function safeTrim(value) { return typeof value === "string" ? value.trim() : ""; @@ -218,12 +217,6 @@ export function parseVideoEventPayload(event = {}) { collectMagnetOrInfoHash(value); } - const magnetMatch = rawContent.match(/magnet:\?xt=urn:[^"'\s<>]+/i); - if (magnetMatch) { - collectMagnetOrInfoHash(magnetMatch[0]); - } - - extractInfoHashesFromString(rawContent, pushInfoHash); traverseForInfoHashes(parsedContent, pushInfoHash); const magnet = magnetCandidates.find(Boolean) || ""; @@ -254,39 +247,3 @@ export function parseVideoEventPayload(event = {}) { version, }; } - -export function magnetFromText(value) { - if (typeof value !== "string") { - return ""; - } - const match = value.match(LEGACY_MAGNET_PATTERN); - return match ? match[0] : ""; -} - -export function findLegacyMagnetInEvent(event = {}) { - const fromContent = magnetFromText(event?.content); - if (fromContent) { - return fromContent.trim(); - } - - const tags = Array.isArray(event?.tags) ? event.tags : []; - for (const tag of tags) { - if (!Array.isArray(tag) || tag.length < 2) { - continue; - } - const key = typeof tag[0] === "string" ? tag[0].trim().toLowerCase() : ""; - const value = typeof tag[1] === "string" ? tag[1].trim() : ""; - if (!value) { - continue; - } - if (key === "magnet" && value) { - return value; - } - const fromTag = magnetFromText(value); - if (fromTag) { - return fromTag.trim(); - } - } - - return ""; -} diff --git a/tests/legacy-infohash.test.mjs b/tests/legacy-infohash.test.mjs deleted file mode 100644 index 6a05fe0a..00000000 --- a/tests/legacy-infohash.test.mjs +++ /dev/null @@ -1,136 +0,0 @@ -import "./test-helpers/setup-localstorage.mjs"; -import assert from "node:assert/strict"; -import { parseVideoEventPayload } from "../js/videoEventUtils.js"; -import { convertEventToVideo } from "../js/nostr/nip71.js"; -import { deriveTorrentPlaybackConfig } from "../js/playbackUtils.js"; - -const LEGACY_INFO_HASH = "0123456789abcdef0123456789abcdef01234567"; - -(function testParseDetectsBareInfoHashInJson() { - const event = { - id: "evt-json", - content: JSON.stringify({ - version: 1, - title: "Legacy note", - magnet: LEGACY_INFO_HASH, - }), - tags: [], - }; - - const parsed = parseVideoEventPayload(event); - assert.equal(parsed.magnet, "", "Bare info hash should not be treated as a magnet URI"); - assert.equal(parsed.infoHash, LEGACY_INFO_HASH); -})(); - -(function testParseDetectsInfoHashInRawContentAndTags() { - const event = { - id: "evt-tag", - content: JSON.stringify({ title: "tag-sourced" }), - tags: [["magnet", LEGACY_INFO_HASH]], - }; - - const parsed = parseVideoEventPayload(event); - assert.equal(parsed.infoHash, LEGACY_INFO_HASH); -})(); - -(function testParseDetectsInfoHashInRawString() { - const event = { - id: "evt-raw", - content: `legacy magnet ${LEGACY_INFO_HASH} broken json`, - tags: [], - }; - - const parsed = parseVideoEventPayload(event); - assert.equal(parsed.infoHash, LEGACY_INFO_HASH); -})(); - -(function testConvertFlagsBareInfoHashAsInvalid() { - const event = { - id: "evt-convert", - pubkey: "pk", - created_at: 1, - tags: [], - content: JSON.stringify({ - version: 1, - title: "Legacy conversion", - magnet: LEGACY_INFO_HASH, - }), - }; - - const video = convertEventToVideo(event); - assert.equal(video.invalid, true, "Bare info-hash payloads should be flagged"); - assert.equal(video.reason, "missing playable source"); -})(); - -(function testLegacyEventWithoutTitleStillLoads() { - const event = { - id: "evt-no-title", - pubkey: "pk2", - created_at: 2, - tags: [], - content: JSON.stringify({ - version: 1, - magnet: `magnet:?xt=urn:btih:${LEGACY_INFO_HASH}`, - }), - }; - - const video = convertEventToVideo(event); - assert.equal(video.invalid, false, "Legacy events without title should fallback"); - assert.ok(video.title && video.title.length > 0, "Fallback title should be provided"); -})(); - -(function testConvertRecoversMagnetFromMagnetTag() { - const magnetUri = - `magnet:?xt=urn:btih:${LEGACY_INFO_HASH}&dn=legacy-tag&tr=wss://tracker.openwebtorrent.com`; - const event = { - id: "evt-magnet-tag", - pubkey: "pk3", - created_at: 3, - // Deliberately invalid JSON so the converter must rely on scavenging. - content: "{not valid json}", - tags: [["magnet", magnetUri]], - }; - - const video = convertEventToVideo(event); - assert.equal(video.invalid, false, "Magnet in tag should still be playable"); - assert.equal(video.magnet, magnetUri); - assert.equal(video.rawMagnet, magnetUri); -})(); - -(function testPlaybackConfigNormalizesInfoHash() { - const result = deriveTorrentPlaybackConfig({ - magnet: "", - infoHash: LEGACY_INFO_HASH, - url: "", - }); - - assert.ok(result.magnet.startsWith("magnet:?")); - const xtValues = new URL(result.magnet).searchParams.getAll("xt"); - assert.deepEqual(xtValues, [`urn:btih:${LEGACY_INFO_HASH}`]); - assert.equal(result.usedInfoHash, true); - assert.equal(result.fallbackMagnet, ""); - assert.equal(result.provided, true); -})(); - -(function testPlaybackConfigDecodesEncodedMagnet() { - const rawMagnet = - `magnet:?xt=urn:btih:${LEGACY_INFO_HASH}&dn=Legacy+Example`; - const encodedMagnet = encodeURIComponent(rawMagnet); - const result = deriveTorrentPlaybackConfig({ - magnet: encodedMagnet, - infoHash: "", - url: "", - }); - - assert.ok(result.magnet.startsWith("magnet:?")); - const parsed = new URL(result.magnet); - assert.equal( - parsed.searchParams.get("xt"), - `urn:btih:${LEGACY_INFO_HASH}`, - "Expected encoded magnet to be normalized" - ); - assert.equal(result.provided, true); - assert.equal(result.usedInfoHash, false); -})(); - -console.log("legacy infohash tests passed");