Files
zap.stream/src/hooks/badges.ts
2023-08-04 18:51:49 +02:00

96 lines
2.6 KiB
TypeScript

import { useMemo } from "react";
import {
TaggedRawEvent,
EventKind,
NoteCollection,
RequestBuilder,
} from "@snort/system";
import { useRequestBuilder } from "@snort/system-react";
import { findTag, toAddress, getTagValues } from "utils";
import { System } from "index";
import type { Badge } from "types";
export function useBadges(
pubkey: string,
since: number,
leaveOpen = true
): { badges: Badge[]; awards: TaggedRawEvent[] } {
const rb = useMemo(() => {
const rb = new RequestBuilder(`badges:${pubkey.slice(0, 12)}`);
rb.withOptions({ leaveOpen });
rb.withFilter().authors([pubkey]).kinds([EventKind.Badge]);
rb.withFilter()
.authors([pubkey])
.kinds([EventKind.BadgeAward])
.since(since);
return rb;
}, [pubkey, since]);
const { data: badgeEvents } = useRequestBuilder<NoteCollection>(
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)}`);
rb.withFilter()
.kinds([EventKind.ProfileBadges])
.tag("d", ["profile_badges"])
.tag("a", rawBadges.map(toAddress));
return rb;
}, [rawBadges]);
const acceptedStream = useRequestBuilder<NoteCollection>(
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]);
return { badges, awards: badgeAwards };
}