refactor (backend): port renderEmoji to backend-rs

This commit is contained in:
naskya 2024-07-30 22:39:42 +09:00
parent da307934e4
commit 6344b72321
No known key found for this signature in database
GPG key ID: 712D413B3A9FED5C
14 changed files with 144 additions and 65 deletions

View file

@ -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";

View file

@ -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<Meta>
/** Fetches and returns the NodeInfo (version 2.0) of a remote server. */
export declare function fetchNodeinfo(host: string): Promise<Nodeinfo>
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<void>
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<Follow>
export declare function renderFollow(follower: UserLike, followee: UserLike, requestId?: string | undefined | null): ApFollow
export declare function renderFollowRelay(relayId: string): Promise<ApFollow>
export interface RenoteMuting {
id: string

View file

@ -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

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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<Self, internal_actor::relay::Error> {
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<String>,
) -> Result<Follow, Error> {
Follow::new(follower, followee, request_id)
) -> Result<ApFollow, Error> {
ApFollow::new(follower, followee, request_id)
}
#[macros::ts_export]
pub async fn render_follow_relay(relay_id: String) -> Result<Follow, internal_actor::relay::Error> {
Follow::new_relay(relay_id).await
pub async fn render_follow_relay(
relay_id: String,
) -> Result<ApFollow, internal_actor::relay::Error> {
ApFollow::new_relay(relay_id).await
}

View file

@ -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";

View file

@ -0,0 +1,18 @@
import type { MigrationInterface, QueryRunner } from "typeorm";
export class SetEmojiPublicUrl1722346019160 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
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<void> {
await queryRunner.query(
`ALTER TABLE "emoji" ALTER COLUMN "publicUrl" SET DEFAULT ''`,
);
}
}

View file

@ -38,7 +38,6 @@ export class Emoji {
@Column("varchar", {
length: 512,
default: "",
})
public publicUrl: string;

View file

@ -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 してるのは後方互換性のため
},
});

View file

@ -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;

View file

@ -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";

View file

@ -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";

View file

@ -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 {