diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index e89ee4632..22ef0b139 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -43,6 +43,7 @@ import type { ApLoggerService } from '../ApLoggerService.js'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import type { ApImageService } from './ApImageService.js'; import type { IActor, IObject } from '../type.js'; +import { ca } from 'date-fns/locale'; const nameLength = 128; const summaryLength = 2048; @@ -259,13 +260,49 @@ export class ApPersonService implements OnModuleInit { // Create user let user: RemoteUser | null = null; + const userAdditionalInfo: Pick = { + avatarId: null, + bannerId: null, + avatarUrl: null, + bannerUrl: null, + avatarBlurhash: null, + bannerBlurhash: null, + emojis: [], + }; + + try { + //#region アバターとヘッダー画像をフェッチ + const [avatar, banner] = await Promise.all([person.icon, person.image].map(img => { + if (img == null) return null; + if (user == null) throw new Error('failed to create user: user is null'); + return this.apImageService.resolveImage(user, img).catch(() => null); + })); + + userAdditionalInfo.avatarId = avatar?.id ?? null; + userAdditionalInfo.bannerId = banner?.id ?? null; + userAdditionalInfo.avatarUrl = avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null; + userAdditionalInfo.bannerUrl = banner ? this.driveFileEntityService.getPublicUrl(banner) : null; + userAdditionalInfo.avatarBlurhash = avatar?.blurhash ?? null; + userAdditionalInfo.bannerBlurhash = banner?.blurhash ?? null; + //#endregion + } catch (err) { + this.logger.error('error occured while fetching user avatar/banner', { stack: err }); + } + + //#region カスタム絵文字取得 + userAdditionalInfo.emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host) + .then(_emojis => _emojis.map(emoji => emoji.name)) + .catch(err => { + this.logger.error(`error occured while fetching user emojis`, { stack: err }); + return []; + }); + //#endregion + try { // Start transaction await this.db.transaction(async transactionalEntityManager => { user = await transactionalEntityManager.save(new User({ id: this.idService.genId(), - avatarId: null, - bannerId: null, createdAt: new Date(), lastFetchedAt: new Date(), name: truncate(person.name, nameLength), @@ -285,6 +322,7 @@ export class ApPersonService implements OnModuleInit { tags, isBot, isCat: (person as any).isCat === true, + ...userAdditionalInfo, })) as RemoteUser; await transactionalEntityManager.save(new UserProfile({ @@ -321,6 +359,9 @@ export class ApPersonService implements OnModuleInit { if (user == null) throw new Error('failed to create user: user is null'); + // Register to the cache + this.cacheService.uriPersonCache.set(user.uri, user); + // Register host this.federatedInstanceService.fetch(host).then(async i => { this.instancesRepository.increment({ id: i.id }, 'usersCount', 1); @@ -335,48 +376,6 @@ export class ApPersonService implements OnModuleInit { // ハッシュタグ更新 this.hashtagService.updateUsertags(user, tags); - //#region アバターとヘッダー画像をフェッチ - const [avatar, banner] = await Promise.all([person.icon, person.image].map(img => { - if (img == null) return null; - if (user == null) throw new Error('failed to create user: user is null'); - return this.apImageService.resolveImage(user, img).catch(() => null); - })); - - const avatarId = avatar?.id ?? null; - const bannerId = banner?.id ?? null; - const avatarUrl = avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null; - const bannerUrl = banner ? this.driveFileEntityService.getPublicUrl(banner) : null; - const avatarBlurhash = avatar?.blurhash ?? null; - const bannerBlurhash = banner?.blurhash ?? null; - - await this.usersRepository.update(user.id, { - avatarId, - bannerId, - avatarUrl, - bannerUrl, - avatarBlurhash, - bannerBlurhash, - }); - - user.avatarId = avatarId; - user.bannerId = bannerId; - user.avatarUrl = avatarUrl; - user.bannerUrl = bannerUrl; - user.avatarBlurhash = avatarBlurhash; - user.bannerBlurhash = bannerBlurhash; - //#endregion - - //#region カスタム絵文字取得 - const emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host).catch(err => { - this.logger.info(`extractEmojis: ${err}`); - return []; - }); - - const emojiNames = emojis.map(emoji => emoji.name); - - await this.usersRepository.update(user.id, { emojis: emojiNames }); - //#endregion - await this.updateFeatured(user.id, resolver).catch(err => this.logger.error(err)); return user; @@ -400,7 +399,7 @@ export class ApPersonService implements OnModuleInit { if (uri.startsWith(`${this.config.url}/`)) return; //#region このサーバーに既に登録されているか - const exist = await this.usersRepository.findOneBy({ uri }) as RemoteUser | null; + const exist = await this.fetchPerson(uri) as RemoteUser | null; if (exist === null) return; //#endregion