From 630bee0cc497840fac725e96aeffb34999f33a5f Mon Sep 17 00:00:00 2001
From: Daiki Mizukami <tesaguriguma@gmail.com>
Date: Thu, 8 Aug 2024 22:33:35 +0900
Subject: [PATCH] enhance(backend): check visibility of reactions of remote
 users

---
 .../activitypub/models/ApPersonService.ts     | 30 ++++++++++---------
 packages/backend/src/core/activitypub/type.ts |  1 +
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index f3ddf3952c..08f8c3ad55 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -296,17 +296,17 @@ export class ApPersonService implements OnModuleInit {
 
 		const isBot = getApType(object) === 'Service' || getApType(object) === 'Application';
 
-		const [followingVisibility, followersVisibility] = await Promise.all(
+		const [publicReactions, followingIsPublic, followersIsPublic] = await Promise.all(
 			[
+				this.isPublicCollection(person.liked, resolver),
 				this.isPublicCollection(person.following, resolver),
 				this.isPublicCollection(person.followers, resolver),
-			].map((p): Promise<'public' | 'private'> => p
-				.then(isPublic => isPublic ? 'public' : 'private')
+			].map((p): Promise<boolean> => p
 				.catch(err => {
 					if (!(err instanceof StatusError) || err.isRetryable) {
-						this.logger.error('error occurred while fetching following/followers collection', { stack: err });
+						this.logger.error('error occurred while fetching actor collection', { stack: err });
 					}
-					return 'private';
+					return false;
 				})
 			)
 		);
@@ -372,8 +372,9 @@ export class ApPersonService implements OnModuleInit {
 					description: _description,
 					url,
 					fields,
-					followingVisibility,
-					followersVisibility,
+					publicReactions,
+					followingVisibility: followingIsPublic ? 'public' : 'private',
+					followersVisibility: followersIsPublic ? 'public' : 'private',
 					birthday: bday?.[0] ?? null,
 					location: person['vcard:Address'] ?? null,
 					userHost: host,
@@ -481,19 +482,19 @@ export class ApPersonService implements OnModuleInit {
 
 		const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32);
 
-		const [followingVisibility, followersVisibility] = await Promise.all(
+		const [publicReactions, followingIsPublic, followersIsPublic] = await Promise.all(
 			[
+				this.isPublicCollection(person.liked, resolver),
 				this.isPublicCollection(person.following, resolver),
 				this.isPublicCollection(person.followers, resolver),
-			].map((p): Promise<'public' | 'private' | undefined> => p
-				.then(isPublic => isPublic ? 'public' : 'private')
+			].map((p): Promise<boolean | undefined> => p
 				.catch(err => {
 					if (!(err instanceof StatusError) || err.isRetryable) {
-						this.logger.error('error occurred while fetching following/followers collection', { stack: err });
+						this.logger.error('error occurred while fetching actor collection', { stack: err });
 						// Do not update the visibiility on transient errors.
 						return undefined;
 					}
-					return 'private';
+					return false;
 				})
 			)
 		);
@@ -566,8 +567,9 @@ export class ApPersonService implements OnModuleInit {
 			url,
 			fields,
 			description: _description,
-			followingVisibility,
-			followersVisibility,
+			publicReactions,
+			followingVisibility: followingIsPublic ? 'public' : followingIsPublic === false ? 'private' : undefined,
+			followersVisibility: followersIsPublic ? 'public' : followersIsPublic === false ? 'private' : undefined,
 			birthday: bday?.[0] ?? null,
 			location: person['vcard:Address'] ?? null,
 		});
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 131c518c0a..57b0a86f86 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -179,6 +179,7 @@ export interface IActor extends IObject {
 	following?: string | ICollection | IOrderedCollection;
 	featured?: string | IOrderedCollection;
 	outbox: string | IOrderedCollection;
+	liked?: string | ICollection | IOrderedCollection;
 	endpoints?: {
 		sharedInbox?: string;
 	};