From 6344b723210eb9fd492447222d43df4c254da795 Mon Sep 17 00:00:00 2001 From: naskya Date: Tue, 30 Jul 2024 22:39:42 +0900 Subject: [PATCH] refactor (backend): port renderEmoji to backend-rs --- docs/downgrade.sql | 4 ++ packages/backend-rs/index.d.ts | 58 ++++++++++++------- packages/backend-rs/index.js | 3 +- .../federation/activitypub/object/accept.rs | 20 +++---- .../federation/activitypub/object/emoji.rs | 51 ++++++++++++++++ .../federation/activitypub/object/follow.rs | 22 +++---- .../src/federation/activitypub/object/mod.rs | 5 +- .../1722346019160-set-emoji-public-url.ts | 18 ++++++ packages/backend/src/models/entities/emoji.ts | 1 - .../src/remote/activitypub/renderer/emoji.ts | 17 ------ .../src/remote/activitypub/renderer/like.ts | 2 +- .../src/remote/activitypub/renderer/note.ts | 2 +- .../src/remote/activitypub/renderer/person.ts | 4 +- packages/backend/src/server/activitypub.ts | 2 +- 14 files changed, 144 insertions(+), 65 deletions(-) create mode 100644 packages/backend-rs/src/federation/activitypub/object/emoji.rs create mode 100644 packages/backend/src/migration/1722346019160-set-emoji-public-url.ts delete mode 100644 packages/backend/src/remote/activitypub/renderer/emoji.ts diff --git a/docs/downgrade.sql b/docs/downgrade.sql index 24f0f4baa8..d52227acc8 100644 --- a/docs/downgrade.sql +++ b/docs/downgrade.sql @@ -1,6 +1,7 @@ BEGIN; DELETE FROM "migrations" WHERE name IN ( + 'SetEmojiPublicUrl1722346019160', 'SetAccessTokenName1722134626110', 'CreateSystemActors1720618854585', 'AddMastodonSubscriptionType1715181461692', @@ -41,6 +42,9 @@ DELETE FROM "migrations" WHERE name IN ( 'RemoveNativeUtilsMigration1705877093218' ); +-- set-emoji-public-url +ALTER TABLE "emoji" ALTER COLUMN "publicUrl" SET DEFAULT ''; + -- addMastodonSubscriptionType ALTER TABLE "sw_subscription" DROP COLUMN "subscriptionTypes"; DROP TYPE "push_subscription_type"; diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index ab4fc04bc5..4ad1992d33 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -25,13 +25,6 @@ export interface AbuseUserReportLike { comment: string } -export interface Accept { - id: string - type: Activity - actor: string - object: Follow -} - export interface AccessToken { id: string createdAt: DateTimeWithTimeZone @@ -55,9 +48,6 @@ export interface Acct { export declare function acctToString(acct: Acct): string -export type Activity = 'Accept'| -'Follow'; - export interface Ad { id: string createdAt: DateTimeWithTimeZone @@ -114,6 +104,33 @@ export type AntennaSrc = 'all'| 'list'| 'users'; +export interface ApAccept { + id: string + type: ApObject + actor: string + object: ApFollow +} + +export interface ApEmoji { + id: string + type: ApObject + name: string + updated: string + icon: Icon +} + +export interface ApFollow { + id: string + type: ApObject + actor: string + object: string +} + +export type ApObject = 'Accept'| +'Emoji'| +'Follow'| +'Image'; + export interface App { id: string createdAt: DateTimeWithTimeZone @@ -420,13 +437,6 @@ export declare function fetchMeta(): Promise /** Fetches and returns the NodeInfo (version 2.0) of a remote server. */ export declare function fetchNodeinfo(host: string): Promise -export interface Follow { - id: string - type: Activity - actor: string - object: string -} - export interface Following { id: string createdAt: DateTimeWithTimeZone @@ -532,6 +542,12 @@ export interface Hashtag { attachedRemoteUsersCount: number } +export interface Icon { + type: ApObject + mediaType: string + url: string +} + export interface IdConfig { length?: number fingerprint?: string @@ -1275,11 +1291,13 @@ export type RelayStatus = 'accepted'| /** Delete all entries in the [attestation_challenge] table created at more than 5 minutes ago */ export declare function removeOldAttestationChallenges(): Promise -export declare function renderAccept(userId: string, followObject: Follow): Accept +export declare function renderAccept(userId: string, followObject: Follow): ApAccept -export declare function renderFollow(follower: UserLike, followee: UserLike, requestId?: string | undefined | null): Follow +export declare function renderEmoji(emoji: Emoji): ApEmoji -export declare function renderFollowRelay(relayId: string): Promise +export declare function renderFollow(follower: UserLike, followee: UserLike, requestId?: string | undefined | null): ApFollow + +export declare function renderFollowRelay(relayId: string): Promise export interface RenoteMuting { id: string diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index 1ffacb1e3c..f7458cb3b0 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -362,8 +362,8 @@ if (!nativeBinding) { } module.exports.acctToString = nativeBinding.acctToString -module.exports.Activity = nativeBinding.Activity module.exports.AntennaSrc = nativeBinding.AntennaSrc +module.exports.ApObject = nativeBinding.ApObject module.exports.ChatEvent = nativeBinding.ChatEvent module.exports.ChatIndexEvent = nativeBinding.ChatIndexEvent module.exports.checkWordMute = nativeBinding.checkWordMute @@ -439,6 +439,7 @@ module.exports.PushSubscriptionType = nativeBinding.PushSubscriptionType module.exports.RelayStatus = nativeBinding.RelayStatus module.exports.removeOldAttestationChallenges = nativeBinding.removeOldAttestationChallenges module.exports.renderAccept = nativeBinding.renderAccept +module.exports.renderEmoji = nativeBinding.renderEmoji module.exports.renderFollow = nativeBinding.renderFollow module.exports.renderFollowRelay = nativeBinding.renderFollowRelay module.exports.safeForSql = nativeBinding.safeForSql diff --git a/packages/backend-rs/src/federation/activitypub/object/accept.rs b/packages/backend-rs/src/federation/activitypub/object/accept.rs index a156b84c5d..a78df18809 100644 --- a/packages/backend-rs/src/federation/activitypub/object/accept.rs +++ b/packages/backend-rs/src/federation/activitypub/object/accept.rs @@ -3,21 +3,21 @@ use crate::config::CONFIG; use uuid::Uuid; #[macros::export(object)] -pub struct Accept { +pub struct ApAccept { pub id: String, - pub r#type: Activity, + pub r#type: ApObject, pub actor: String, - pub object: follow::Follow, + pub object: follow::ApFollow, } -impl ActivityPubObject for Accept {} +impl ActivityPubObject for ApAccept {} -impl Accept { +impl ApAccept { #[allow(dead_code)] // TODO: remove this line - fn new(user_id: String, follow_object: follow::Follow) -> Self { + fn new(user_id: String, follow_object: follow::ApFollow) -> Self { Self { id: format!("{}/{}", CONFIG.url, Uuid::new_v4()), - r#type: Activity::Accept, + r#type: ApObject::Accept, actor: format!("{}/users/{}", CONFIG.url, user_id), object: follow_object, } @@ -25,9 +25,9 @@ impl Accept { } #[cfg(any(test, doctest, feature = "napi"))] -type Follow = follow::Follow; +type Follow = follow::ApFollow; #[macros::ts_export] -pub fn render_accept(user_id: String, follow_object: Follow) -> Accept { - Accept::new(user_id, follow_object) +pub fn render_accept(user_id: String, follow_object: Follow) -> ApAccept { + ApAccept::new(user_id, follow_object) } diff --git a/packages/backend-rs/src/federation/activitypub/object/emoji.rs b/packages/backend-rs/src/federation/activitypub/object/emoji.rs new file mode 100644 index 0000000000..178a885739 --- /dev/null +++ b/packages/backend-rs/src/federation/activitypub/object/emoji.rs @@ -0,0 +1,51 @@ +use super::*; +use crate::{config::CONFIG, model::entity::emoji}; +use chrono::Utc; + +#[macros::export(object)] +pub struct ApEmoji { + pub id: String, + pub r#type: ApObject, + pub name: String, + pub updated: String, + pub icon: Icon, +} + +#[macros::export(object)] +pub struct Icon { + pub r#type: ApObject, + pub media_type: String, + pub url: String, +} + +impl ActivityPubObject for ApEmoji {} + +impl ApEmoji { + #[allow(dead_code)] // TODO: remove this line + fn new(emoji: emoji::Model) -> Self { + Self { + id: format!("{}/emojis/{}", CONFIG.url, emoji.name), + r#type: ApObject::Emoji, + name: format!(":{}:", emoji.name), + updated: emoji + .updated_at + .unwrap_or_else(|| Utc::now().into()) + .to_rfc3339(), + icon: Icon { + r#type: ApObject::Image, + media_type: emoji.r#type.unwrap_or_else(|| "image/png".to_owned()), + url: emoji.public_url, + }, + } + } +} + +// for napi export +// https://github.com/napi-rs/napi-rs/issues/2060 +#[allow(dead_code)] // TODO: remove this line +type Emoji = emoji::Model; + +#[macros::ts_export] +pub fn render_emoji(emoji: Emoji) -> ApEmoji { + ApEmoji::new(emoji) +} diff --git a/packages/backend-rs/src/federation/activitypub/object/follow.rs b/packages/backend-rs/src/federation/activitypub/object/follow.rs index a609704af9..6beb55ca90 100644 --- a/packages/backend-rs/src/federation/activitypub/object/follow.rs +++ b/packages/backend-rs/src/federation/activitypub/object/follow.rs @@ -9,14 +9,14 @@ pub struct UserLike { } #[macros::export(object)] -pub struct Follow { +pub struct ApFollow { pub id: String, - pub r#type: Activity, + pub r#type: ApObject, pub actor: String, pub object: String, } -impl ActivityPubObject for Follow {} +impl ActivityPubObject for ApFollow {} #[macros::errors] pub enum Error { @@ -26,7 +26,7 @@ pub enum Error { MissingFolloweeUri, } -impl Follow { +impl ApFollow { #[allow(dead_code)] // TODO: remove this line fn new( follower: UserLike, @@ -37,7 +37,7 @@ impl Follow { id: request_id.unwrap_or_else(|| { format!("{}/follows/{}/{}", CONFIG.url, follower.id, followee.id) }), - r#type: Activity::Follow, + r#type: ApObject::Follow, actor: match user::is_local!(follower) { true => format!("{}/users/{}", CONFIG.url, follower.id), false => follower.uri.ok_or(Error::MissingFollowerUri)?, @@ -53,7 +53,7 @@ impl Follow { async fn new_relay(relay_id: String) -> Result { Ok(Self { id: format!("{}/activities/follow-relay/{}", CONFIG.url, relay_id), - r#type: Activity::Follow, + r#type: ApObject::Follow, actor: format!( "{}/users/{}", CONFIG.url, @@ -69,11 +69,13 @@ pub fn render_follow( follower: UserLike, followee: UserLike, request_id: Option, -) -> Result { - Follow::new(follower, followee, request_id) +) -> Result { + ApFollow::new(follower, followee, request_id) } #[macros::ts_export] -pub async fn render_follow_relay(relay_id: String) -> Result { - Follow::new_relay(relay_id).await +pub async fn render_follow_relay( + relay_id: String, +) -> Result { + ApFollow::new_relay(relay_id).await } diff --git a/packages/backend-rs/src/federation/activitypub/object/mod.rs b/packages/backend-rs/src/federation/activitypub/object/mod.rs index ebb83035b0..2da7787116 100644 --- a/packages/backend-rs/src/federation/activitypub/object/mod.rs +++ b/packages/backend-rs/src/federation/activitypub/object/mod.rs @@ -1,12 +1,15 @@ pub mod accept; +pub mod emoji; pub mod follow; pub trait ActivityPubObject {} #[macros::export(string_enum)] -pub enum Activity { +pub enum ApObject { Accept, + Emoji, Follow, + Image, } const AS_PUBLIC_URL: &str = "https://www.w3.org/ns/activitystreams#Public"; diff --git a/packages/backend/src/migration/1722346019160-set-emoji-public-url.ts b/packages/backend/src/migration/1722346019160-set-emoji-public-url.ts new file mode 100644 index 0000000000..8f3c95ccb9 --- /dev/null +++ b/packages/backend/src/migration/1722346019160-set-emoji-public-url.ts @@ -0,0 +1,18 @@ +import type { MigrationInterface, QueryRunner } from "typeorm"; + +export class SetEmojiPublicUrl1722346019160 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `UPDATE "emoji" SET "publicUrl" = "originalUrl" WHERE "publicUrl" = ''`, + ); + await queryRunner.query( + `ALTER TABLE "emoji" ALTER COLUMN "publicUrl" DROP DEFAULT`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "emoji" ALTER COLUMN "publicUrl" SET DEFAULT ''`, + ); + } +} diff --git a/packages/backend/src/models/entities/emoji.ts b/packages/backend/src/models/entities/emoji.ts index 87b525dc59..0e5dcc32c9 100644 --- a/packages/backend/src/models/entities/emoji.ts +++ b/packages/backend/src/models/entities/emoji.ts @@ -38,7 +38,6 @@ export class Emoji { @Column("varchar", { length: 512, - default: "", }) public publicUrl: string; diff --git a/packages/backend/src/remote/activitypub/renderer/emoji.ts b/packages/backend/src/remote/activitypub/renderer/emoji.ts deleted file mode 100644 index dab0e8cac7..0000000000 --- a/packages/backend/src/remote/activitypub/renderer/emoji.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { config } from "@/config.js"; -import type { Emoji } from "@/models/entities/emoji.js"; - -export default (emoji: Emoji) => ({ - id: `${config.url}/emojis/${emoji.name}`, - type: "Emoji", - name: `:${emoji.name}:`, - updated: - emoji.updatedAt != null - ? emoji.updatedAt.toISOString() - : new Date().toISOString, - icon: { - type: "Image", - mediaType: emoji.type || "image/png", - url: emoji.publicUrl || emoji.originalUrl, // || emoji.originalUrl してるのは後方互換性のため - }, -}); diff --git a/packages/backend/src/remote/activitypub/renderer/like.ts b/packages/backend/src/remote/activitypub/renderer/like.ts index ea0df3e359..e6eab0b261 100644 --- a/packages/backend/src/remote/activitypub/renderer/like.ts +++ b/packages/backend/src/remote/activitypub/renderer/like.ts @@ -3,7 +3,7 @@ import { config } from "@/config.js"; import type { NoteReaction } from "@/models/entities/note-reaction.js"; import type { Note } from "@/models/entities/note.js"; import { Emojis } from "@/models/index.js"; -import renderEmoji from "./emoji.js"; +import { renderEmoji } from "backend-rs"; export const renderLike = async (noteReaction: NoteReaction, note: Note) => { const reaction = noteReaction.reaction; diff --git a/packages/backend/src/remote/activitypub/renderer/note.ts b/packages/backend/src/remote/activitypub/renderer/note.ts index dc978f1e0e..e688a4ce00 100644 --- a/packages/backend/src/remote/activitypub/renderer/note.ts +++ b/packages/backend/src/remote/activitypub/renderer/note.ts @@ -6,7 +6,7 @@ import { DriveFiles, Notes, Users, Emojis, Polls } from "@/models/index.js"; import type { Emoji } from "@/models/entities/emoji.js"; import type { Poll } from "@/models/entities/poll.js"; import toHtml from "@/remote/activitypub/misc/get-note-html.js"; -import renderEmoji from "./emoji.js"; +import { renderEmoji } from "backend-rs"; import renderMention from "./mention.js"; import renderHashtag from "./hashtag.js"; import renderDocument from "./document.js"; diff --git a/packages/backend/src/remote/activitypub/renderer/person.ts b/packages/backend/src/remote/activitypub/renderer/person.ts index c6371440b4..30e067b2ac 100644 --- a/packages/backend/src/remote/activitypub/renderer/person.ts +++ b/packages/backend/src/remote/activitypub/renderer/person.ts @@ -4,11 +4,11 @@ import { config } from "@/config.js"; import type { ILocalUser } from "@/models/entities/user.js"; import { DriveFiles, UserProfiles } from "@/models/index.js"; import { getUserKeypair } from "@/misc/keypair-store.js"; -import { toHtml } from "../../../mfm/to-html.js"; +import { toHtml } from "@/mfm/to-html.js"; import renderImage from "./image.js"; import renderKey from "./key.js"; import { getEmojis } from "./note.js"; -import renderEmoji from "./emoji.js"; +import { renderEmoji } from "backend-rs"; import renderHashtag from "./hashtag.js"; import type { IIdentifier } from "../models/identifier.js"; diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index bc0442d381..e302cb198c 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -7,12 +7,12 @@ import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderNote from "@/remote/activitypub/renderer/note.js"; import renderKey from "@/remote/activitypub/renderer/key.js"; import { renderPerson } from "@/remote/activitypub/renderer/person.js"; -import renderEmoji from "@/remote/activitypub/renderer/emoji.js"; import { inbox as processInbox } from "@/queue/index.js"; import { fetchMeta, getInstanceActor, isSelfHost, + renderEmoji, renderFollow, } from "backend-rs"; import {