usePostComment.ts
1 import { useMutation, useQueryClient } from '@tanstack/react-query'; 2 import { useNostrPublish } from '@/hooks/useNostrPublish'; 3 import { NKinds, type NostrEvent } from '@nostrify/nostrify'; 4 5 interface PostCommentParams { 6 root: NostrEvent | URL; // The root event to comment on 7 reply?: NostrEvent | URL; // Optional reply to another comment 8 content: string; 9 } 10 11 /** Post a NIP-22 (kind 1111) comment on an event. */ 12 export function usePostComment() { 13 const { mutateAsync: publishEvent } = useNostrPublish(); 14 const queryClient = useQueryClient(); 15 16 return useMutation({ 17 mutationFn: async ({ root, reply, content }: PostCommentParams) => { 18 const tags: string[][] = []; 19 20 // d-tag identifiers 21 const dRoot = root instanceof URL ? '' : root.tags.find(([name]) => name === 'd')?.[1] ?? ''; 22 const dReply = reply instanceof URL ? '' : reply?.tags.find(([name]) => name === 'd')?.[1] ?? ''; 23 24 // Root event tags 25 if (root instanceof URL) { 26 tags.push(['I', root.toString()]); 27 } else if (NKinds.addressable(root.kind)) { 28 tags.push(['A', `${root.kind}:${root.pubkey}:${dRoot}`]); 29 } else if (NKinds.replaceable(root.kind)) { 30 tags.push(['A', `${root.kind}:${root.pubkey}:`]); 31 } else { 32 tags.push(['E', root.id]); 33 } 34 if (root instanceof URL) { 35 tags.push(['K', root.hostname]); 36 } else { 37 tags.push(['K', root.kind.toString()]); 38 tags.push(['P', root.pubkey]); 39 } 40 41 // Reply event tags 42 if (reply) { 43 if (reply instanceof URL) { 44 tags.push(['i', reply.toString()]); 45 } else if (NKinds.addressable(reply.kind)) { 46 tags.push(['a', `${reply.kind}:${reply.pubkey}:${dReply}`]); 47 } else if (NKinds.replaceable(reply.kind)) { 48 tags.push(['a', `${reply.kind}:${reply.pubkey}:`]); 49 } else { 50 tags.push(['e', reply.id]); 51 } 52 if (reply instanceof URL) { 53 tags.push(['k', reply.hostname]); 54 } else { 55 tags.push(['k', reply.kind.toString()]); 56 tags.push(['p', reply.pubkey]); 57 } 58 } else { 59 // If this is a top-level comment, use the root event's tags 60 if (root instanceof URL) { 61 tags.push(['i', root.toString()]); 62 } else if (NKinds.addressable(root.kind)) { 63 tags.push(['a', `${root.kind}:${root.pubkey}:${dRoot}`]); 64 } else if (NKinds.replaceable(root.kind)) { 65 tags.push(['a', `${root.kind}:${root.pubkey}:`]); 66 } else { 67 tags.push(['e', root.id]); 68 } 69 if (root instanceof URL) { 70 tags.push(['k', root.hostname]); 71 } else { 72 tags.push(['k', root.kind.toString()]); 73 tags.push(['p', root.pubkey]); 74 } 75 } 76 77 const event = await publishEvent({ 78 kind: 1111, 79 content, 80 tags, 81 }); 82 83 return event; 84 }, 85 onSuccess: (_, { root }) => { 86 // Invalidate and refetch comments 87 queryClient.invalidateQueries({ 88 queryKey: ['nostr', 'comments', root instanceof URL ? root.toString() : root.id] 89 }); 90 }, 91 }); 92 }