From cbbf49905b8efd701d09ddb4a2263d23e92a3b2d Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Mon, 9 Dec 2024 13:11:23 +0100 Subject: [PATCH] fix(federation): :bug: Fix remote emojis being incorrectly marked as local --- classes/database/emoji.ts | 25 +++++++++++++------------ classes/database/note.ts | 25 ++++++++++++++++--------- classes/database/user.ts | 2 +- classes/inbox/processor.ts | 12 ++++++++++-- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/classes/database/emoji.ts b/classes/database/emoji.ts index 97c29251..4df0d7fa 100644 --- a/classes/database/emoji.ts +++ b/classes/database/emoji.ts @@ -2,7 +2,7 @@ import { emojiValidatorWithColons, emojiValidatorWithIdentifiers } from "@/api"; import { proxyUrl } from "@/response"; import type { Emoji as APIEmoji } from "@versia/client/types"; import type { CustomEmojiExtension } from "@versia/federation/types"; -import { db } from "@versia/kit/db"; +import { type Instance, db } from "@versia/kit/db"; import { Emojis, Instances } from "@versia/kit/tables"; import { type InferInsertModel, @@ -12,10 +12,10 @@ import { desc, eq, inArray, + isNull, } from "drizzle-orm"; import { z } from "zod"; import { BaseInterface } from "./base.ts"; -import { Instance } from "./instance.ts"; type EmojiWithInstance = InferSelectModel & { instance: InferSelectModel | null; @@ -135,7 +135,7 @@ export class Emoji extends BaseInterface { public static async fetchFromRemote( emojiToFetch: CustomEmojiExtension["emojis"][0], - host?: string, + instance: Instance, ): Promise { const existingEmoji = await db .select() @@ -144,7 +144,7 @@ export class Emoji extends BaseInterface { .where( and( eq(Emojis.shortcode, emojiToFetch.name), - host ? eq(Instances.baseUrl, host) : undefined, + eq(Instances.id, instance.id), ), ) .limit(1); @@ -159,9 +159,7 @@ export class Emoji extends BaseInterface { return found; } - const foundInstance = host ? await Instance.resolve(host) : null; - - return await Emoji.fromVersia(emojiToFetch, foundInstance?.id ?? null); + return await Emoji.fromVersia(emojiToFetch, instance); } public get id(): string { @@ -181,9 +179,12 @@ export class Emoji extends BaseInterface { } return Emoji.manyFromSql( - inArray( - Emojis.shortcode, - matches.map((match) => match.replace(/:/g, "")), + and( + inArray( + Emojis.shortcode, + matches.map((match) => match.replace(/:/g, "")), + ), + isNull(Emojis.instanceId), ), ); } @@ -216,7 +217,7 @@ export class Emoji extends BaseInterface { public static fromVersia( emoji: CustomEmojiExtension["emojis"][0], - instanceId: string | null, + instance: Instance, ): Promise { // Extracts the shortcode from the emoji name (e.g. :shortcode: -> shortcode) const shortcode = [ @@ -233,7 +234,7 @@ export class Emoji extends BaseInterface { alt: Object.entries(emoji.url)[0][1].description || undefined, contentType: Object.keys(emoji.url)[0], visibleInPicker: true, - instanceId, + instanceId: instance.id, }); } } diff --git a/classes/database/note.ts b/classes/database/note.ts index c9e14145..538ff196 100644 --- a/classes/database/note.ts +++ b/classes/database/note.ts @@ -13,7 +13,7 @@ import type { Delete as VersiaDelete, Note as VersiaNote, } from "@versia/federation/types"; -import { type Instance, Notification, db } from "@versia/kit/db"; +import { Instance, Notification, db } from "@versia/kit/db"; import { Attachments, EmojiToNote, @@ -715,6 +715,11 @@ export class Note extends BaseInterface { */ public static async saveFromRemote(uri: string): Promise { let note: VersiaNote | null = null; + const instance = await Instance.resolve(uri); + + if (!instance) { + return null; + } if (uri) { if (!URL.canParse(uri)) { @@ -741,7 +746,7 @@ export class Note extends BaseInterface { throw new Error("Invalid object author"); } - return await Note.fromVersia(note, author); + return await Note.fromVersia(note, author, instance); } /** @@ -753,19 +758,21 @@ export class Note extends BaseInterface { public static async fromVersia( note: VersiaNote, author: User, + instance: Instance, ): Promise { const emojis: Emoji[] = []; const logger = getLogger(["federation", "resolvers"]); for (const emoji of note.extensions?.["pub.versia:custom_emojis"] ?.emojis ?? []) { - const resolvedEmoji = await Emoji.fetchFromRemote(emoji).catch( - (e) => { - logger.error`${e}`; - sentry?.captureException(e); - return null; - }, - ); + const resolvedEmoji = await Emoji.fetchFromRemote( + emoji, + instance, + ).catch((e) => { + logger.error`${e}`; + sentry?.captureException(e); + return null; + }); if (resolvedEmoji) { emojis.push(resolvedEmoji); diff --git a/classes/database/user.ts b/classes/database/user.ts index 4b253262..e14646db 100644 --- a/classes/database/user.ts +++ b/classes/database/user.ts @@ -667,7 +667,7 @@ export class User extends BaseInterface { const userEmojis = data.extensions?.["pub.versia:custom_emojis"]?.emojis ?? []; const emojis = await Promise.all( - userEmojis.map((emoji) => Emoji.fromVersia(emoji, instance.id)), + userEmojis.map((emoji) => Emoji.fromVersia(emoji, instance)), ); if (emojis.length > 0) { diff --git a/classes/inbox/processor.ts b/classes/inbox/processor.ts index cdc2729e..6697c4aa 100644 --- a/classes/inbox/processor.ts +++ b/classes/inbox/processor.ts @@ -16,7 +16,7 @@ import type { User as VersiaUser, } from "@versia/federation/types"; import { - type Instance, + Instance, Like, Note, Notification, @@ -277,6 +277,14 @@ export class InboxProcessor { private async processNote(): Promise { const note = this.body as VersiaNote; const author = await User.resolve(note.author); + const instance = await Instance.resolve(note.uri); + + if (!instance) { + return Response.json( + { error: "Instance not found" }, + { status: 404 }, + ); + } if (!author) { return Response.json( @@ -285,7 +293,7 @@ export class InboxProcessor { ); } - await Note.fromVersia(note, author); + await Note.fromVersia(note, author, instance); return null; }