From fae9e62af52c97c0d7be37e4240f05298fba122d Mon Sep 17 00:00:00 2001 From: Sven Date: Sun, 3 May 2026 12:06:46 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20swarm-loc-guard=20=E2=80=94=20reject=20?= =?UTF-8?q?OwnYourSwarm=20posts=20without=20Loc=20in=20content?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/patch-micropub-swarm-loc-guard.mjs | 63 ++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 scripts/patch-micropub-swarm-loc-guard.mjs diff --git a/scripts/patch-micropub-swarm-loc-guard.mjs b/scripts/patch-micropub-swarm-loc-guard.mjs new file mode 100644 index 00000000..7ee7822d --- /dev/null +++ b/scripts/patch-micropub-swarm-loc-guard.mjs @@ -0,0 +1,63 @@ +/** + * Patch: swarm-loc-guard + * + * Only accept OwnYourSwarm Micropub posts that contain the text "Loc" + * in their content. Check-ins without "Loc" are rejected with 422. + * + * Workflow: Sven adds "Loc" to Swarm check-ins he wants published. + * Check-ins without that text (stealth, accidental, no-content) are rejected. + */ + +import { readFile, writeFile, access } from "node:fs/promises"; + +const MARKER = "// [patch] swarm-loc-guard"; + +const candidates = [ + "node_modules/@indiekit/endpoint-micropub/lib/post-data.js", + "node_modules/@indiekit/indiekit/node_modules/@indiekit/endpoint-micropub/lib/post-data.js", +]; + +const oldSnippet = ` if ( + type === "note" && + (hasCheckinProperty || hasSwarmSyndication) + ) { + properties.visibility = "unlisted"; + }`; + +const newSnippet = ` if ( + type === "note" && + (hasCheckinProperty || hasSwarmSyndication) + ) { + // Guard: only accept OwnYourSwarm posts that contain "Loc" in content. ${MARKER} + const rawContent = Array.isArray(properties.content) + ? properties.content.join(" ") + : String(properties.content || ""); + if (hasSwarmSyndication && !rawContent.includes("Loc")) { + throw new IndiekitError(422, "OwnYourSwarm post without 'Loc' in content rejected"); + } + properties.visibility = "unlisted"; + }`; + +async function exists(path) { + try { await access(path); return true; } catch { return false; } +} + +let patched = 0; +for (const filePath of candidates) { + if (!(await exists(filePath))) continue; + const source = await readFile(filePath, "utf8"); + if (source.includes(MARKER)) { + console.log(`[postinstall] swarm-loc-guard: already patched (${filePath})`); + continue; + } + if (!source.includes(oldSnippet)) { + console.log(`[postinstall] swarm-loc-guard: target snippet not found in ${filePath} — skipping`); + continue; + } + await writeFile(filePath, source.replace(oldSnippet, newSnippet), "utf8"); + console.log(`[postinstall] swarm-loc-guard: patched ${filePath}`); + patched++; +} +if (patched === 0) { + console.log("[postinstall] swarm-loc-guard: nothing patched"); +}