From fef1ad3540da347dbf3bd649259a0f68cf1d8af2 Mon Sep 17 00:00:00 2001 From: NoriDev <11006910+noridev@users.noreply.github.com> Date: Thu, 31 Aug 2023 18:52:50 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=AA=E3=83=A2=E3=83=BC=E3=83=88=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E3=81=AE=E3=83=8E=E3=83=BC=E3=83=88?= =?UTF-8?q?/=E3=83=95=E3=82=A9=E3=83=AD=E3=83=BC/=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=AD=E3=83=AF=E3=83=BC=E6=95=B0=E3=82=92=E3=83=AA=E3=83=A2?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=AE?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=81=A8=E5=90=8C=E3=81=98=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E8=A6=8B=E3=81=88=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=20(#362)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test * Update CHANGELOG_CHERRYPICK.md --- CHANGELOG_CHERRYPICK.md | 1 + .../activitypub/models/ApPersonService.ts | 140 +++++++++++++++++- .../src/core/entities/UserEntityService.ts | 4 +- 3 files changed, 142 insertions(+), 3 deletions(-) diff --git a/CHANGELOG_CHERRYPICK.md b/CHANGELOG_CHERRYPICK.md index 4b7c295d52..509ecec225 100644 --- a/CHANGELOG_CHERRYPICK.md +++ b/CHANGELOG_CHERRYPICK.md @@ -34,6 +34,7 @@ - 타임라인 소개 추가 - 이용 약관을 서버 메뉴에서 볼 수 있도록 - 계정 초기 설정과 타임라인 튜토리얼을 다시 진행할 수 있도록 +- 리모트 사용자의 노트/팔로잉/팔로워 수를 리모트 서버의 정보와 동일하게 보이도록 - 유저 메뉴에서 '리모트 유저 정보 갱신'을 진행할 수 있도록 - 설정에서 변경 가능한 옵션은 다이얼로그에서 안내하도록 주석 추가 diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 12da6039af..b74f52b8ce 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -279,6 +279,51 @@ export class ApPersonService implements OnModuleInit { throw new Error('unexpected schema of person url: ' + url); } + let followersCount: number | undefined; + + if (typeof person.followers === 'string') { + try { + const data = await fetch(person.followers, { + headers: { Accept: 'application/json' }, + }); + const jsonData = JSON.parse(await data.text()); + + followersCount = jsonData.totalItems; + } catch { + followersCount = undefined; + } + } + + let followingCount: number | undefined; + + if (typeof person.following === 'string') { + try { + const data = await fetch(person.following, { + headers: { Accept: 'application/json' }, + }); + const jsonData = JSON.parse(await data.text()); + + followingCount = jsonData.totalItems; + } catch (e) { + followingCount = undefined; + } + } + + let notesCount: number | undefined; + + if (typeof person.outbox === 'string') { + try { + const data = await fetch(person.outbox, { + headers: { Accept: 'application/json' }, + }); + const jsonData = JSON.parse(await data.text()); + + notesCount = jsonData.totalItems; + } catch (e) { + notesCount = undefined; + } + } + // Create user let user: MiRemoteUser | null = null; @@ -312,6 +357,30 @@ export class ApPersonService implements OnModuleInit { inbox: person.inbox, sharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox, followersUri: person.followers ? getApId(person.followers) : undefined, + followersCount: + followersCount !== undefined + ? followersCount + : person.followers && + typeof person.followers !== 'string' && + isCollectionOrOrderedCollection(person.followers) + ? person.followers.totalItems + : undefined, + followingCount: + followingCount !== undefined + ? followingCount + : person.following && + typeof person.following !== 'string' && + isCollectionOrOrderedCollection(person.following) + ? person.following.totalItems + : undefined, + notesCount: + notesCount !== undefined + ? notesCount + : person.outbox && + typeof person.outbox !== 'string' && + isCollectionOrOrderedCollection(person.outbox) + ? person.outbox.totalItems + : undefined, featured: person.featured ? getApId(person.featured) : undefined, uri: person.id, tags, @@ -440,11 +509,80 @@ export class ApPersonService implements OnModuleInit { throw new Error('unexpected schema of person url: ' + url); } + let followersCount: number | undefined; + + if (typeof person.followers === 'string') { + try { + const data = await fetch(person.followers, { + headers: { Accept: 'application/json' }, + }); + const jsonData = JSON.parse(await data.text()); + + followersCount = jsonData.totalItems; + } catch { + followersCount = undefined; + } + } + + let followingCount: number | undefined; + + if (typeof person.following === 'string') { + try { + const data = await fetch(person.following, { + headers: { Accept: 'application/json' }, + }); + const jsonData = JSON.parse(await data.text()); + + followingCount = jsonData.totalItems; + } catch { + followingCount = undefined; + } + } + + let notesCount: number | undefined; + + if (typeof person.outbox === 'string') { + try { + const data = await fetch(person.outbox, { + headers: { Accept: 'application/json' }, + }); + const jsonData = JSON.parse(await data.text()); + + notesCount = jsonData.totalItems; + } catch (e) { + notesCount = undefined; + } + } + const updates = { lastFetchedAt: new Date(), inbox: person.inbox, sharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox, followersUri: person.followers ? getApId(person.followers) : undefined, + followersCount: + followersCount !== undefined + ? followersCount + : person.followers && + typeof person.followers !== 'string' && + isCollectionOrOrderedCollection(person.followers) + ? person.followers.totalItems + : undefined, + followingCount: + followingCount !== undefined + ? followingCount + : person.following && + typeof person.following !== 'string' && + isCollectionOrOrderedCollection(person.following) + ? person.following.totalItems + : undefined, + notesCount: + notesCount !== undefined + ? notesCount + : person.outbox && + typeof person.outbox !== 'string' && + isCollectionOrOrderedCollection(person.outbox) + ? person.outbox.totalItems + : undefined, featured: person.featured, emojis: emojiNames, name: truncate(person.name, nameLength), @@ -587,7 +725,7 @@ export class ApPersonService implements OnModuleInit { // Resolve to Object(may be Note) arrays const unresolvedItems = isCollection(collection) ? collection.items : collection.orderedItems; - const items = await Promise.all(toArray(unresolvedItems).map(x => _resolver.resolve(x))); + const items = await Promise.all(toArray(unresolvedItems).map(x => _resolver?.resolve(x))); // Resolve and regist Notes const limit = promiseLimit(2); diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 69911c7f56..b339f52844 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -421,8 +421,8 @@ export class UserEntityService implements OnModuleInit { birthday: profile!.birthday, lang: profile!.lang, fields: profile!.fields, - followersCount: followersCount ?? 0, - followingCount: followingCount ?? 0, + followersCount: followersCount ?? '?', + followingCount: followingCount ?? '?', notesCount: user.notesCount, pinnedNoteIds: pins.map(pin => pin.noteId), pinnedNotes: this.noteEntityService.packMany(pins.map(pin => pin.note!), me, {