feat: trust score filter
This commit is contained in:
parent
43f4c34fb3
commit
5f785e5553
48 changed files with 974 additions and 480 deletions
160
src/hooks/useFilteredReplies.tsx
Normal file
160
src/hooks/useFilteredReplies.tsx
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
import { getEventKey, isMentioningMutedUsers } from '@/lib/event'
|
||||
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
|
||||
import { useMuteList } from '@/providers/MuteListProvider'
|
||||
import { useNostr } from '@/providers/NostrProvider'
|
||||
import { useUserTrust } from '@/providers/UserTrustProvider'
|
||||
import { NostrEvent } from 'nostr-tools'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useAllDescendantThreads } from './useThread'
|
||||
|
||||
export function useFilteredReplies(stuffKey: string) {
|
||||
const { pubkey } = useNostr()
|
||||
const { minTrustScore, meetsMinTrustScore } = useUserTrust()
|
||||
const { mutePubkeySet } = useMuteList()
|
||||
const { hideContentMentioningMutedUsers } = useContentPolicy()
|
||||
const allThreads = useAllDescendantThreads(stuffKey)
|
||||
const [replies, setReplies] = useState<NostrEvent[]>([])
|
||||
const [hasReplied, setHasReplied] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const filterReplies = async () => {
|
||||
const replyKeySet = new Set<string>()
|
||||
const thread = allThreads.get(stuffKey) || []
|
||||
const filtered: NostrEvent[] = []
|
||||
|
||||
await Promise.all(
|
||||
thread.map(async (evt) => {
|
||||
const key = getEventKey(evt)
|
||||
if (replyKeySet.has(key)) return
|
||||
replyKeySet.add(key)
|
||||
|
||||
if (mutePubkeySet.has(evt.pubkey)) return
|
||||
if (hideContentMentioningMutedUsers && isMentioningMutedUsers(evt, mutePubkeySet)) return
|
||||
|
||||
const meetsTrust = await meetsMinTrustScore(evt.pubkey)
|
||||
if (!meetsTrust) {
|
||||
const replyKey = getEventKey(evt)
|
||||
const repliesForThisReply = allThreads.get(replyKey)
|
||||
// If the reply is not trusted, check if there are any trusted replies for this reply
|
||||
if (repliesForThisReply && repliesForThisReply.length > 0) {
|
||||
let hasTrustedReply = false
|
||||
for (const reply of repliesForThisReply) {
|
||||
if (await meetsMinTrustScore(reply.pubkey)) {
|
||||
hasTrustedReply = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!hasTrustedReply) return
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
filtered.push(evt)
|
||||
})
|
||||
)
|
||||
|
||||
filtered.sort((a, b) => b.created_at - a.created_at)
|
||||
setReplies(filtered)
|
||||
}
|
||||
|
||||
filterReplies()
|
||||
}, [
|
||||
stuffKey,
|
||||
allThreads,
|
||||
mutePubkeySet,
|
||||
hideContentMentioningMutedUsers,
|
||||
minTrustScore,
|
||||
meetsMinTrustScore
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
let replied = false
|
||||
for (const reply of replies) {
|
||||
if (reply.pubkey === pubkey) {
|
||||
replied = true
|
||||
break
|
||||
}
|
||||
}
|
||||
setHasReplied(replied)
|
||||
}, [replies, pubkey])
|
||||
|
||||
return { replies, hasReplied }
|
||||
}
|
||||
|
||||
export function useFilteredAllReplies(stuffKey: string) {
|
||||
const { pubkey } = useNostr()
|
||||
const allThreads = useAllDescendantThreads(stuffKey)
|
||||
const { minTrustScore, meetsMinTrustScore } = useUserTrust()
|
||||
const { mutePubkeySet } = useMuteList()
|
||||
const { hideContentMentioningMutedUsers } = useContentPolicy()
|
||||
const [replies, setReplies] = useState<NostrEvent[]>([])
|
||||
const [hasReplied, setHasReplied] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const filterReplies = async () => {
|
||||
const replyKeySet = new Set<string>()
|
||||
const replyEvents: NostrEvent[] = []
|
||||
|
||||
let parentKeys = [stuffKey]
|
||||
while (parentKeys.length > 0) {
|
||||
const events = parentKeys.flatMap((key) => allThreads.get(key) ?? [])
|
||||
await Promise.all(
|
||||
events.map(async (evt) => {
|
||||
const key = getEventKey(evt)
|
||||
if (replyKeySet.has(key)) return
|
||||
replyKeySet.add(key)
|
||||
|
||||
if (mutePubkeySet.has(evt.pubkey)) return
|
||||
if (hideContentMentioningMutedUsers && isMentioningMutedUsers(evt, mutePubkeySet))
|
||||
return
|
||||
|
||||
const meetsTrust = await meetsMinTrustScore(evt.pubkey)
|
||||
if (!meetsTrust) {
|
||||
const replyKey = getEventKey(evt)
|
||||
const repliesForThisReply = allThreads.get(replyKey)
|
||||
// If the reply is not trusted, check if there are any trusted replies for this reply
|
||||
if (repliesForThisReply && repliesForThisReply.length > 0) {
|
||||
let hasTrustedReply = false
|
||||
for (const reply of repliesForThisReply) {
|
||||
if (await meetsMinTrustScore(reply.pubkey)) {
|
||||
hasTrustedReply = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!hasTrustedReply) return
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
replyEvents.push(evt)
|
||||
})
|
||||
)
|
||||
parentKeys = events.map((evt) => getEventKey(evt))
|
||||
}
|
||||
setReplies(replyEvents.sort((a, b) => a.created_at - b.created_at))
|
||||
}
|
||||
|
||||
filterReplies()
|
||||
}, [
|
||||
stuffKey,
|
||||
allThreads,
|
||||
mutePubkeySet,
|
||||
hideContentMentioningMutedUsers,
|
||||
minTrustScore,
|
||||
meetsMinTrustScore
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
let replied = false
|
||||
for (const reply of replies) {
|
||||
if (reply.pubkey === pubkey) {
|
||||
replied = true
|
||||
break
|
||||
}
|
||||
}
|
||||
setHasReplied(replied)
|
||||
}, [replies, pubkey])
|
||||
|
||||
return { replies, hasReplied }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue