forked from FoundKeyGang/FoundKey
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:
parent
00fe1d341b
commit
0cd330afe4
1 changed files with 33 additions and 99 deletions
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue