86 lines
4.1 KiB
TypeScript
86 lines
4.1 KiB
TypeScript
import type { Article } from '@/types/nostr'
|
|
import { nostrService } from '../nostr'
|
|
import { getPublishRelays } from '../relaySelection'
|
|
import { ensureKeys } from './shared'
|
|
|
|
export async function deleteArticleEvent(articleId: string, authorPubkey: string, authorPrivateKey?: string): Promise<void> {
|
|
ensureKeys(authorPubkey, authorPrivateKey)
|
|
const originalEvent = await getOriginalPublicationEventOrThrow(articleId)
|
|
assertAuthorOwnsEvent({ eventPubkey: originalEvent.pubkey, authorPubkey })
|
|
const deleteEventTemplate = await buildDeleteEventTemplateOrThrow({ originalEvent, authorPubkey })
|
|
const originalParsed = await parseOriginalArticleOrThrow(originalEvent)
|
|
const deletePayload = await buildDeletedArticlePayload({ originalParsed, deleteEventTemplate })
|
|
const event = await finalizeEventTemplate({ template: deleteEventTemplate, authorPrivateKey })
|
|
const relays = await getPublishRelays()
|
|
await publishDeletion({ event, relays, payload: deletePayload })
|
|
}
|
|
|
|
async function getOriginalPublicationEventOrThrow(articleId: string): Promise<import('nostr-tools').Event> {
|
|
const { objectCache } = await import('../objectCache')
|
|
const originalEvent = await objectCache.getEventById('publication', articleId)
|
|
if (!originalEvent) {
|
|
throw new Error('Article not found in cache')
|
|
}
|
|
return originalEvent
|
|
}
|
|
|
|
function assertAuthorOwnsEvent(params: { eventPubkey: string; authorPubkey: string }): void {
|
|
if (params.eventPubkey !== params.authorPubkey) {
|
|
throw new Error('Only the author can delete this article')
|
|
}
|
|
}
|
|
|
|
async function buildDeleteEventTemplateOrThrow(params: { originalEvent: import('nostr-tools').Event; authorPubkey: string }): Promise<import('nostr-tools').EventTemplate> {
|
|
const { buildDeleteEvent } = await import('../objectModification')
|
|
const template = await buildDeleteEvent(params.originalEvent, params.authorPubkey)
|
|
if (!template) {
|
|
throw new Error('Failed to build delete event')
|
|
}
|
|
return template
|
|
}
|
|
|
|
async function parseOriginalArticleOrThrow(originalEvent: import('nostr-tools').Event): Promise<Article> {
|
|
const { parseArticleFromEvent } = await import('../nostrEventParsing')
|
|
const parsed = await parseArticleFromEvent(originalEvent)
|
|
if (!parsed) {
|
|
throw new Error('Failed to parse original article')
|
|
}
|
|
return parsed
|
|
}
|
|
|
|
async function buildDeletedArticlePayload(params: { originalParsed: Article; deleteEventTemplate: import('nostr-tools').EventTemplate }): Promise<{ hash: string; index: number; version: number; parsed: Article }> {
|
|
const { extractTagsFromEvent } = await import('../nostrTagSystem')
|
|
const tags = extractTagsFromEvent(params.deleteEventTemplate)
|
|
const version = tags.version ?? params.originalParsed.version + 1
|
|
const index = params.originalParsed.index ?? 0
|
|
const parsed: Article = { ...params.originalParsed, version }
|
|
return { hash: params.originalParsed.hash, index, version, parsed }
|
|
}
|
|
|
|
async function finalizeEventTemplate(params: { template: import('nostr-tools').EventTemplate; authorPrivateKey: string | undefined }): Promise<import('nostr-tools').Event> {
|
|
const privateKey = params.authorPrivateKey ?? nostrService.getPrivateKey()
|
|
if (!privateKey) {
|
|
throw new Error('Private key required for signing')
|
|
}
|
|
const { writeOrchestrator } = await import('../writeOrchestrator')
|
|
writeOrchestrator.setPrivateKey(privateKey)
|
|
const { finalizeEvent } = await import('nostr-tools')
|
|
const { hexToBytes } = await import('nostr-tools/utils')
|
|
return finalizeEvent(params.template, hexToBytes(privateKey))
|
|
}
|
|
|
|
async function publishDeletion(params: {
|
|
event: import('nostr-tools').Event
|
|
relays: string[]
|
|
payload: { hash: string; index: number; version: number; parsed: Article }
|
|
}): Promise<void> {
|
|
const { writeOrchestrator } = await import('../writeOrchestrator')
|
|
const result = await writeOrchestrator.writeAndPublish(
|
|
{ objectType: 'publication', hash: params.payload.hash, event: params.event, parsed: params.payload.parsed, version: params.payload.version, hidden: true, index: params.payload.index },
|
|
params.relays
|
|
)
|
|
if (!result.success) {
|
|
throw new Error('Failed to publish delete event')
|
|
}
|
|
}
|