diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index fc91fcf5ae..744b1ea683 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -101,7 +101,6 @@ export class ApPersonService implements OnModuleInit { @Inject(DI.followingsRepository) private followingsRepository: FollowingsRepository, - ) { } @@ -227,20 +226,37 @@ export class ApPersonService implements OnModuleInit { return null; } - private async resolveAvatarAndBanner(user: MiRemoteUser, icon: any, image: any): Promise> { + private async resolveAvatarAndBanner(user: MiRemoteUser, icon: any, image: any): Promise>> { + if (user == null) throw new Error('failed to create user: user is null'); + const [avatar, banner] = await Promise.all([icon, image].map(img => { - if (img == null) return null; - if (user == null) throw new Error('failed to create user: user is null'); + // if we have an explicitly missing image, return an + // explicitly-null set of values + if ((img == null) || (typeof img === 'object' && img.url == null)) { + return { id: null, url: null, blurhash: null }; + } + return this.apImageService.resolveImage(user, img).catch(() => null); })); + /* + we don't want to return nulls on errors! if the database fields + are already null, nothing changes; if the database has old + values, we should keep those. The exception is if the remote has + actually removed the images: in that case, the block above + returns the special {id:null}&c value, and we return those + */ return { - avatarId: avatar?.id ?? null, - bannerId: banner?.id ?? null, - avatarUrl: avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null, - bannerUrl: banner ? this.driveFileEntityService.getPublicUrl(banner) : null, - avatarBlurhash: avatar?.blurhash ?? null, - bannerBlurhash: banner?.blurhash ?? null, + ...( avatar ? { + avatarId: avatar.id, + avatarUrl: avatar.url ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null, + avatarBlurhash: avatar.blurhash, + } : {}), + ...( banner ? { + bannerId: banner.id, + bannerUrl: banner.url ? this.driveFileEntityService.getPublicUrl(banner) : null, + bannerBlurhash: banner.blurhash, + } : {}), }; } @@ -444,10 +460,6 @@ export class ApPersonService implements OnModuleInit { const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/); const url = getOneApHrefNullable(person.url); - let host = null; - if (url) { - host = new URL(url).host; - } if (url && !checkHttps(url)) { throw new Error('unexpected schema of person url: ' + url);