mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
Insert "emoji" tags into statuses
This commit is contained in:
parent
b1a1ace0ac
commit
28275b7611
3 changed files with 94 additions and 74 deletions
|
|
@ -16,6 +16,7 @@ import { lookupPubkey } from '@/utils/lookup.ts';
|
|||
import { languageSchema } from '@/schema.ts';
|
||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||
import { assertAuthenticated, createEvent, parseBody, updateListEvent } from '@/utils/api.ts';
|
||||
import { getCustomEmojis } from '@/utils/custom-emoji.ts';
|
||||
import { getInvoice, getLnurl } from '@/utils/lnurl.ts';
|
||||
import { purifyEvent } from '@/utils/purify.ts';
|
||||
import { getZapSplits } from '@/utils/zap-split.ts';
|
||||
|
|
@ -190,6 +191,23 @@ const createStatusController: AppController = async (c) => {
|
|||
}
|
||||
}
|
||||
|
||||
const shortcodes = new Set<string>();
|
||||
|
||||
for (const [, shortcode] of data.status?.matchAll(/(?<!\w):(\w+):(?!\w)/g) ?? []) {
|
||||
shortcodes.add(shortcode);
|
||||
}
|
||||
|
||||
if (shortcodes.size) {
|
||||
const emojis = await getCustomEmojis(await user!.signer.getPublicKey(), c.var);
|
||||
|
||||
for (const shortcode of shortcodes) {
|
||||
const emoji = emojis.get(shortcode);
|
||||
if (emoji) {
|
||||
tags.push(['emoji', shortcode, emoji.url.toString()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const pubkey = await user!.signer.getPublicKey();
|
||||
const author = pubkey ? await getAuthor(pubkey, c.var) : undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { userMiddleware } from '@ditto/mastoapi/middleware';
|
||||
import { DittoRoute } from '@ditto/mastoapi/router';
|
||||
import { NostrFilter, NRelay } from '@nostrify/nostrify';
|
||||
|
||||
import { getCustomEmojis } from '@/utils/custom-emoji.ts';
|
||||
|
||||
const route = new DittoRoute();
|
||||
|
||||
|
|
@ -29,77 +30,4 @@ route.get('/', userMiddleware(), async (c) => {
|
|||
}));
|
||||
});
|
||||
|
||||
interface GetCustomEmojisOpts {
|
||||
relay: NRelay;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
async function getCustomEmojis(
|
||||
pubkey: string,
|
||||
opts: GetCustomEmojisOpts,
|
||||
): Promise<Map<string, { url: URL; category?: string }>> {
|
||||
const { relay, signal } = opts;
|
||||
|
||||
const emojis = new Map<string, { url: URL; category?: string }>();
|
||||
|
||||
const [emojiList] = await relay.query([{ kinds: [10030], authors: [pubkey] }], { signal });
|
||||
|
||||
if (!emojiList) {
|
||||
return emojis;
|
||||
}
|
||||
|
||||
const a = new Set<string>();
|
||||
|
||||
for (const tag of emojiList.tags) {
|
||||
if (tag[0] === 'emoji') {
|
||||
const [, shortcode, url] = tag;
|
||||
|
||||
if (!emojis.has(shortcode)) {
|
||||
try {
|
||||
emojis.set(shortcode, { url: new URL(url) });
|
||||
} catch {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tag[0] === 'a') {
|
||||
a.add(tag[1]);
|
||||
}
|
||||
}
|
||||
|
||||
const filters: NostrFilter[] = [];
|
||||
|
||||
for (const addr of a) {
|
||||
const match = addr.match(/^30030:([0-9a-f]{64}):(.+)$/);
|
||||
|
||||
if (match) {
|
||||
const [, pubkey, d] = match;
|
||||
filters.push({ kinds: [30030], authors: [pubkey], '#d': [d] });
|
||||
}
|
||||
}
|
||||
|
||||
if (!filters.length) {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
for (const event of await relay.query(filters, { signal })) {
|
||||
const d = event.tags.find(([name]) => name === 'd')?.[1];
|
||||
|
||||
for (const [t, shortcode, url] of event.tags) {
|
||||
if (t === 'emoji') {
|
||||
if (!emojis.has(shortcode)) {
|
||||
try {
|
||||
emojis.set(shortcode, { url: new URL(url), category: d });
|
||||
} catch {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return emojis;
|
||||
}
|
||||
|
||||
export default route;
|
||||
|
|
|
|||
74
packages/ditto/utils/custom-emoji.ts
Normal file
74
packages/ditto/utils/custom-emoji.ts
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import type { NostrFilter, NRelay } from '@nostrify/nostrify';
|
||||
|
||||
interface GetCustomEmojisOpts {
|
||||
relay: NRelay;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
export async function getCustomEmojis(
|
||||
pubkey: string,
|
||||
opts: GetCustomEmojisOpts,
|
||||
): Promise<Map<string, { url: URL; category?: string }>> {
|
||||
const { relay, signal } = opts;
|
||||
|
||||
const emojis = new Map<string, { url: URL; category?: string }>();
|
||||
|
||||
const [emojiList] = await relay.query([{ kinds: [10030], authors: [pubkey] }], { signal });
|
||||
|
||||
if (!emojiList) {
|
||||
return emojis;
|
||||
}
|
||||
|
||||
const a = new Set<string>();
|
||||
|
||||
for (const tag of emojiList.tags) {
|
||||
if (tag[0] === 'emoji') {
|
||||
const [, shortcode, url] = tag;
|
||||
|
||||
if (!emojis.has(shortcode)) {
|
||||
try {
|
||||
emojis.set(shortcode, { url: new URL(url) });
|
||||
} catch {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tag[0] === 'a') {
|
||||
a.add(tag[1]);
|
||||
}
|
||||
}
|
||||
|
||||
const filters: NostrFilter[] = [];
|
||||
|
||||
for (const addr of a) {
|
||||
const match = addr.match(/^30030:([0-9a-f]{64}):(.+)$/);
|
||||
|
||||
if (match) {
|
||||
const [, pubkey, d] = match;
|
||||
filters.push({ kinds: [30030], authors: [pubkey], '#d': [d] });
|
||||
}
|
||||
}
|
||||
|
||||
if (!filters.length) {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
for (const event of await relay.query(filters, { signal })) {
|
||||
const d = event.tags.find(([name]) => name === 'd')?.[1];
|
||||
|
||||
for (const [t, shortcode, url] of event.tags) {
|
||||
if (t === 'emoji') {
|
||||
if (!emojis.has(shortcode)) {
|
||||
try {
|
||||
emojis.set(shortcode, { url: new URL(url), category: d });
|
||||
} catch {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return emojis;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue