You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

98 lines
3.4 KiB

import {
ExtendedKind,
NOTE_STATS_OP_REFERENCE_KINDS,
NOTE_STATS_OP_REFERENCE_KINDS_WITHOUT_HIGHLIGHT
} from '@/constants'
import { buildRssArticleUrlThreadInteractionFilters } from '@/lib/rss-web-feed'
import { kinds, type Filter } from 'nostr-tools'
/** Thread root shapes used by {@link buildThreadInteractionFilters} (matches ReplyNoteList `rootInfo`). */
export type ThreadInteractionRootInfo =
| { type: 'E'; id: string; pubkey: string }
| { type: 'A'; id: string; eventId: string; pubkey: string; relay?: string }
| { type: 'I'; id: string }
function sortedUniqueKinds(kindsList: readonly number[]): number[] {
return Array.from(new Set(kindsList)).sort((a, b) => a - b)
}
export type BuildThreadInteractionFiltersInput = {
root: ThreadInteractionRootInfo
/** Kind of the note/article the user opened (affects zap inclusion). */
opEventKind: number
limit: number
}
/**
* One relay wave per thread: minimal tag-scoped filters with merged `kinds` arrays.
* Client code classifies replies vs backlinks; {@link QueryService} splits only when over relay caps.
*/
export function buildThreadInteractionFilters(input: BuildThreadInteractionFiltersInput): Filter[] {
const { root, opEventKind, limit } = input
const isZapPoll = opEventKind === ExtendedKind.ZAP_POLL
const kindsNoteCommentVoiceZap = sortedUniqueKinds([
kinds.ShortTextNote,
ExtendedKind.COMMENT,
ExtendedKind.VOICE_COMMENT,
kinds.Zap
])
const kindsNoteCommentVoice = sortedUniqueKinds([
kinds.ShortTextNote,
ExtendedKind.COMMENT,
ExtendedKind.VOICE_COMMENT
])
const kindsPrimaryThread = isZapPoll ? kindsNoteCommentVoice : kindsNoteCommentVoiceZap
const kindsUpperEThread = sortedUniqueKinds(
isZapPoll
? [ExtendedKind.COMMENT, ExtendedKind.VOICE_COMMENT]
: [ExtendedKind.COMMENT, ExtendedKind.VOICE_COMMENT, kinds.Zap]
)
const kindsOnETag = sortedUniqueKinds([
...kindsPrimaryThread,
kinds.Reaction,
...NOTE_STATS_OP_REFERENCE_KINDS_WITHOUT_HIGHLIGHT
])
const kindsOnUpperETag = sortedUniqueKinds([
...kindsUpperEThread,
...NOTE_STATS_OP_REFERENCE_KINDS_WITHOUT_HIGHLIGHT
])
const kindsOnQTag = sortedUniqueKinds([
kinds.ShortTextNote,
ExtendedKind.COMMENT,
ExtendedKind.VOICE_COMMENT,
...NOTE_STATS_OP_REFERENCE_KINDS
])
if (root.type === 'I') {
return buildRssArticleUrlThreadInteractionFilters(root.id, limit)
}
const filters: Filter[] = []
if (root.type === 'E') {
filters.push({ '#e': [root.id], kinds: kindsOnETag, limit })
filters.push({ '#E': [root.id], kinds: kindsOnUpperETag, limit })
filters.push({ '#q': [root.id], kinds: kindsOnQTag, limit })
if (opEventKind === ExtendedKind.PUBLIC_MESSAGE) {
filters.push({ '#q': [root.id], kinds: [ExtendedKind.PUBLIC_MESSAGE], limit })
}
return filters
}
filters.push({ '#a': [root.id], kinds: kindsOnETag, limit })
filters.push({ '#A': [root.id], kinds: kindsOnUpperETag, limit })
if (/^[0-9a-f]{64}$/i.test(root.eventId)) {
const eSnap = root.eventId.trim().toLowerCase()
filters.push({ '#e': [eSnap], kinds: kindsOnETag, limit })
filters.push({ '#E': [eSnap], kinds: kindsOnUpperETag, limit })
}
const qVals = Array.from(
new Set([root.eventId, root.id].map((x) => (typeof x === 'string' ? x.trim() : '')).filter(Boolean))
)
if (qVals.length > 0) {
filters.push({ '#q': qVals, kinds: kindsOnQTag, limit })
}
return filters
}