Submissions: labeled actions + real appeal-driven unblock

Make each admin action self-explanatory and give content appeals a real
effect instead of a dead-end "Dismiss".

- submissionsSection.js: per-type action sets, each button paired with a
  one-line description. Applications show Approve (adds to whitelist) / Deny;
  appeals that name a real event show "Approve & unblock" (removes the video
  from the event block list) / "Keep blocked"; other types show "Mark handled".
- submissionService.js: parse an appeal's `e` tag into targetEventId (trusted
  only when it's a well-formed 64-char hex id).
- iframe-content-appeals-form.html: add a required "Blocked video link or
  event ID" field; regex-validate + normalize a share link / nevent / note /
  hex to the hex event id, tag it as `e`, and include it in the body. Block
  submission when no valid reference is provided.
- CSS: stacked action + hint styling; iframe-form .form-hint.
- tests: cover targetEventId parsing (valid, malformed, absent).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-07-07 09:52:04 -04:00
1 parent ef4191538c
commit 2803f6b56f
5 files changed
+263 -21

No files matched your search

@@ -45,6 +45,18 @@
placeholder="Enter the magnet link"
/>
<label for="eventPointer">Blocked video link or event ID:</label>
<input
class="form-control"
type="text"
id="eventPointer"
placeholder="Paste the video's share link, nevent1…, note1…, or 64-char event id"
/>
<p class="form-hint">
Required — open the blocked video's ⋯ menu, choose “Copy link”, and
paste it here so a moderator can locate and unblock the exact video.
</p>
<label for="submissionDate">Date of Content Submission:</label>
<input class="form-control" type="date" id="submissionDate" />
@@ -202,6 +214,36 @@
];
const pool = new SimplePool();
// Validate + normalize the blocked-video reference to a 64-char hex
// event id. Accepts a bitvid share link (which embeds an nevent), a raw
// nevent1…/note1… pointer, or a bare hex id. Returns "" when nothing
// valid is found so the caller can block submission.
const HEX_EVENT_ID = /^[0-9a-f]{64}$/i;
function extractEventHex(input) {
const trimmed = String(input || "").trim();
if (!trimmed) {
return "";
}
if (HEX_EVENT_ID.test(trimmed)) {
return trimmed.toLowerCase();
}
// Pull an nevent/note token out of a URL or free text.
const match = trimmed.match(/(nevent1[0-9a-z]+|note1[0-9a-z]+)/i);
const token = match ? match[1] : trimmed;
try {
const decoded = nip19.decode(token);
if (decoded.type === "nevent" && HEX_EVENT_ID.test(decoded.data?.id || "")) {
return decoded.data.id.toLowerCase();
}
if (decoded.type === "note" && HEX_EVENT_ID.test(decoded.data || "")) {
return decoded.data.toLowerCase();
}
} catch (err) {
// not a decodable pointer
}
return "";
}
document
.getElementById("dm-form")
.addEventListener("submit", async (ev) => {
@@ -220,6 +262,17 @@
const magnetLink = document
.getElementById("magnetLink")
.value.trim();
const eventPointer = document
.getElementById("eventPointer")
.value.trim();
const targetEventHex = extractEventHex(eventPointer);
if (!targetEventHex) {
log(
"Please paste a valid video share link, nevent1…, note1…, or 64-char event id so a moderator can locate the blocked video.",
"error"
);
return;
}
const submissionDate = document
.getElementById("submissionDate")
.value.trim();
@@ -261,6 +314,7 @@
**2. Content Details**
- **Title of the Video:** ${videoTitle}
- **Magnet Link:** ${magnetLink}
- **Blocked Event ID:** ${targetEventHex}
- **Date of Content Submission:** ${submissionDate}
**3. Reason for Appeal**
@@ -315,10 +369,9 @@ For further questions, reach out through bitvid’s Nostr support channels.
const ephemeralPubHex = getPublicKey(ephemeralPriv);
log("Ephemeral pubkey: " + ephemeralPubHex.slice(0, 16) + "...");
// Encrypt the appeal content.
log("Encrypting appeal content (nip04)...");
// Build a structured bitvid submission (kind 30083, PUBLIC — no
// encryption). Published from the ephemeral key.
log("Building appeal submission (kind 30083, public)...");
const now = Math.floor(Date.now() / 1000);
const submissionId =
"sub-" +
@@ -332,6 +385,7 @@ For further questions, reach out through bitvid’s Nostr support channels.
["d", submissionId],
["k", "appeal"],
["p", targetPubHex],
["e", targetEventHex],
["t", "bitvid-submission"],
["client", "bitvid"],
],