From 885f8e18560ea7cc55970f552fae4ae6780213de Mon Sep 17 00:00:00 2001
From: InspectorCaracal <51038201+InspectorCaracal@users.noreply.github.com>
Date: Fri, 5 Feb 2021 19:50:33 -0700
Subject: [PATCH] Parse followers audience from followers URI (#7112)

* add followersUri

* add followersUri to audience parse

* fetch followersUri

* followersUri db migration

* update followersUri

* Rename 1611354329133-followersUri to 1611354329133-followersUri.ts

* typo

* Update person.ts

* create/update person consistency

* Update audience.ts

* missing paren

* tabs

* use strict equality

* Update audience.ts
---
 migration/1611354329133-followersUri.ts | 16 ++++++++++++++++
 src/models/entities/user.ts             |  6 ++++++
 src/remote/activitypub/audience.ts      |  7 +++----
 src/remote/activitypub/models/person.ts |  2 ++
 4 files changed, 27 insertions(+), 4 deletions(-)
 create mode 100644 migration/1611354329133-followersUri.ts

diff --git a/migration/1611354329133-followersUri.ts b/migration/1611354329133-followersUri.ts
new file mode 100644
index 0000000000..5114418aed
--- /dev/null
+++ b/migration/1611354329133-followersUri.ts
@@ -0,0 +1,16 @@
+import {MigrationInterface, QueryRunner} from "typeorm";
+
+export class followersUri1611354329133 implements MigrationInterface {
+    name = 'followersUri1611354329133'
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "user" ADD "followersUri" varchar(512) DEFAULT NULL`);
+        await queryRunner.query(`COMMENT ON COLUMN "user"."followersUri" IS 'The URI of the user Follower Collection. It will be null if the origin of the user is local.'`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`COMMENT ON COLUMN "user"."followersUri" IS 'The URI of the user Follower Collection. It will be null if the origin of the user is local.'`);
+        await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "followersUri"`);
+    }
+
+}
diff --git a/src/models/entities/user.ts b/src/models/entities/user.ts
index ba2062fdb6..91fbe35d94 100644
--- a/src/models/entities/user.ts
+++ b/src/models/entities/user.ts
@@ -201,6 +201,12 @@ export class User {
 	})
 	public uri: string | null;
 
+	@Column('varchar', {
+		length: 512, nullable: true,
+		comment: 'The URI of the user Follower Collection. It will be null if the origin of the user is local.'
+	})
+	public followersUri: string | null;
+
 	@Index({ unique: true })
 	@Column('char', {
 		length: 16, nullable: true, unique: true,
diff --git a/src/remote/activitypub/audience.ts b/src/remote/activitypub/audience.ts
index 7cff678ae3..85a70f8286 100644
--- a/src/remote/activitypub/audience.ts
+++ b/src/remote/activitypub/audience.ts
@@ -86,8 +86,7 @@ function isPublic(id: string) {
 }
 
 function isFollowers(id: string, actor: IRemoteUser) {
-	return [
-		`${actor.uri}/followers`,
-		// actor.followerUri,	// TODO
-	].includes(id);
+	return (
+		id === (actor.followersUri || `${actor.uri}/followers`)
+	);
 }
diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts
index f0a312b21a..8f1483ab43 100644
--- a/src/remote/activitypub/models/person.ts
+++ b/src/remote/activitypub/models/person.ts
@@ -159,6 +159,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
 				host,
 				inbox: person.inbox,
 				sharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined),
+				followersUri: person.followers ? getApId(person.followers) : undefined,
 				featured: person.featured ? getApId(person.featured) : undefined,
 				uri: person.id,
 				tags,
@@ -330,6 +331,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
 		lastFetchedAt: new Date(),
 		inbox: person.inbox,
 		sharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined),
+		followersUri: person.followers ? getApId(person.followers) : undefined,
 		featured: person.featured,
 		emojis: emojiNames,
 		name: person.name,