Allow users to delete their messages
No more than 30 minutes old
This commit is contained in:
parent
2daaec15fa
commit
9e26e9dc60
3 changed files with 76 additions and 16 deletions
|
|
@ -1,12 +1,24 @@
|
|||
import { auth } from "$lib/auth.svelte";
|
||||
import { publishForum } from "$lib/relay";
|
||||
|
||||
// Users may delete their own posts only within this window; afterwards the relay
|
||||
// also refuses (pyramid caps group self-deletes at 2h, we're stricter on top).
|
||||
export const SELF_DELETE_WINDOW = 30 * 60; // seconds
|
||||
|
||||
export function withinSelfDeleteWindow(createdAt: number): boolean {
|
||||
return Math.floor(Date.now() / 1000) - createdAt <= SELF_DELETE_WINDOW;
|
||||
}
|
||||
|
||||
// What's pending deletion, surfaced to the confirmation modal. `label` is the
|
||||
// noun shown in the dialog copy ("discussion", "reply", "message").
|
||||
// noun shown in the dialog copy ("discussion", "reply", "message"). `self` picks
|
||||
// the mechanism: authors delete via NIP-09 (kind 5), admins moderate via
|
||||
// NIP-29 (kind 9005). `eventKind` feeds the NIP-09 `k` tag.
|
||||
type DeleteTarget = {
|
||||
eventId: string;
|
||||
groupId: string;
|
||||
label: string;
|
||||
self?: boolean;
|
||||
eventKind?: number;
|
||||
};
|
||||
|
||||
let target = $state<DeleteTarget | null>(null);
|
||||
|
|
@ -45,8 +57,9 @@ export function cancelDelete() {
|
|||
error = null;
|
||||
}
|
||||
|
||||
// NIP-29 kind:9005 delete-event. The relay enforces the role check and only
|
||||
// resolves the publish (OK: true) once it has processed the deletion.
|
||||
// Authors self-delete with NIP-09 (kind 5); admins moderate with NIP-29
|
||||
// (kind 9005). The relay enforces the matching rule (author match / role) and
|
||||
// only resolves the publish (OK: true) once it has processed the deletion.
|
||||
export async function confirmDelete(reason?: string) {
|
||||
if (!target) return;
|
||||
if (!auth.signer) {
|
||||
|
|
@ -56,21 +69,28 @@ export async function confirmDelete(reason?: string) {
|
|||
busy = true;
|
||||
error = null;
|
||||
|
||||
const kind = target.self ? 5 : 9005;
|
||||
const tags: string[][] = [
|
||||
["h", target.groupId],
|
||||
["e", target.eventId],
|
||||
];
|
||||
if (target.self && target.eventKind !== undefined) {
|
||||
tags.push(["k", String(target.eventKind)]);
|
||||
}
|
||||
|
||||
try {
|
||||
const signed = await auth.signer.signEvent({
|
||||
kind: 9005,
|
||||
kind,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags,
|
||||
content: reason?.trim() ?? "",
|
||||
});
|
||||
|
||||
const timeout = new Promise<never>((_, reject) =>
|
||||
setTimeout(() => reject(new Error("Relay did not respond in time")), 8000),
|
||||
setTimeout(
|
||||
() => reject(new Error("Relay did not respond in time")),
|
||||
8000,
|
||||
),
|
||||
);
|
||||
await Promise.race([Promise.all(publishForum(signed)), timeout]);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue