2024-09-23 20:57:29 +05:00
|
|
|
import {
|
2024-10-24 21:07:18 +05:00
|
|
|
getRelayListForUser,
|
2024-10-14 19:20:43 +05:00
|
|
|
NDKFilter,
|
|
|
|
NDKKind,
|
2024-10-24 21:07:18 +05:00
|
|
|
NDKRelaySet,
|
2024-10-14 19:20:43 +05:00
|
|
|
NDKSubscription,
|
|
|
|
NDKSubscriptionCacheUsage
|
|
|
|
} from '@nostr-dev-kit/ndk'
|
|
|
|
import { useEffect, useState } from 'react'
|
2024-11-05 13:57:39 +01:00
|
|
|
import { CommentEvent, UserRelaysType } from 'types'
|
2024-10-24 21:07:18 +05:00
|
|
|
import { log, LogType, timeout } from 'utils'
|
2024-10-14 19:20:43 +05:00
|
|
|
import { useNDKContext } from './useNDKContext'
|
2025-02-25 10:26:17 +01:00
|
|
|
import _ from 'lodash'
|
2024-09-23 20:57:29 +05:00
|
|
|
|
2024-11-05 13:57:39 +01:00
|
|
|
export const useComments = (
|
|
|
|
author: string | undefined,
|
2025-01-29 21:23:29 +01:00
|
|
|
aTag: string | undefined,
|
|
|
|
eTag?: string | undefined
|
2024-11-05 13:57:39 +01:00
|
|
|
) => {
|
2024-10-14 19:20:43 +05:00
|
|
|
const { ndk } = useNDKContext()
|
2024-09-23 20:57:29 +05:00
|
|
|
const [commentEvents, setCommentEvents] = useState<CommentEvent[]>([])
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
useEffect(() => {
|
2025-01-29 21:23:29 +01:00
|
|
|
if (!(author && (aTag || eTag))) {
|
|
|
|
// Author and aTag/eTag are required
|
2024-11-05 13:57:39 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
let subscription: NDKSubscription // Define the subscription variable here for cleanup
|
2024-09-23 20:57:29 +05:00
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const setupSubscription = async () => {
|
2024-10-24 21:07:18 +05:00
|
|
|
// Find the mod author's relays.
|
|
|
|
|
|
|
|
const authorReadRelays = await Promise.race([
|
2024-11-05 13:57:39 +01:00
|
|
|
getRelayListForUser(author, ndk),
|
2024-10-24 21:07:18 +05:00
|
|
|
timeout(10 * 1000) // add a 10 sec timeout
|
|
|
|
])
|
|
|
|
.then((ndkRelayList) => {
|
|
|
|
if (ndkRelayList) return ndkRelayList[UserRelaysType.Read]
|
|
|
|
return [] // Return an empty array if ndkRelayList is undefined
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
log(
|
2024-12-26 16:40:40 +01:00
|
|
|
false, // Too many failed requests, turned off for clarity
|
2024-10-24 21:07:18 +05:00
|
|
|
LogType.Error,
|
2024-11-05 13:57:39 +01:00
|
|
|
`An error occurred in fetching user's (${author}) ${UserRelaysType.Read}`,
|
2024-10-24 21:07:18 +05:00
|
|
|
err
|
|
|
|
)
|
|
|
|
return [] as string[]
|
|
|
|
})
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const filter: NDKFilter = {
|
2025-01-28 15:35:30 +01:00
|
|
|
kinds: [NDKKind.Text, NDKKind.GenericReply],
|
2025-01-29 21:23:29 +01:00
|
|
|
...(aTag
|
|
|
|
? {
|
|
|
|
'#a': [aTag]
|
|
|
|
}
|
|
|
|
: {}),
|
|
|
|
...(eTag
|
|
|
|
? {
|
|
|
|
'#e': [eTag]
|
|
|
|
}
|
|
|
|
: {})
|
2024-10-14 19:20:43 +05:00
|
|
|
}
|
|
|
|
|
2024-10-24 21:07:18 +05:00
|
|
|
const relayUrls = new Set<string>()
|
|
|
|
|
|
|
|
ndk.pool.urls().forEach((relayUrl) => {
|
|
|
|
relayUrls.add(relayUrl)
|
2024-10-24 20:29:57 +05:00
|
|
|
})
|
|
|
|
|
2024-10-24 21:07:18 +05:00
|
|
|
authorReadRelays.forEach((relayUrl) => relayUrls.add(relayUrl))
|
|
|
|
|
|
|
|
subscription = ndk.subscribe(
|
|
|
|
filter,
|
|
|
|
{
|
|
|
|
closeOnEose: false,
|
|
|
|
cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST
|
|
|
|
},
|
2024-11-20 13:50:49 +01:00
|
|
|
relayUrls.size
|
|
|
|
? NDKRelaySet.fromRelayUrls(Array.from(relayUrls), ndk)
|
|
|
|
: undefined
|
2024-10-24 21:07:18 +05:00
|
|
|
)
|
2024-09-23 20:57:29 +05:00
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
subscription.on('event', (ndkEvent) => {
|
2025-02-20 18:44:07 +01:00
|
|
|
const eTags = ndkEvent.getMatchingTags('e')
|
|
|
|
const aTags = ndkEvent.getMatchingTags('a')
|
|
|
|
|
|
|
|
// This event is not a reply to, nor does it refer to any other event
|
|
|
|
if (!aTags.length && !eTags.length) return
|
|
|
|
|
2024-09-23 20:57:29 +05:00
|
|
|
setCommentEvents((prev) => {
|
2025-02-20 18:44:07 +01:00
|
|
|
if (ndkEvent.kind === NDKKind.Text) {
|
|
|
|
// Resolve comments with markers and positional "e" tags
|
|
|
|
// https://github.com/nostr-protocol/nips/blob/master/10.md
|
|
|
|
const root = ndkEvent.getMatchingTags('e', 'root')
|
|
|
|
const replies = ndkEvent.getMatchingTags('e', 'reply')
|
|
|
|
|
|
|
|
// This event has reply markers but does not match eTag
|
|
|
|
if (replies.length && !replies.some((e) => eTag === e[1])) {
|
|
|
|
return [...prev]
|
|
|
|
}
|
|
|
|
|
|
|
|
// This event has a single #e tag reference
|
|
|
|
// Checks single marked event (root) and a single positional "e" tags
|
|
|
|
// Allow if either old kind 1 reply to addressable or matches eTag
|
2025-02-25 10:26:17 +01:00
|
|
|
if (eTags.length === 1 && !(aTag || eTag === _.first(eTags)?.[1])) {
|
2025-02-20 18:44:07 +01:00
|
|
|
return [...prev]
|
|
|
|
}
|
|
|
|
|
2025-02-25 10:26:17 +01:00
|
|
|
// Position "e" tags (no markers)
|
2025-02-20 18:44:07 +01:00
|
|
|
// Multiple e tags, checks the last "e" tag
|
|
|
|
// Last "e" tag does not match eTag
|
|
|
|
if (
|
|
|
|
root.length + replies.length === 0 &&
|
|
|
|
eTags.length > 1 &&
|
2025-02-25 10:26:17 +01:00
|
|
|
_.last(eTags)?.[1] !== eTag
|
2025-02-20 18:44:07 +01:00
|
|
|
) {
|
|
|
|
return [...prev]
|
|
|
|
}
|
2025-02-25 10:26:17 +01:00
|
|
|
|
|
|
|
// "e" tags with markets
|
|
|
|
// Multiple replies, checks the last "e" tag
|
|
|
|
// Only show direct replies
|
|
|
|
if (replies.length > 1 && _.last(replies)?.[1] !== eTag) {
|
|
|
|
return [...prev]
|
|
|
|
}
|
2025-02-20 18:44:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Event is already included
|
|
|
|
if (prev.find((comment) => comment.event.id === ndkEvent.id)) {
|
2024-09-23 20:57:29 +05:00
|
|
|
return [...prev]
|
|
|
|
}
|
|
|
|
|
2025-02-20 18:44:07 +01:00
|
|
|
// Event is a direct reply
|
2025-01-28 15:35:30 +01:00
|
|
|
return [{ event: ndkEvent }, ...prev]
|
2024-09-23 20:57:29 +05:00
|
|
|
})
|
2024-10-14 19:20:43 +05:00
|
|
|
})
|
|
|
|
|
|
|
|
subscription.start()
|
|
|
|
}
|
|
|
|
|
|
|
|
setupSubscription()
|
|
|
|
|
|
|
|
// Cleanup function to stop the subscription on unmount
|
|
|
|
return () => {
|
|
|
|
if (subscription) {
|
|
|
|
subscription.stop()
|
2024-09-23 20:57:29 +05:00
|
|
|
}
|
2024-10-14 19:20:43 +05:00
|
|
|
}
|
2025-01-29 21:23:29 +01:00
|
|
|
}, [aTag, author, eTag, ndk])
|
2024-09-23 20:57:29 +05:00
|
|
|
|
|
|
|
return {
|
|
|
|
commentEvents,
|
|
|
|
setCommentEvents
|
|
|
|
}
|
|
|
|
}
|