fix(federation): 🐛 Fix remote emojis being incorrectly marked as local

This commit is contained in:
Jesse Wierzbinski 2024-12-09 13:11:23 +01:00
parent c94dd7c59d
commit cbbf49905b
No known key found for this signature in database
4 changed files with 40 additions and 24 deletions

View file

@ -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<typeof Emojis> & {
instance: InferSelectModel<typeof Instances> | null;
@ -135,7 +135,7 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
public static async fetchFromRemote(
emojiToFetch: CustomEmojiExtension["emojis"][0],
host?: string,
instance: Instance,
): Promise<Emoji> {
const existingEmoji = await db
.select()
@ -144,7 +144,7 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
.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<typeof Emojis, EmojiWithInstance> {
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<typeof Emojis, EmojiWithInstance> {
}
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<typeof Emojis, EmojiWithInstance> {
public static fromVersia(
emoji: CustomEmojiExtension["emojis"][0],
instanceId: string | null,
instance: Instance,
): Promise<Emoji> {
// Extracts the shortcode from the emoji name (e.g. :shortcode: -> shortcode)
const shortcode = [
@ -233,7 +234,7 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
alt: Object.entries(emoji.url)[0][1].description || undefined,
contentType: Object.keys(emoji.url)[0],
visibleInPicker: true,
instanceId,
instanceId: instance.id,
});
}
}

View file

@ -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<typeof Notes, NoteTypeWithRelations> {
*/
public static async saveFromRemote(uri: string): Promise<Note | null> {
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<typeof Notes, NoteTypeWithRelations> {
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<typeof Notes, NoteTypeWithRelations> {
public static async fromVersia(
note: VersiaNote,
author: User,
instance: Instance,
): Promise<Note> {
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);

View file

@ -667,7 +667,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
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) {

View file

@ -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<Response | null> {
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;
}