116 lines
2.6 KiB
TypeScript
116 lines
2.6 KiB
TypeScript
import {
|
|
RequestBuilder,
|
|
EventKind,
|
|
ReplaceableNoteStore,
|
|
NoteCollection,
|
|
NostrEvent,
|
|
} from "@snort/system";
|
|
import { useRequestBuilder } from "@snort/system-react";
|
|
import { System } from "index";
|
|
import { useMemo } from "react";
|
|
import { findTag } from "utils";
|
|
import type { EmojiTag } from "../element/emoji";
|
|
import uniqBy from "lodash.uniqby";
|
|
|
|
export interface Emoji {
|
|
native?: string;
|
|
id?: string;
|
|
}
|
|
|
|
export interface EmojiPack {
|
|
address: string;
|
|
name: string;
|
|
author: string;
|
|
emojis: EmojiTag[];
|
|
}
|
|
|
|
function cleanShortcode(shortcode?: string) {
|
|
return shortcode?.replace(/\s+/, "_");
|
|
}
|
|
|
|
function toEmojiPack(ev: NostrEvent): EmojiPack {
|
|
const d = findTag(ev, "d") || "";
|
|
return {
|
|
address: `${ev.kind}:${ev.pubkey}:${d}`,
|
|
name: d,
|
|
author: ev.pubkey,
|
|
emojis: ev.tags
|
|
.filter((t) => t.at(0) === "emoji")
|
|
.map((t) => ["emoji", cleanShortcode(t.at(1)), t.at(2)]) as EmojiTag[],
|
|
};
|
|
}
|
|
|
|
export function packId(pack: EmojiPack): string {
|
|
return `${pack.author}:${pack.name}`;
|
|
}
|
|
|
|
export default function useEmoji(pubkey?: string) {
|
|
const sub = useMemo(() => {
|
|
if(!pubkey) return null;
|
|
const rb = new RequestBuilder(`emoji:${pubkey}`);
|
|
|
|
rb.withFilter()
|
|
.authors([pubkey])
|
|
.kinds([10030 as EventKind]);
|
|
|
|
return rb;
|
|
}, [pubkey]);
|
|
|
|
const { data: userEmoji } = useRequestBuilder<ReplaceableNoteStore>(
|
|
System,
|
|
ReplaceableNoteStore,
|
|
sub
|
|
);
|
|
|
|
const related = useMemo(() => {
|
|
if (userEmoji) {
|
|
return userEmoji.tags.filter(
|
|
(t) => t.at(0) === "a" && t.at(1)?.startsWith(`30030:`)
|
|
);
|
|
}
|
|
return [];
|
|
}, [userEmoji]);
|
|
|
|
const subRelated = useMemo(() => {
|
|
if(!pubkey) return null;
|
|
const splitted = related.map((t) => t.at(1)!.split(":"));
|
|
const authors = splitted
|
|
.map((s) => s.at(1))
|
|
.filter((s) => s)
|
|
.map((s) => s as string);
|
|
const identifiers = splitted
|
|
.map((s) => s.at(2))
|
|
.filter((s) => s)
|
|
.map((s) => s as string);
|
|
|
|
const rb = new RequestBuilder(`emoji-related:${pubkey}`);
|
|
|
|
rb.withFilter()
|
|
.kinds([30030 as EventKind])
|
|
.authors(authors)
|
|
.tag("d", identifiers);
|
|
|
|
rb.withFilter()
|
|
.kinds([30030 as EventKind])
|
|
.authors([pubkey]);
|
|
|
|
return rb;
|
|
}, [pubkey, related]);
|
|
|
|
const { data: relatedData } = useRequestBuilder<NoteCollection>(
|
|
System,
|
|
NoteCollection,
|
|
subRelated
|
|
);
|
|
|
|
const emojiPacks = useMemo(() => {
|
|
return relatedData ?? [];
|
|
}, [relatedData]);
|
|
|
|
const emojis = useMemo(() => {
|
|
return uniqBy(emojiPacks.map(toEmojiPack), packId);
|
|
}, [emojiPacks]);
|
|
|
|
return emojis;
|
|
}
|