Resolve custom emojis from federated posts

This commit is contained in:
Jesse Wierzbinski 2024-04-10 15:40:43 -10:00
parent ec7b5dcbab
commit 275244b941
No known key found for this signature in database
3 changed files with 54 additions and 16 deletions

View file

@ -2,6 +2,7 @@ import type { Emoji } from "@prisma/client";
import { client } from "~database/datasource"; import { client } from "~database/datasource";
import type { APIEmoji } from "~types/entities/emoji"; import type { APIEmoji } from "~types/entities/emoji";
import type * as Lysand from "lysand-types"; import type * as Lysand from "lysand-types";
import { addInstanceIfNotExists } from "./Instance";
/** /**
* Represents an emoji entity in the database. * Represents an emoji entity in the database.
@ -29,16 +30,28 @@ export const parseEmojis = async (text: string): Promise<Emoji[]> => {
}); });
}; };
export const addEmojiIfNotExists = async (emoji: Lysand.Emoji) => { /**
* Gets an emoji from the database, and fetches it from the remote instance if it doesn't exist.
* @param emoji Emoji to fetch
* @param host Host to fetch the emoji from if remote
* @returns The emoji
*/
export const fetchEmoji = async (emoji: Lysand.Emoji, host?: string) => {
const existingEmoji = await client.emoji.findFirst({ const existingEmoji = await client.emoji.findFirst({
where: { where: {
shortcode: emoji.name, shortcode: emoji.name,
instance: null, instance: host
? {
base_url: host,
}
: null,
}, },
}); });
if (existingEmoji) return existingEmoji; if (existingEmoji) return existingEmoji;
const instance = host ? await addInstanceIfNotExists(host) : null;
return await client.emoji.create({ return await client.emoji.create({
data: { data: {
shortcode: emoji.name, shortcode: emoji.name,
@ -46,6 +59,13 @@ export const addEmojiIfNotExists = async (emoji: Lysand.Emoji) => {
alt: emoji.alt || emoji.url[0].description || undefined, alt: emoji.alt || emoji.url[0].description || undefined,
content_type: Object.keys(emoji.url)[0], content_type: Object.keys(emoji.url)[0],
visible_in_picker: true, visible_in_picker: true,
instance: host
? {
connect: {
id: instance?.id,
},
}
: undefined,
}, },
}); });
}; };

View file

@ -26,7 +26,7 @@ import {
attachmentToAPI, attachmentToAPI,
attachmentToLysand, attachmentToLysand,
} from "./Attachment"; } from "./Attachment";
import { emojiToAPI, emojiToLysand, parseEmojis } from "./Emoji"; import { emojiToAPI, emojiToLysand, fetchEmoji, parseEmojis } from "./Emoji";
import type { UserWithRelations } from "./User"; import type { UserWithRelations } from "./User";
import { getUserUri, resolveUser, resolveWebFinger, userToAPI } from "./User"; import { getUserUri, resolveUser, resolveWebFinger, userToAPI } from "./User";
import { statusAndUserRelations, userRelations } from "./relations"; import { statusAndUserRelations, userRelations } from "./relations";
@ -116,16 +116,34 @@ export const resolveStatus = async (
throw new Error("Invalid object author"); throw new Error("Invalid object author");
} }
const attachments = ( const attachments = [];
await Promise.all(
(note.attachments ?? []).map((attachment) => for (const attachment of note.attachments ?? []) {
attachmentFromLysand(attachment).catch((e) => { const resolvedAttachment = await attachmentFromLysand(attachment).catch(
console.error(e); (e) => {
return null; console.error(e);
}), return null;
), },
) );
).filter((attachment) => attachment !== null) as Attachment[];
if (resolvedAttachment) {
attachments.push(resolvedAttachment);
}
}
const emojis = [];
for (const emoji of note.extensions?.["org.lysand:custom_emojis"]?.emojis ??
[]) {
const resolvedEmoji = await fetchEmoji(emoji).catch((e) => {
console.error(e);
return null;
});
if (resolvedEmoji) {
emojis.push(resolvedEmoji);
}
}
return await createNewStatus( return await createNewStatus(
author, author,
@ -137,7 +155,7 @@ export const resolveStatus = async (
note.visibility as APIStatus["visibility"], note.visibility as APIStatus["visibility"],
note.is_sensitive ?? false, note.is_sensitive ?? false,
note.subject ?? "", note.subject ?? "",
[], emojis,
note.uri, note.uri,
await Promise.all( await Promise.all(
(note.mentions ?? []) (note.mentions ?? [])

View file

@ -7,7 +7,7 @@ import { client } from "~database/datasource";
import type { APIAccount } from "~types/entities/account"; import type { APIAccount } from "~types/entities/account";
import type { APISource } from "~types/entities/source"; import type { APISource } from "~types/entities/source";
import type * as Lysand from "lysand-types"; import type * as Lysand from "lysand-types";
import { addEmojiIfNotExists, emojiToAPI, emojiToLysand } from "./Emoji"; import { fetchEmoji, emojiToAPI, emojiToLysand } from "./Emoji";
import { addInstanceIfNotExists } from "./Instance"; import { addInstanceIfNotExists } from "./Instance";
import { userRelations } from "./relations"; import { userRelations } from "./relations";
import { createNewRelationship } from "./Relationship"; import { createNewRelationship } from "./Relationship";
@ -241,7 +241,7 @@ export const resolveUser = async (uri: string) => {
const emojis = []; const emojis = [];
for (const emoji of userEmojis) { for (const emoji of userEmojis) {
emojis.push(await addEmojiIfNotExists(emoji)); emojis.push(await fetchEmoji(emoji));
} }
const user = await client.user.create({ const user = await client.user.create({