story-research-zapwall/hooks/useAuthorPresentation.ts
2026-01-10 10:50:47 +01:00

164 lines
5.3 KiB
TypeScript

import { useState } from 'react'
import { nostrService } from '@/lib/nostr'
import { articlePublisher } from '@/lib/articlePublisher'
import type { Article } from '@/types/nostr'
import type { NostrProfile } from '@/types/nostr'
interface AuthorPresentationDraft {
authorName: string
presentation: string
contentDescription: string
mainnetAddress: string
pictureUrl?: string
}
type UseAuthorPresentationResult = {
loading: boolean
error: string | null
success: boolean
publishPresentation: (draft: AuthorPresentationDraft) => Promise<void>
checkPresentationExists: () => Promise<Article | null>
deletePresentation: (articleId: string) => Promise<void>
}
export function useAuthorPresentation(pubkey: string | null): UseAuthorPresentationResult {
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [success, setSuccess] = useState(false)
const publishPresentation = (draft: AuthorPresentationDraft): Promise<void> =>
publishAuthorPresentation({ pubkey, draft, setLoading, setError, setSuccess })
const checkPresentationExists = (): Promise<Article | null> => checkPresentation({ pubkey })
const deletePresentation = (articleId: string): Promise<void> =>
deleteAuthorPresentation({ pubkey, articleId, setLoading, setError })
return {
loading,
error,
success,
publishPresentation,
checkPresentationExists,
deletePresentation,
}
}
async function publishAuthorPresentation(params: {
pubkey: string | null
draft: AuthorPresentationDraft
setLoading: (value: boolean) => void
setError: (value: string | null) => void
setSuccess: (value: boolean) => void
}): Promise<void> {
if (!params.pubkey) {
params.setError('Clé publique non disponible')
return
}
params.setLoading(true)
params.setError(null)
try {
const privateKey = getPrivateKeyOrThrow('Clé privée requise pour publier. Veuillez vous connecter avec un portefeuille Nostr qui fournit des capacités de signature.')
await updateProfileBestEffort(params.draft)
const result = await publishPresentationArticleWithDraft({ draft: params.draft, pubkey: params.pubkey, privateKey })
params.setSuccess(result.success === true)
if (!result.success) {
params.setError(result.error ?? 'Erreur lors de la publication')
}
} catch (e) {
const errorMessage = e instanceof Error ? e.message : 'Erreur inconnue'
console.error('Error publishing presentation:', e)
params.setError(errorMessage)
} finally {
params.setLoading(false)
}
}
async function publishPresentationArticleWithDraft(params: {
draft: AuthorPresentationDraft
pubkey: string
privateKey: string
}): Promise<{ success: boolean; error?: string }> {
const { title, preview, fullContent } = buildPresentationContent(params.draft)
return articlePublisher.publishPresentationArticle(
{
title,
preview,
content: fullContent,
presentation: params.draft.presentation,
contentDescription: params.draft.contentDescription,
mainnetAddress: params.draft.mainnetAddress,
...(params.draft.pictureUrl ? { pictureUrl: params.draft.pictureUrl } : {}),
},
params.pubkey,
params.privateKey
)
}
async function updateProfileBestEffort(draft: AuthorPresentationDraft): Promise<void> {
const profileUpdates: Partial<NostrProfile> = {
name: draft.authorName.trim(),
...(draft.pictureUrl ? { picture: draft.pictureUrl } : {}),
}
try {
await nostrService.updateProfile(profileUpdates)
} catch (e) {
console.error('Error updating profile:', e)
}
}
function buildPresentationContent(draft: AuthorPresentationDraft): { title: string; preview: string; fullContent: string } {
const title = `Présentation de ${draft.authorName.trim()}`
const preview = draft.presentation.substring(0, 200)
const fullContent = `${draft.presentation}\n\n---\n\nDescription du contenu :\n${draft.contentDescription}`
return { title, preview, fullContent }
}
async function checkPresentation(params: { pubkey: string | null }): Promise<Article | null> {
if (!params.pubkey) {
return null
}
try {
return articlePublisher.getAuthorPresentation(params.pubkey)
} catch (e) {
console.error('Error checking presentation:', e)
return null
}
}
async function deleteAuthorPresentation(params: {
pubkey: string | null
articleId: string
setLoading: (value: boolean) => void
setError: (value: string | null) => void
}): Promise<void> {
if (!params.pubkey) {
throw new Error('Clé publique non disponible')
}
params.setLoading(true)
params.setError(null)
try {
const privateKey = getPrivateKeyOrThrow(
'Clé privée requise pour supprimer. Veuillez vous connecter avec un portefeuille Nostr qui fournit des capacités de signature.'
)
const { deleteArticleEvent } = await import('@/lib/articleMutations')
await deleteArticleEvent(params.articleId, params.pubkey, privateKey)
} catch (e) {
const errorMessage = e instanceof Error ? e.message : 'Erreur inconnue'
console.error('Error deleting presentation:', e)
params.setError(errorMessage)
throw e
} finally {
params.setLoading(false)
}
}
function getPrivateKeyOrThrow(message: string): string {
const privateKey = nostrService.getPrivateKey()
if (!privateKey) {
throw new Error(message)
}
return privateKey
}