diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2019-04-13 01:43:22 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-13 01:43:22 +0900 |
| commit | 987168b863c52d0548050ffbac569782bb9a8cef (patch) | |
| tree | c9aa2243dcdcbd044688d201a51c601574bff259 /src/remote/activitypub/models/note.ts | |
| parent | Fix bug (diff) | |
| download | misskey-987168b863c52d0548050ffbac569782bb9a8cef.tar.gz misskey-987168b863c52d0548050ffbac569782bb9a8cef.tar.bz2 misskey-987168b863c52d0548050ffbac569782bb9a8cef.zip | |
strictNullChecks (#4666)
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
Diffstat (limited to 'src/remote/activitypub/models/note.ts')
| -rw-r--r-- | src/remote/activitypub/models/note.ts | 126 |
1 files changed, 67 insertions, 59 deletions
diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts index eb4175875d..78f5005953 100644 --- a/src/remote/activitypub/models/note.ts +++ b/src/remote/activitypub/models/note.ts @@ -21,6 +21,7 @@ import { IObject, INote } from '../type'; import { Emoji } from '../../../models/entities/emoji'; import { genId } from '../../../misc/gen-id'; import fetchMeta from '../../../misc/fetch-meta'; +import { ensure } from '../../../prelude/ensure'; const logger = apLogger; @@ -29,13 +30,14 @@ const logger = apLogger; * * Misskeyに対象のNoteが登録されていればそれを返します。 */ -export async function fetchNote(value: string | IObject, resolver?: Resolver): Promise<Note> { +export async function fetchNote(value: string | IObject, resolver?: Resolver): Promise<Note | null> { const uri = typeof value == 'string' ? value : value.id; + if (uri == null) throw 'missing uri'; // URIがこのサーバーを指しているならデータベースからフェッチ if (uri.startsWith(config.url + '/')) { const id = uri.split('/').pop(); - return await Notes.findOne(id); + return await Notes.findOne(id).then(x => x || null); } //#region このサーバーに既に登録されていたらそれを返す @@ -52,7 +54,7 @@ export async function fetchNote(value: string | IObject, resolver?: Resolver): P /** * Noteを作成します。 */ -export async function createNote(value: any, resolver?: Resolver, silent = false): Promise<Note> { +export async function createNote(value: any, resolver?: Resolver, silent = false): Promise<Note | null> { if (resolver == null) resolver = new Resolver(); const object: any = await resolver.resolve(value); @@ -65,7 +67,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false value: value, object: object }); - return null; + throw 'invalid note'; } const note: INote = object; @@ -75,11 +77,11 @@ export async function createNote(value: any, resolver?: Resolver, silent = false logger.info(`Creating the Note: ${note.id}`); // 投稿者をフェッチ - const actor = await resolvePerson(note.attributedTo, null, resolver) as IRemoteUser; + const actor = await resolvePerson(note.attributedTo, resolver) as IRemoteUser; // 投稿者が凍結されていたらスキップ if (actor.isSuspended) { - return null; + throw 'actor has been suspended'; } //#region Visibility @@ -95,9 +97,9 @@ export async function createNote(value: any, resolver?: Resolver, silent = false visibility = 'followers'; } else { visibility = 'specified'; - visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri, null, resolver))); + visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri, resolver))); } -} + } //#endergion const apMentions = await extractMentionedUsers(actor, note.to, note.cc, resolver); @@ -118,7 +120,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false : []; // リプライ - const reply: Note = note.inReplyTo + const reply: Note | undefined | null = note.inReplyTo ? await resolveNote(note.inReplyTo, resolver).catch(e => { // 4xxの場合はリプライしてないことにする if (e.statusCode >= 400 && e.statusCode < 500) { @@ -131,7 +133,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false : null; // 引用 - let quote: Note; + let quote: Note | undefined | null; if (note._misskey_quote && typeof note._misskey_quote == 'string') { quote = await resolveNote(note._misskey_quote).catch(e => { @@ -152,7 +154,8 @@ export async function createNote(value: any, resolver?: Resolver, silent = false // vote if (reply && reply.hasPoll) { - const poll = await Polls.findOne({ noteId: reply.id }); + const poll = await Polls.findOne({ noteId: reply.id }).then(ensure); + const tryCreateVote = async (name: string, index: number): Promise<null> => { if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) { logger.warn(`vote to expired poll from AP: actor=${actor.username}@${actor.host}, note=${note.id}, choice=${name}`); @@ -180,7 +183,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false } } - const emojis = await extractEmojis(note.tag, actor.host).catch(e => { + const emojis = await extractEmojis(note.tag || [], actor.host).catch(e => { logger.info(`extractEmojis: ${e}`); return [] as Emoji[]; }); @@ -196,7 +199,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false } return await post(actor, { - createdAt: new Date(note.published), + createdAt: note.published ? new Date(note.published) : null, files, reply, renote: quote, @@ -223,8 +226,9 @@ export async function createNote(value: any, resolver?: Resolver, silent = false * Misskeyに対象のNoteが登録されていればそれを返し、そうでなければ * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 */ -export async function resolveNote(value: string | IObject, resolver?: Resolver): Promise<Note> { +export async function resolveNote(value: string | IObject, resolver?: Resolver): Promise<Note | null> { const uri = typeof value == 'string' ? value : value.id; + if (uri == null) throw 'missing uri'; // ブロックしてたら中断 // TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく @@ -244,75 +248,79 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver): // 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。 return await createNote(uri, resolver).catch(e => { if (e.name === 'duplicated') { - return fetchNote(uri); + return fetchNote(uri).then(note => { + if (note == null) { + throw 'something happened'; + } else { + return note; + } + }); } else { throw e; } }); } -export async function extractEmojis(tags: ITag[], host: string) { +export async function extractEmojis(tags: ITag[], host: string): Promise<Emoji[]> { host = toPuny(host); if (!tags) return []; - const eomjiTags = tags.filter(tag => tag.type === 'Emoji' && tag.icon && tag.icon.url); - - return await Promise.all( - eomjiTags.map(async tag => { - const name = tag.name.replace(/^:/, '').replace(/:$/, ''); + const eomjiTags = tags.filter(tag => tag.type === 'Emoji' && tag.icon && tag.icon.url && tag.name); - const exists = await Emojis.findOne({ - host, - name - }); + return await Promise.all(eomjiTags.map(async tag => { + const name = tag.name!.replace(/^:/, '').replace(/:$/, ''); - if (exists) { - if ((tag.updated != null && exists.updatedAt == null) - || (tag.id != null && exists.uri == null) - || (tag.updated != null && exists.updatedAt != null && new Date(tag.updated) > exists.updatedAt) - ) { - await Emojis.update({ - host, - name, - }, { - uri: tag.id, - url: tag.icon.url, - updatedAt: new Date(tag.updated), - }); + const exists = await Emojis.findOne({ + host, + name + }); - return await Emojis.findOne({ - host, - name - }); - } + if (exists) { + if ((tag.updated != null && exists.updatedAt == null) + || (tag.id != null && exists.uri == null) + || (tag.updated != null && exists.updatedAt != null && new Date(tag.updated) > exists.updatedAt) + ) { + await Emojis.update({ + host, + name, + }, { + uri: tag.id, + url: tag.icon!.url, + updatedAt: new Date(tag.updated!), + }); - return exists; + return await Emojis.findOne({ + host, + name + }) as Emoji; } - logger.info(`register emoji host=${host}, name=${name}`); + return exists; + } - return await Emojis.save({ - id: genId(), - host, - name, - uri: tag.id, - url: tag.icon.url, - updatedAt: tag.updated ? new Date(tag.updated) : undefined, - aliases: [] - } as Emoji); - }) - ); + logger.info(`register emoji host=${host}, name=${name}`); + + return await Emojis.save({ + id: genId(), + host, + name, + uri: tag.id, + url: tag.icon!.url, + updatedAt: tag.updated ? new Date(tag.updated) : undefined, + aliases: [] + } as Partial<Emoji>); + })); } async function extractMentionedUsers(actor: IRemoteUser, to: string[], cc: string[], resolver: Resolver) { const ignoreUris = ['https://www.w3.org/ns/activitystreams#Public', `${actor.uri}/followers`]; const uris = difference(unique(concat([to || [], cc || []])), ignoreUris); - const limit = promiseLimit(2); + const limit = promiseLimit<User | null>(2); const users = await Promise.all( - uris.map(uri => limit(() => resolvePerson(uri, null, resolver).catch(() => null)) as Promise<User>) + uris.map(uri => limit(() => resolvePerson(uri, resolver).catch(() => null)) as Promise<User | null>) ); - return users.filter(x => x != null); + return users.filter(x => x != null) as User[]; } |