fix(api): 🐛 Add Reaction custom emoji data in statuses

This commit is contained in:
Jesse Wierzbinski 2025-05-26 15:13:56 +02:00
parent 8c0a20a743
commit 287f428a83
No known key found for this signature in database
3 changed files with 68 additions and 21 deletions

View file

@ -1,11 +1,37 @@
import { afterAll, describe, expect, test } from "bun:test"; import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { randomUUIDv7 } from "bun";
import { Emoji } from "~/classes/database/emoji";
import { Media } from "~/classes/database/media";
import { generateClient, getTestStatuses, getTestUsers } from "~/tests/utils"; import { generateClient, getTestStatuses, getTestUsers } from "~/tests/utils";
const { users, deleteUsers } = await getTestUsers(3); const { users, deleteUsers } = await getTestUsers(3);
const timeline = (await getTestStatuses(2, users[0])).toReversed(); const timeline = (await getTestStatuses(2, users[0])).toReversed();
let emojiMedia: Media;
let customEmoji: Emoji;
beforeAll(async () => {
emojiMedia = await Media.insert({
id: randomUUIDv7(),
content: {
"image/png": {
content: "https://example.com/image.png",
remote: true,
},
},
});
customEmoji = await Emoji.insert({
id: randomUUIDv7(),
shortcode: "test_emoji",
visibleInPicker: true,
mediaId: emojiMedia.id,
});
});
afterAll(async () => { afterAll(async () => {
await deleteUsers(); await deleteUsers();
await customEmoji.delete();
await emojiMedia.delete();
}); });
describe("/api/v1/statuses/:id/reactions/:name", () => { describe("/api/v1/statuses/:id/reactions/:name", () => {
@ -40,6 +66,29 @@ describe("/api/v1/statuses/:id/reactions/:name", () => {
); );
}); });
test("should add custom emoji reaction", async () => {
await using client = await generateClient(users[1]);
const { data, ok } = await client.createEmojiReaction(
timeline[0].id,
`:${customEmoji.data.shortcode}:`,
);
expect(ok).toBe(true);
expect(data.reactions).toContainEqual(
expect.objectContaining({
name: `:${customEmoji.data.shortcode}:`,
count: 1,
me: true,
}),
);
expect(data.emojis).toContainEqual(
expect.objectContaining({
shortcode: customEmoji.data.shortcode,
}),
);
});
test("should add multiple different reactions", async () => { test("should add multiple different reactions", async () => {
await using client1 = await generateClient(users[1]); await using client1 = await generateClient(users[1]);
await using client2 = await generateClient(users[2]); await using client2 = await generateClient(users[2]);

View file

@ -105,19 +105,12 @@ export default apiRoute((app) => {
emoji = unicodeEmoji; emoji = unicodeEmoji;
} }
// Use the User react method
try {
await user.react(note, emoji); await user.react(note, emoji);
// Reload note to get updated reactions // Reload note to get updated reactions
await note.reload(user.id); await note.reload(user.id);
return context.json(await note.toApi(user), 201); return context.json(await note.toApi(user), 201);
} catch {
// If it's already reacted, just return the current status
await note.reload(user.id);
return context.json(await note.toApi(user), 201);
}
}, },
); );
@ -206,7 +199,6 @@ export default apiRoute((app) => {
emoji = unicodeEmoji; emoji = unicodeEmoji;
} }
// Use the User unreact method
await user.unreact(note, emoji); await user.unreact(note, emoji);
// Reload note to get updated reactions // Reload note to get updated reactions

View file

@ -641,6 +641,18 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
); );
} }
const reactions = this.getReactions(userFetching ?? undefined).map(
// Remove account_ids
(r) => ({
...r,
account_ids: undefined,
}),
);
const emojis = data.emojis.concat(
data.reactions.map((r) => r.emoji).filter((v) => v !== null),
);
return { return {
id: data.id, id: data.id,
in_reply_to_id: data.replyId || null, in_reply_to_id: data.replyId || null,
@ -652,7 +664,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
: undefined, : undefined,
card: null, card: null,
content: replacedContent, content: replacedContent,
emojis: data.emojis.map((emoji) => new Emoji(emoji).toApi()), emojis: emojis.map((emoji) => new Emoji(emoji).toApi()),
favourited: data.liked, favourited: data.liked,
favourites_count: data.likeCount, favourites_count: data.likeCount,
media_attachments: (data.attachments ?? []).map((a) => media_attachments: (data.attachments ?? []).map((a) =>
@ -699,13 +711,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
edited_at: data.updatedAt edited_at: data.updatedAt
? new Date(data.updatedAt).toISOString() ? new Date(data.updatedAt).toISOString()
: null, : null,
reactions: this.getReactions(userFetching ?? undefined).map( reactions,
// Remove account_ids
(r) => ({
...r,
account_ids: undefined,
}),
),
text: data.contentSource, text: data.contentSource,
}; };
} }