import { useMemo } from "react"; import { EventKind, NoteCollection, RequestBuilder } from "@snort/system"; import { useRequestBuilder } from "@snort/system-react"; import { unixNow } from "@snort/shared"; import { findTag, toAddress, getTagValues } from "utils"; import { WEEK } from "const"; import { System } from "index"; import type { Badge } from "types"; export function useBadges(pubkey: string, leaveOpen = true): Array { const since = useMemo(() => unixNow() - WEEK, [pubkey]); const rb = useMemo(() => { const rb = new RequestBuilder(`badges:${pubkey.slice(0, 12)}`); rb.withOptions({ leaveOpen }); rb.withFilter() .authors([pubkey]) .kinds([EventKind.Badge, EventKind.BadgeAward]); return rb; }, [pubkey]); const { data: badgeEvents } = useRequestBuilder( System, NoteCollection, rb, ); const rawBadges = useMemo(() => { if (badgeEvents) { return badgeEvents .filter((e) => e.kind === EventKind.Badge) .sort((a, b) => b.created_at - a.created_at); } return []; }, [badgeEvents]); const badgeAwards = useMemo(() => { if (badgeEvents) { return badgeEvents.filter((e) => e.kind === EventKind.BadgeAward); } return []; }, [badgeEvents]); const acceptedSub = useMemo(() => { if (rawBadges.length === 0) return null; const rb = new RequestBuilder( `accepted-badges:${pubkey.slice(0, 12)}:${rawBadges.length}`, ); rb.withFilter() .kinds([EventKind.ProfileBadges]) .tag("d", ["profile_badges"]) .tag("a", rawBadges.map(toAddress)); return rb; }, [rawBadges]); const acceptedStream = useRequestBuilder( System, NoteCollection, acceptedSub, ); const acceptedEvents = acceptedStream.data ?? []; const badges = useMemo(() => { return rawBadges.map((e) => { const name = findTag(e, "d"); const address = toAddress(e); const awardEvents = badgeAwards.filter( (b) => findTag(b, "a") === address, ); const awardees = new Set( awardEvents.map((e) => getTagValues(e.tags, "p")).flat(), ); const accepted = new Set( acceptedEvents .filter((pb) => awardees.has(pb.pubkey)) .filter((pb) => pb.tags.find((t) => t.at(0) === "a" && t.at(1) === address), ) .map((pb) => pb.pubkey), ); const thumb = findTag(e, "thumb"); const image = findTag(e, "image"); return { name, thumb, image, awardees, accepted }; }); return []; }, [rawBadges]); const awards = useMemo(() => { return badgeAwards.filter((e) => e.created_at > since); }, [badgeAwards]); return { badges, awards }; }