From ee754f83cd043b61d6ec37618f11614cb39782b9 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 17 Apr 2018 15:30:58 +0900
Subject: [PATCH] #1448

---
 src/remote/activitypub/objects/note.ts   |  7 ++-
 src/remote/activitypub/objects/person.ts | 80 ++++++++++++++++++++++++
 2 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/src/remote/activitypub/objects/note.ts b/src/remote/activitypub/objects/note.ts
index 3edcb8c63f..221d502f06 100644
--- a/src/remote/activitypub/objects/note.ts
+++ b/src/remote/activitypub/objects/note.ts
@@ -6,7 +6,7 @@ import Resolver from '../resolver';
 import Note, { INote } from '../../../models/note';
 import post from '../../../services/note/create';
 import { INote as INoteActivityStreamsObject, IObject } from '../type';
-import { resolvePerson } from './person';
+import { resolvePerson, updatePerson } from './person';
 import { resolveImage } from './image';
 import { IRemoteUser } from '../../../models/user';
 
@@ -75,6 +75,11 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 
 	const { window } = new JSDOM(note.content);
 
+	// ユーザーの情報が古かったらついでに更新しておく
+	if (actor.updatedAt && Date.now() - actor.updatedAt.getTime() > 1000 * 60 * 60 * 24) {
+		updatePerson(note.attributedTo);
+	}
+
 	return await post(actor, {
 		createdAt: new Date(note.published),
 		media,
diff --git a/src/remote/activitypub/objects/person.ts b/src/remote/activitypub/objects/person.ts
index b0539fd73b..b755b2603a 100644
--- a/src/remote/activitypub/objects/person.ts
+++ b/src/remote/activitypub/objects/person.ts
@@ -119,6 +119,86 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs
 	return user;
 }
 
+/**
+ * Personの情報を更新します。
+ *
+ * Misskeyに対象のPersonが登録されていなければ無視します。
+ */
+export async function updatePerson(value: string | IObject, resolver?: Resolver): Promise<void> {
+	const uri = typeof value == 'string' ? value : value.id;
+
+	// URIがこのサーバーを指しているならスキップ
+	if (uri.startsWith(config.url + '/')) {
+		return;
+	}
+
+	//#region このサーバーに既に登録されているか
+	const exist = await User.findOne({ uri }) as IRemoteUser;
+
+	if (exist == null) {
+		return;
+	}
+	//#endregion
+
+	if (resolver == null) resolver = new Resolver();
+
+	const object = await resolver.resolve(value) as any;
+
+	if (
+		object == null ||
+		object.type !== 'Person'
+	) {
+		log(`invalid person: ${JSON.stringify(object, null, 2)}`);
+		throw new Error('invalid person');
+	}
+
+	const person: IPerson = object;
+
+	log(`Updating the Person: ${person.id}`);
+
+	const [followersCount = 0, followingCount = 0, notesCount = 0] = await Promise.all([
+		resolver.resolve(person.followers).then(
+			resolved => isCollectionOrOrderedCollection(resolved) ? resolved.totalItems : undefined,
+			() => undefined
+		),
+		resolver.resolve(person.following).then(
+			resolved => isCollectionOrOrderedCollection(resolved) ? resolved.totalItems : undefined,
+			() => undefined
+		),
+		resolver.resolve(person.outbox).then(
+			resolved => isCollectionOrOrderedCollection(resolved) ? resolved.totalItems : undefined,
+			() => undefined
+		)
+	]);
+
+	const summaryDOM = JSDOM.fragment(person.summary);
+
+	// アイコンとヘッダー画像をフェッチ
+	const [avatarId, bannerId] = (await Promise.all([
+		person.icon,
+		person.image
+	].map(img =>
+		img == null
+			? Promise.resolve(null)
+			: resolveImage(exist, img)
+	))).map(file => file != null ? file._id : null);
+
+	// Update user
+	await User.update({ _id: exist._id }, {
+		$set: {
+			updatedAt: new Date(),
+			avatarId,
+			bannerId,
+			description: summaryDOM.textContent,
+			followersCount,
+			followingCount,
+			notesCount,
+			name: person.name,
+			url: person.url
+		}
+	});
+}
+
 /**
  * Personを解決します。
  *