diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 4afed7dc5c..46df43325d 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -21,6 +21,10 @@ import { bindThis } from '@/decorators.js'; import { ApiError } from '../../error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { FetchAllowSoftFailMask } from '@/core/activitypub/misc/check-against-url.js'; +import * as Acct from '@/misc/acct.js'; +import { IsNull } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import type { NotesRepository, UsersRepository } from '@/models/_.js'; export const meta = { tags: ['federation'], @@ -116,6 +120,9 @@ export default class extends Endpoint { // eslint- private apDbResolverService: ApDbResolverService, private apPersonService: ApPersonService, private apNoteService: ApNoteService, + + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, ) { super(meta, paramDef, async (ps, me) => { const object = await this.fetchAny(ps.uri, me); @@ -137,7 +144,7 @@ export default class extends Endpoint { // eslint- } let local = await this.mergePack(me, ...await Promise.all([ - this.apDbResolverService.getUserFromApId(uri), + this.apDbResolverService.getUserFromApId(uri).then(async x => x ?? await this.getUserFromProfileUrl(uri)), this.apDbResolverService.getNoteFromApId(uri), ])); if (local != null) return local; @@ -200,6 +207,30 @@ export default class extends Endpoint { // eslint- ); } + // To keep consistency with ap/show from external server, + // this function will handle `https://local.instance/@user` + // profile url to resolve user. + @bindThis + private async getUserFromProfileUrl(url: string): Promise { + if (!this.utilityService.isUriLocal(url)) { + return null; + } + + const uri = new URL(url); + const pathComponents = uri.pathname.split('/').filter(Boolean); + if (pathComponents.length === 1 && pathComponents[0].startsWith('@')) { + const acct = Acct.parse(pathComponents[0]); + + return await this.usersRepository.findOneBy({ + usernameLower: acct.username.toLowerCase(), + host: acct.host ?? IsNull(), + isSuspended: false, + }); + } + + return null; + } + @bindThis private async mergePack(me: MiLocalUser | null | undefined, user: MiUser | null | undefined, note: MiNote | null | undefined): Promise | null> { if (user != null) {