From a54576564b0c4654d62bfc9d1bd231a78a97e408 Mon Sep 17 00:00:00 2001
From: naskya <m@naskya.net>
Date: Sat, 3 Aug 2024 11:12:08 +0900
Subject: [PATCH] refactor (backend): port renderFlag to backend-rs

---
 packages/backend-rs/index.d.ts                | 10 +++++
 packages/backend-rs/index.js                  |  1 +
 .../src/federation/activitypub/object/flag.rs | 40 +++++++++++++++++++
 .../src/federation/activitypub/object/mod.rs  |  2 +
 .../src/remote/activitypub/renderer/flag.ts   | 17 --------
 .../admin/resolve-abuse-user-report.ts        |  7 ++--
 6 files changed, 56 insertions(+), 21 deletions(-)
 create mode 100644 packages/backend-rs/src/federation/activitypub/object/flag.rs
 delete mode 100644 packages/backend/src/remote/activitypub/renderer/flag.ts

diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts
index 9cf3a9827d..b70c02141f 100644
--- a/packages/backend-rs/index.d.ts
+++ b/packages/backend-rs/index.d.ts
@@ -119,6 +119,13 @@ export interface ApEmoji {
   icon: Icon
 }
 
+export interface ApFlag {
+  type: ApObject
+  actor: string
+  content: string
+  object: string
+}
+
 export interface ApFollow {
   id: string
   type: ApObject
@@ -128,6 +135,7 @@ export interface ApFollow {
 
 export type ApObject =  'Accept'|
 'Emoji'|
+'Flag'|
 'Follow'|
 'Image'|
 'Tombstone';
@@ -1301,6 +1309,8 @@ export declare function renderAccept(userId: string, followObject: ApFollow): Ap
 
 export declare function renderEmoji(emoji: Emoji): ApEmoji
 
+export declare function renderFlag(targetUserUri: string, comment: string): Promise<ApFlag>
+
 export declare function renderFollow(follower: UserLike, followee: UserLike, requestId?: string | undefined | null): ApFollow
 
 export declare function renderFollowRelay(relayId: string): Promise<ApFollow>
diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js
index 20b9c6f4ad..b1d20a7bc7 100644
--- a/packages/backend-rs/index.js
+++ b/packages/backend-rs/index.js
@@ -440,6 +440,7 @@ module.exports.RelayStatus = nativeBinding.RelayStatus
 module.exports.removeOldAttestationChallenges = nativeBinding.removeOldAttestationChallenges
 module.exports.renderAccept = nativeBinding.renderAccept
 module.exports.renderEmoji = nativeBinding.renderEmoji
+module.exports.renderFlag = nativeBinding.renderFlag
 module.exports.renderFollow = nativeBinding.renderFollow
 module.exports.renderFollowRelay = nativeBinding.renderFollowRelay
 module.exports.renderTombstone = nativeBinding.renderTombstone
diff --git a/packages/backend-rs/src/federation/activitypub/object/flag.rs b/packages/backend-rs/src/federation/activitypub/object/flag.rs
new file mode 100644
index 0000000000..8dcfbeb047
--- /dev/null
+++ b/packages/backend-rs/src/federation/activitypub/object/flag.rs
@@ -0,0 +1,40 @@
+use super::*;
+use crate::{config::CONFIG, federation::internal_actor};
+
+#[macros::export(object)]
+pub struct ApFlag {
+    pub r#type: ApObject,
+    pub actor: String,
+    pub content: String,
+    // TODO: object can be an array of uri's
+    pub object: String,
+}
+
+impl ActivityPubObject for ApFlag {}
+
+impl ApFlag {
+    #[allow(dead_code)] // TODO: remove this line
+    async fn new(
+        target_user_uri: String,
+        comment: String,
+    ) -> Result<Self, internal_actor::instance::Error> {
+        Ok(Self {
+            r#type: ApObject::Flag,
+            actor: format!(
+                "{}/users/{}",
+                CONFIG.url,
+                internal_actor::instance::get().await?.id
+            ),
+            content: comment,
+            object: target_user_uri,
+        })
+    }
+}
+
+#[macros::ts_export]
+pub async fn render_flag(
+    target_user_uri: String,
+    comment: String,
+) -> Result<ApFlag, internal_actor::instance::Error> {
+    ApFlag::new(target_user_uri, comment).await
+}
diff --git a/packages/backend-rs/src/federation/activitypub/object/mod.rs b/packages/backend-rs/src/federation/activitypub/object/mod.rs
index a20fbc342e..99f4802ea0 100644
--- a/packages/backend-rs/src/federation/activitypub/object/mod.rs
+++ b/packages/backend-rs/src/federation/activitypub/object/mod.rs
@@ -1,5 +1,6 @@
 pub mod accept;
 pub mod emoji;
+pub mod flag;
 pub mod follow;
 pub mod tombstone;
 
@@ -9,6 +10,7 @@ pub trait ActivityPubObject {}
 pub enum ApObject {
     Accept,
     Emoji,
+    Flag,
     Follow,
     Image,
     Tombstone,
diff --git a/packages/backend/src/remote/activitypub/renderer/flag.ts b/packages/backend/src/remote/activitypub/renderer/flag.ts
deleted file mode 100644
index 1fa260be5e..0000000000
--- a/packages/backend/src/remote/activitypub/renderer/flag.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { config } from "@/config.js";
-import type { ILocalUser } from "@/models/entities/user.js";
-
-// to anonymise reporters, the reporting actor must be a system user
-// object has to be a uri or array of uris
-export const renderFlag = (
-	user: ILocalUser,
-	object: [string],
-	content: string,
-) => {
-	return {
-		type: "Flag",
-		actor: `${config.url}/users/${user.id}`,
-		content,
-		object,
-	};
-};
diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
index c93024b41b..bcab03469e 100644
--- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
+++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
@@ -1,10 +1,9 @@
 import define from "@/server/api/define.js";
 import { AbuseUserReports, Users } from "@/models/index.js";
-import { getInstanceActor } from "backend-rs";
+import { getInstanceActor, renderFlag } from "backend-rs";
 import { deliver } from "@/queue/index.js";
 import { renderActivity } from "@/remote/activitypub/renderer/index.js";
-import { renderFlag } from "@/remote/activitypub/renderer/flag.js";
-import { ILocalUser } from "@/models/entities/user";
+import type { ILocalUser } from "@/models/entities/user";
 
 export const meta = {
 	tags: ["admin"],
@@ -35,7 +34,7 @@ export default define(meta, paramDef, async (ps, me) => {
 
 		deliver(
 			actor.id,
-			renderActivity(renderFlag(actor, [targetUser.uri!], report.comment)),
+			renderActivity(await renderFlag(targetUser.uri, report.comment)),
 			targetUser.inbox,
 		);
 	}