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.
92 lines
3.1 KiB
92 lines
3.1 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 kindsNoteCommentVoiceZap = sortedUniqueKinds([ |
|
kinds.ShortTextNote, |
|
ExtendedKind.COMMENT, |
|
ExtendedKind.VOICE_COMMENT, |
|
kinds.Zap |
|
]) |
|
const kindsPrimaryThread = kindsNoteCommentVoiceZap |
|
const kindsUpperEThread = sortedUniqueKinds([ |
|
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 |
|
}
|
|
|