refactor: simplify ap/show with DbResolver (#8838)

Using the existing code in DbResolver we can avoid separate code for
parsing the URIs in this endpoint.

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
Johann150 2022-06-23 14:32:17 +02:00
parent 00fe1d341b
commit 0cd330afe4
Signed by untrusted user: Johann150
GPG key ID: 9EE6577A2A06F8F1

View file

@ -2,12 +2,13 @@ import define from '../../define.js';
import config from '@/config/index.js'; import config from '@/config/index.js';
import { createPerson } from '@/remote/activitypub/models/person.js'; import { createPerson } from '@/remote/activitypub/models/person.js';
import { createNote } from '@/remote/activitypub/models/note.js'; import { createNote } from '@/remote/activitypub/models/note.js';
import DbResolver from '@/remote/activitypub/db-resolver.js';
import Resolver from '@/remote/activitypub/resolver.js'; import Resolver from '@/remote/activitypub/resolver.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
import { extractDbHost } from '@/misc/convert-host.js'; import { extractDbHost } from '@/misc/convert-host.js';
import { Users, Notes } from '@/models/index.js'; import { Users, Notes } from '@/models/index.js';
import { Note } from '@/models/entities/note.js'; import { Note } from '@/models/entities/note.js';
import { User } from '@/models/entities/user.js'; import { CacheableLocalUser, User } from '@/models/entities/user.js';
import { fetchMeta } from '@/misc/fetch-meta.js'; import { fetchMeta } from '@/misc/fetch-meta.js';
import { isActor, isPost, getApId } from '@/remote/activitypub/type.js'; import { isActor, isPost, getApId } from '@/remote/activitypub/type.js';
import ms from 'ms'; import ms from 'ms';
@ -77,8 +78,8 @@ export const paramDef = {
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps) => { export default define(meta, paramDef, async (ps, me) => {
const object = await fetchAny(ps.uri); const object = await fetchAny(ps.uri, me);
if (object) { if (object) {
return object; return object;
} else { } else {
@ -89,48 +90,18 @@ export default define(meta, paramDef, async (ps) => {
/*** /***
* URIからUserかNoteを解決する * URIからUserかNoteを解決する
*/ */
async function fetchAny(uri: string): Promise<SchemaType<typeof meta['res']> | null> { async function fetchAny(uri: string, me: CacheableLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
// URIがこのサーバーを指しているなら、ローカルユーザーIDとしてDBからフェッチ
if (uri.startsWith(config.url + '/')) {
const parts = uri.split('/');
const id = parts.pop();
const type = parts.pop();
if (type === 'notes') {
const note = await Notes.findOneBy({ id });
if (note) {
return {
type: 'Note',
object: await Notes.pack(note, null, { detail: true }),
};
}
} else if (type === 'users') {
const user = await Users.findOneBy({ id });
if (user) {
return {
type: 'User',
object: await Users.pack(user, null, { detail: true }),
};
}
}
}
// ブロックしてたら中断 // ブロックしてたら中断
const fetchedMeta = await fetchMeta(); const fetchedMeta = await fetchMeta();
if (fetchedMeta.blockedHosts.includes(extractDbHost(uri))) return null; if (fetchedMeta.blockedHosts.includes(extractDbHost(uri))) return null;
// URI(AP Object id)としてDB検索 const dbResolver = new DbResolver();
{
const [user, note] = await Promise.all([
Users.findOneBy({ uri: uri }),
Notes.findOneBy({ uri: uri }),
]);
const packed = await mergePack(user, note); let local = await mergePack(me, ...await Promise.all([
if (packed !== null) return packed; dbResolver.getUserFromApId(uri),
} dbResolver.getNoteFromApId(uri),
]));
if (local != null) return local;
// リモートから一旦オブジェクトフェッチ // リモートから一旦オブジェクトフェッチ
const resolver = new Resolver(); const resolver = new Resolver();
@ -139,74 +110,37 @@ async function fetchAny(uri: string): Promise<SchemaType<typeof meta['res']> | n
// /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する // /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する
// これはDBに存在する可能性があるため再度DB検索 // これはDBに存在する可能性があるため再度DB検索
if (uri !== object.id) { if (uri !== object.id) {
if (object.id.startsWith(config.url + '/')) { local = await mergePack(me, ...await Promise.all([
const parts = object.id.split('/'); dbResolver.getUserFromApId(object.id),
const id = parts.pop(); dbResolver.getNoteFromApId(object.id),
const type = parts.pop(); ]));
if (local != null) return local;
if (type === 'notes') {
const note = await Notes.findOneBy({ id });
if (note) {
return {
type: 'Note',
object: await Notes.pack(note, null, { detail: true }),
};
}
} else if (type === 'users') {
const user = await Users.findOneBy({ id });
if (user) {
return {
type: 'User',
object: await Users.pack(user, null, { detail: true }),
};
}
}
}
const [user, note] = await Promise.all([
Users.findOneBy({ uri: object.id }),
Notes.findOneBy({ uri: object.id }),
]);
const packed = await mergePack(user, note);
if (packed !== null) return packed;
} }
// それでもみつからなければ新規であるため登録 return await mergePack(
if (isActor(object)) { me,
const user = await createPerson(getApId(object)); isActor(object) ? await createPerson(getApId(object)) : null,
return { isPost(object) ? await createNote(getApId(object), undefined, true) : null,
type: 'User', );
object: await Users.pack(user, null, { detail: true }),
};
}
if (isPost(object)) {
const note = await createNote(getApId(object), undefined, true);
return {
type: 'Note',
object: await Notes.pack(note!, null, { detail: true }),
};
}
return null;
} }
async function mergePack(user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> { async function mergePack(me: CacheableLocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> {
if (user != null) { if (user != null) {
return { return {
type: 'User', type: 'User',
object: await Users.pack(user, null, { detail: true }), object: await Users.pack(user, me, { detail: true }),
}; };
} } else if (note != null) {
try {
const object = await Notes.pack(note, me, { detail: true });
if (note != null) { return {
return { type: 'Note',
type: 'Note', object,
object: await Notes.pack(note, null, { detail: true }), };
}; } catch (e) {
return null;
}
} }
return null; return null;