chore(federation): 👽 Finish initial Versia Working Draft 4 update

This commit is contained in:
Jesse Wierzbinski 2024-08-26 19:27:40 +02:00
parent c3fa867e74
commit 42e198ca0e
No known key found for this signature in database
14 changed files with 90 additions and 115 deletions

View file

@ -1,4 +1,4 @@
import { emojiValidatorWithColons } from "@/api";
import { emojiValidatorWithColons, emojiValidatorWithIdentifiers } from "@/api";
import { proxyUrl } from "@/response";
import type { Emoji as ApiEmoji } from "@lysand-org/client/types";
import type { CustomEmojiExtension } from "@versia/federation/types";
@ -191,7 +191,7 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
public toVersia(): CustomEmojiExtension["emojis"][0] {
return {
name: this.data.shortcode,
name: `:${this.data.shortcode}:`,
url: {
[this.data.contentType]: {
content: this.data.url,
@ -206,8 +206,17 @@ export class Emoji extends BaseInterface<typeof Emojis, EmojiWithInstance> {
emoji: CustomEmojiExtension["emojis"][0],
instanceId: string | null,
): Promise<Emoji> {
// Extracts the shortcode from the emoji name (e.g. :shortcode: -> shortcode)
const shortcode = [
...emoji.name.matchAll(emojiValidatorWithIdentifiers),
][0].groups.shortcode;
if (!shortcode) {
throw new Error("Could not extract shortcode from emoji name");
}
return Emoji.insert({
shortcode: emoji.name,
shortcode,
url: Object.entries(emoji.url)[0][1].content,
alt: Object.entries(emoji.url)[0][1].description || undefined,
contentType: Object.keys(emoji.url)[0],

View file

@ -139,7 +139,7 @@ export class Instance extends BaseInterface<typeof Instances> {
const wellKnownUrl = new URL("/.well-known/versia", origin);
const logger = getLogger("federation");
const requester = await User.getServerActor().getFederationRequester();
const requester = await User.getFederationRequester();
try {
const { ok, raw, data } = await requester
@ -195,7 +195,7 @@ export class Instance extends BaseInterface<typeof Instances> {
// Go to endpoint, then follow the links to the actual metadata
const logger = getLogger("federation");
const requester = await User.getServerActor().getFederationRequester();
const requester = await User.getFederationRequester();
try {
const {

View file

@ -602,8 +602,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
throw new Error(`Invalid URI to parse ${uri}`);
}
const requester =
await User.getServerActor().getFederationRequester();
const requester = await User.getFederationRequester();
const { data } = await requester.get(uri, {
// @ts-expect-error Bun extension
@ -636,7 +635,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
const emojis: Emoji[] = [];
const logger = getLogger("federation");
for (const emoji of note.extensions?.["org.lysand:custom_emojis"]
for (const emoji of note.extensions?.["pub.versia:custom_emojis"]
?.emojis ?? []) {
const resolvedEmoji = await Emoji.fetchFromRemote(emoji).catch(
(e) => {
@ -948,7 +947,7 @@ export class Note extends BaseInterface<typeof Notes, StatusWithRelations> {
// TODO: Refactor as part of groups
group: status.visibility === "public" ? "public" : "followers",
extensions: {
"org.lysand:custom_emojis": {
"pub.versia:custom_emojis": {
emojis: status.emojis.map((emoji) =>
new Emoji(emoji).toVersia(),
),

View file

@ -135,56 +135,6 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
);
}
static getServerActor(): User {
return new User({
id: "00000000-0000-0000-0000-000000000000",
username: "actor",
avatar: "",
createdAt: "2024-01-01T00:00:00.000Z",
displayName: "Server Actor",
note: "This is a system actor used for server-to-server communication. It is not a real user.",
updatedAt: "2024-01-01T00:00:00.000Z",
instanceId: null,
publicKey: config.instance.keys.public,
source: {
fields: [],
language: null,
note: "",
privacy: "public",
sensitive: false,
},
fields: [],
isAdmin: false,
isBot: false,
isLocked: false,
isDiscoverable: false,
endpoints: {
dislikes: "",
featured: "",
likes: "",
followers: "",
following: "",
inbox: "",
outbox: "",
},
disableAutomoderation: false,
email: "",
emailVerificationToken: "",
emojis: [],
followerCount: 0,
followingCount: 0,
header: "",
instance: null,
password: "",
passwordResetToken: "",
privateKey: config.instance.keys.private,
roles: [],
sanctions: [],
statusCount: 0,
uri: "/users/actor",
});
}
static getUri(id: string, uri: string | null, baseUrl: string) {
return uri || new URL(`/users/${id}`, baseUrl).toString();
}
@ -433,7 +383,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
uri: string,
instance: Instance,
): Promise<User> {
const requester = await User.getServerActor().getFederationRequester();
const requester = await User.getFederationRequester();
const { data: json } = await requester.get<Partial<VersiaUser>>(uri, {
// @ts-expect-error Bun extension
proxy: config.http.proxy.address,
@ -749,6 +699,20 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
return output;
}
/**
* Helper to get the appropriate Versia SDK requester with the instance's private key
*
* @returns The requester
*/
static async getFederationRequester(): Promise<FederationRequester> {
const signatureConstructor = await SignatureConstructor.fromStringKey(
config.instance.keys.private,
config.http.base_url,
);
return new FederationRequester(signatureConstructor);
}
/**
* Helper to get the appropriate Versia SDK requester with this user's private key
*
@ -947,6 +911,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
).toString(),
indexable: false,
username: user.username,
manually_approves_followers: this.data.isLocked,
avatar: urlToContentFormat(this.getAvatarUrl(config)) ?? undefined,
header: urlToContentFormat(this.getHeaderUrl(config)) ?? undefined,
display_name: user.displayName,
@ -960,7 +925,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
algorithm: "ed25519",
},
extensions: {
"org.lysand:custom_emojis": {
"pub.versia:custom_emojis": {
emojis: user.emojis.map((emoji) =>
new Emoji(emoji).toVersia(),
),