From 35564ceeccc09a2172e2d2e6c4de194399ff2965 Mon Sep 17 00:00:00 2001
From: naskya <m@naskya.net>
Date: Fri, 2 Aug 2024 20:49:53 +0900
Subject: [PATCH] refactor (backend): port renderTombstone to backend-rs

---
 packages/backend-rs/index.d.ts                | 10 +++++++-
 packages/backend-rs/index.js                  |  1 +
 .../src/federation/activitypub/object/mod.rs  |  2 ++
 .../activitypub/object/tombstone.rs           | 25 +++++++++++++++++++
 .../remote/activitypub/renderer/tombstone.ts  |  4 ---
 .../backend/src/services/messages/delete.ts   | 13 +++++-----
 packages/backend/src/services/note/delete.ts  | 10 +++-----
 7 files changed, 46 insertions(+), 19 deletions(-)
 create mode 100644 packages/backend-rs/src/federation/activitypub/object/tombstone.rs
 delete mode 100644 packages/backend/src/remote/activitypub/renderer/tombstone.ts

diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts
index 10060ccc5a..9cf3a9827d 100644
--- a/packages/backend-rs/index.d.ts
+++ b/packages/backend-rs/index.d.ts
@@ -129,7 +129,8 @@ export interface ApFollow {
 export type ApObject =  'Accept'|
 'Emoji'|
 'Follow'|
-'Image';
+'Image'|
+'Tombstone';
 
 export interface App {
   id: string
@@ -142,6 +143,11 @@ export interface App {
   callbackUrl: string | null
 }
 
+export interface ApTombstone {
+  id: string
+  type: ApObject
+}
+
 export interface AttestationChallenge {
   id: string
   userId: string
@@ -1299,6 +1305,8 @@ export declare function renderFollow(follower: UserLike, followee: UserLike, req
 
 export declare function renderFollowRelay(relayId: string): Promise<ApFollow>
 
+export declare function renderTombstone(noteId: string): ApTombstone
+
 export interface RenoteMuting {
   id: string
   createdAt: DateTimeWithTimeZone
diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js
index b2ea8e0c4b..20b9c6f4ad 100644
--- a/packages/backend-rs/index.js
+++ b/packages/backend-rs/index.js
@@ -442,6 +442,7 @@ module.exports.renderAccept = nativeBinding.renderAccept
 module.exports.renderEmoji = nativeBinding.renderEmoji
 module.exports.renderFollow = nativeBinding.renderFollow
 module.exports.renderFollowRelay = nativeBinding.renderFollowRelay
+module.exports.renderTombstone = nativeBinding.renderTombstone
 module.exports.safeForSql = nativeBinding.safeForSql
 module.exports.sendPushNotification = nativeBinding.sendPushNotification
 module.exports.shouldNyaify = nativeBinding.shouldNyaify
diff --git a/packages/backend-rs/src/federation/activitypub/object/mod.rs b/packages/backend-rs/src/federation/activitypub/object/mod.rs
index 2da7787116..a20fbc342e 100644
--- a/packages/backend-rs/src/federation/activitypub/object/mod.rs
+++ b/packages/backend-rs/src/federation/activitypub/object/mod.rs
@@ -1,6 +1,7 @@
 pub mod accept;
 pub mod emoji;
 pub mod follow;
+pub mod tombstone;
 
 pub trait ActivityPubObject {}
 
@@ -10,6 +11,7 @@ pub enum ApObject {
     Emoji,
     Follow,
     Image,
+    Tombstone,
 }
 
 const AS_PUBLIC_URL: &str = "https://www.w3.org/ns/activitystreams#Public";
diff --git a/packages/backend-rs/src/federation/activitypub/object/tombstone.rs b/packages/backend-rs/src/federation/activitypub/object/tombstone.rs
new file mode 100644
index 0000000000..81b9b63820
--- /dev/null
+++ b/packages/backend-rs/src/federation/activitypub/object/tombstone.rs
@@ -0,0 +1,25 @@
+use super::*;
+use crate::config::CONFIG;
+
+#[macros::export(object)]
+pub struct ApTombstone {
+    pub id: String,
+    pub r#type: ApObject,
+}
+
+impl ActivityPubObject for ApTombstone {}
+
+impl ApTombstone {
+    #[allow(dead_code)] // TODO: remove this line
+    fn new(note_id: String) -> Self {
+        Self {
+            id: format!("{}/notes/{}", CONFIG.url, note_id),
+            r#type: ApObject::Tombstone,
+        }
+    }
+}
+
+#[macros::ts_export]
+pub fn render_tombstone(note_id: String) -> ApTombstone {
+    ApTombstone::new(note_id)
+}
diff --git a/packages/backend/src/remote/activitypub/renderer/tombstone.ts b/packages/backend/src/remote/activitypub/renderer/tombstone.ts
deleted file mode 100644
index 5c4003c75a..0000000000
--- a/packages/backend/src/remote/activitypub/renderer/tombstone.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export default (id: string) => ({
-	id,
-	type: "Tombstone",
-});
diff --git a/packages/backend/src/services/messages/delete.ts b/packages/backend/src/services/messages/delete.ts
index f0b65151ec..aa9eb0ed54 100644
--- a/packages/backend/src/services/messages/delete.ts
+++ b/packages/backend/src/services/messages/delete.ts
@@ -1,10 +1,12 @@
-import { config } from "@/config.js";
 import { MessagingMessages, Users } from "@/models/index.js";
 import type { MessagingMessage } from "@/models/entities/messaging-message.js";
-import { publishToChatStream, publishToGroupChatStream } from "backend-rs";
+import {
+	publishToChatStream,
+	publishToGroupChatStream,
+	renderTombstone,
+} from "backend-rs";
 import { renderActivity } from "@/remote/activitypub/renderer/index.js";
 import renderDelete from "@/remote/activitypub/renderer/delete.js";
-import renderTombstone from "@/remote/activitypub/renderer/tombstone.js";
 import { deliver } from "@/queue/index.js";
 
 export async function deleteMessage(message: MessagingMessage) {
@@ -36,10 +38,7 @@ async function postDeleteMessage(message: MessagingMessage) {
 
 		if (Users.isLocalUser(user) && Users.isRemoteUser(recipient)) {
 			const activity = renderActivity(
-				renderDelete(
-					renderTombstone(`${config.url}/notes/${message.id}`),
-					user,
-				),
+				renderDelete(renderTombstone(message.id), user),
 			);
 			deliver(user.id, activity, recipient.inbox);
 		}
diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts
index 0ae03a60ac..f599a55470 100644
--- a/packages/backend/src/services/note/delete.ts
+++ b/packages/backend/src/services/note/delete.ts
@@ -3,7 +3,6 @@ import renderDelete from "@/remote/activitypub/renderer/delete.js";
 import renderAnnounce from "@/remote/activitypub/renderer/announce.js";
 import { renderUndo } from "@/remote/activitypub/renderer/undo.js";
 import { renderActivity } from "@/remote/activitypub/renderer/index.js";
-import renderTombstone from "@/remote/activitypub/renderer/tombstone.js";
 import { config } from "@/config.js";
 import type { User, ILocalUser, IRemoteUser } from "@/models/entities/user.js";
 import type { Note, IMentionedRemoteUsers } from "@/models/entities/note.js";
@@ -16,7 +15,7 @@ import { countSameRenotes } from "@/misc/count-same-renotes.js";
 import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
 import { deliverToRelays } from "@/services/relay.js";
 import type { IActivity } from "@/remote/activitypub/type.js";
-import { NoteEvent, publishToNoteStream } from "backend-rs";
+import { NoteEvent, publishToNoteStream, renderTombstone } from "backend-rs";
 
 async function recalculateNotesCountOfLocalUser(user: {
 	id: User["id"];
@@ -102,7 +101,7 @@ export default async function (
 						),
 						user.id,
 					)
-				: renderDelete(renderTombstone(`${config.url}/notes/${note.id}`), user),
+				: renderDelete(renderTombstone(note.id), user),
 		);
 
 		deliverToConcerned(user, note, content);
@@ -127,10 +126,7 @@ export default async function (
 		affectedLocalUsers[cascadingNote.user.id] ??= cascadingNote.user;
 		if (cascadingNote.localOnly) continue; // filter out local-only notes
 		const content = renderActivity(
-			renderDelete(
-				renderTombstone(`${config.url}/notes/${cascadingNote.id}`),
-				cascadingNote.user,
-			),
+			renderDelete(renderTombstone(cascadingNote.id), cascadingNote.user),
 		);
 		deliverToConcerned(cascadingNote.user, cascadingNote, content);
 	}