mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 05:49:16 +01:00
refactor(federation): 🔥 Refactor Note federation and creation code
This commit is contained in:
parent
54b2dfb78d
commit
f79b0bc999
19 changed files with 243 additions and 354 deletions
|
|
@ -45,7 +45,7 @@ export default apiRoute((app) =>
|
|||
async (context) => {
|
||||
const otherUser = context.get("user");
|
||||
|
||||
if (otherUser.isLocal()) {
|
||||
if (otherUser.local) {
|
||||
throw new ApiError(400, "Cannot refetch a local user");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default apiRoute((app) =>
|
|||
);
|
||||
|
||||
// Check if accepting remote follow
|
||||
if (account.isRemote()) {
|
||||
if (account.remote) {
|
||||
// Federate follow accept
|
||||
await user.acceptFollowRequest(account);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export default apiRoute((app) =>
|
|||
);
|
||||
|
||||
// Check if rejecting remote follow
|
||||
if (account.isRemote()) {
|
||||
if (account.remote) {
|
||||
// Federate follow reject
|
||||
await user.rejectFollowRequest(account);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
jsonOrForm,
|
||||
withNoteParam,
|
||||
} from "@/api";
|
||||
import { sanitizedHtmlStrip } from "@/sanitization";
|
||||
import {
|
||||
Attachment as AttachmentSchema,
|
||||
PollOption,
|
||||
|
|
@ -13,12 +14,13 @@ import {
|
|||
zBoolean,
|
||||
} from "@versia/client/schemas";
|
||||
import { RolePermission } from "@versia/client/schemas";
|
||||
import { Media } from "@versia/kit/db";
|
||||
import { Emoji, Media } from "@versia/kit/db";
|
||||
import * as VersiaEntities from "@versia/sdk/entities";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { ApiError } from "~/classes/errors/api-error";
|
||||
import { contentToHtml, parseTextMentions } from "~/classes/functions/status";
|
||||
import { config } from "~/config.ts";
|
||||
|
||||
const schema = z
|
||||
|
|
@ -226,22 +228,50 @@ export default apiRoute((app) => {
|
|||
);
|
||||
}
|
||||
|
||||
const newNote = await note.updateFromData({
|
||||
author: user,
|
||||
content: statusText
|
||||
? new VersiaEntities.TextContentFormat({
|
||||
[content_type]: {
|
||||
content: statusText,
|
||||
remote: false,
|
||||
},
|
||||
})
|
||||
const sanitizedSpoilerText = spoiler_text
|
||||
? await sanitizedHtmlStrip(spoiler_text)
|
||||
: undefined;
|
||||
|
||||
const content = statusText
|
||||
? new VersiaEntities.TextContentFormat({
|
||||
[content_type]: {
|
||||
content: statusText,
|
||||
remote: false,
|
||||
},
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const parsedMentions = statusText
|
||||
? await parseTextMentions(statusText, user)
|
||||
: [];
|
||||
|
||||
const parsedEmojis = statusText
|
||||
? await Emoji.parseFromText(statusText)
|
||||
: [];
|
||||
|
||||
await note.update({
|
||||
spoilerText: sanitizedSpoilerText,
|
||||
sensitive,
|
||||
content: content
|
||||
? await contentToHtml(content, parsedMentions)
|
||||
: undefined,
|
||||
isSensitive: sensitive,
|
||||
spoilerText: spoiler_text,
|
||||
mediaAttachments: foundAttachments,
|
||||
});
|
||||
|
||||
return context.json(await newNote.toApi(user), 200);
|
||||
// Emojis, mentions, and attachments are stored in a different table, so update them there too
|
||||
await note.updateEmojis(parsedEmojis);
|
||||
await note.updateMentions(parsedMentions);
|
||||
await note.updateAttachments(foundAttachments);
|
||||
|
||||
await note.reload();
|
||||
|
||||
// Send notifications for mentioned local users
|
||||
for (const mentioned of parsedMentions) {
|
||||
if (mentioned.local) {
|
||||
await mentioned.notify("mention", user, note);
|
||||
}
|
||||
}
|
||||
|
||||
return context.json(await note.toApi(user), 200);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export default apiRoute((app) =>
|
|||
throw new Error("Failed to reblog");
|
||||
}
|
||||
|
||||
if (note.author.isLocal() && user.isLocal()) {
|
||||
if (note.author.local && user.local) {
|
||||
await note.author.notify("reblog", user, newReblog);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { apiRoute, auth, handleZodError, jsonOrForm } from "@/api";
|
||||
import { sanitizedHtmlStrip } from "@/sanitization";
|
||||
import {
|
||||
Attachment as AttachmentSchema,
|
||||
PollOption,
|
||||
|
|
@ -7,12 +8,14 @@ import {
|
|||
zBoolean,
|
||||
} from "@versia/client/schemas";
|
||||
import { RolePermission } from "@versia/client/schemas";
|
||||
import { Media, Note } from "@versia/kit/db";
|
||||
import { Emoji, Media, Note } from "@versia/kit/db";
|
||||
import * as VersiaEntities from "@versia/sdk/entities";
|
||||
import { randomUUIDv7 } from "bun";
|
||||
import { describeRoute } from "hono-openapi";
|
||||
import { resolver, validator } from "hono-openapi/zod";
|
||||
import { z } from "zod";
|
||||
import { ApiError } from "~/classes/errors/api-error";
|
||||
import { contentToHtml, parseTextMentions } from "~/classes/functions/status";
|
||||
import { config } from "~/config.ts";
|
||||
|
||||
const schema = z
|
||||
|
|
@ -175,27 +178,59 @@ export default apiRoute((app) =>
|
|||
);
|
||||
}
|
||||
|
||||
const newNote = await Note.fromData({
|
||||
author: user,
|
||||
content: new VersiaEntities.TextContentFormat({
|
||||
[content_type]: {
|
||||
content: status ?? "",
|
||||
remote: false,
|
||||
},
|
||||
}),
|
||||
const sanitizedSpoilerText = spoiler_text
|
||||
? await sanitizedHtmlStrip(spoiler_text)
|
||||
: undefined;
|
||||
|
||||
const content = status
|
||||
? new VersiaEntities.TextContentFormat({
|
||||
[content_type]: {
|
||||
content: status,
|
||||
remote: false,
|
||||
},
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const parsedMentions = status
|
||||
? await parseTextMentions(status, user)
|
||||
: [];
|
||||
|
||||
const parsedEmojis = status
|
||||
? await Emoji.parseFromText(status)
|
||||
: [];
|
||||
|
||||
const newNote = await Note.insert({
|
||||
id: randomUUIDv7(),
|
||||
authorId: user.id,
|
||||
visibility,
|
||||
isSensitive: sensitive ?? false,
|
||||
spoilerText: spoiler_text ?? "",
|
||||
mediaAttachments: foundAttachments,
|
||||
content: content
|
||||
? await contentToHtml(content, parsedMentions)
|
||||
: undefined,
|
||||
sensitive,
|
||||
spoilerText: sanitizedSpoilerText,
|
||||
replyId: in_reply_to_id ?? undefined,
|
||||
quoteId: quote_id ?? undefined,
|
||||
application: application ?? undefined,
|
||||
quotingId: quote_id ?? undefined,
|
||||
applicationId: application?.id,
|
||||
});
|
||||
|
||||
// Emojis, mentions, and attachments are stored in a different table, so update them there too
|
||||
await newNote.updateEmojis(parsedEmojis);
|
||||
await newNote.updateMentions(parsedMentions);
|
||||
await newNote.updateAttachments(foundAttachments);
|
||||
|
||||
await newNote.reload();
|
||||
|
||||
if (!local_only) {
|
||||
await newNote.federateToUsers();
|
||||
}
|
||||
|
||||
// Send notifications for mentioned local users
|
||||
for (const mentioned of parsedMentions) {
|
||||
if (mentioned.local) {
|
||||
await mentioned.notify("mention", user, newNote);
|
||||
}
|
||||
}
|
||||
|
||||
return context.json(await newNote.toApi(user), 200);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export default apiRoute((app) =>
|
|||
|
||||
const liker = await User.fromId(like.data.likerId);
|
||||
|
||||
if (!liker || liker.isRemote()) {
|
||||
if (!liker || liker.remote) {
|
||||
throw ApiError.accountNotFound();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,10 +53,7 @@ export default apiRoute((app) =>
|
|||
),
|
||||
);
|
||||
|
||||
if (
|
||||
!(note && (await note.isViewableByUser(null))) ||
|
||||
note.isRemote()
|
||||
) {
|
||||
if (!(note && (await note.isViewableByUser(null))) || note.remote) {
|
||||
throw ApiError.noteNotFound();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,10 +63,7 @@ export default apiRoute((app) =>
|
|||
),
|
||||
);
|
||||
|
||||
if (
|
||||
!(note && (await note.isViewableByUser(null))) ||
|
||||
note.isRemote()
|
||||
) {
|
||||
if (!(note && (await note.isViewableByUser(null))) || note.remote) {
|
||||
throw ApiError.noteNotFound();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,10 +61,7 @@ export default apiRoute((app) =>
|
|||
),
|
||||
);
|
||||
|
||||
if (
|
||||
!(note && (await note.isViewableByUser(null))) ||
|
||||
note.isRemote()
|
||||
) {
|
||||
if (!(note && (await note.isViewableByUser(null))) || note.remote) {
|
||||
throw ApiError.noteNotFound();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export default apiRoute((app) =>
|
|||
throw ApiError.accountNotFound();
|
||||
}
|
||||
|
||||
if (user.isRemote()) {
|
||||
if (user.remote) {
|
||||
throw new ApiError(403, "User is not on this instance");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default apiRoute((app) =>
|
|||
throw new ApiError(404, "User not found");
|
||||
}
|
||||
|
||||
if (author.isRemote()) {
|
||||
if (author.remote) {
|
||||
throw new ApiError(403, "User is not on this instance");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue