diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index d0d206760cb9..d91eed34988a 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -29,7 +29,7 @@ import { bindThis } from '@/decorators.js'; import type { MiRemoteUser } from '@/models/User.js'; import { isNotNull } from '@/misc/is-not-null.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; +import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, isValidActor, isValidPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; import { ApDbResolverService } from './ApDbResolverService.js'; @@ -471,9 +471,9 @@ export class ApInboxService { formerType = 'Note'; } - if (validPost.includes(formerType)) { + if (isValidPost(formerType)) { return await this.deleteNote(actor, uri); - } else if (validActor.includes(formerType)) { + } else if (isValidActor(formerType)) { return await this.deleteActor(actor, uri); } else { return `Unknown type ${formerType}`; diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index a2e47327e27b..24bfd63d1776 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -25,7 +25,7 @@ import { bindThis } from '@/decorators.js'; import { checkHttps } from '@/misc/check-https.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { isNotNull } from '@/misc/is-not-null.js'; -import { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js'; +import { getOneApId, getApId, getOneApHrefNullable, isEmoji, getApType, isPost } from '../type.js'; import { ApLoggerService } from '../ApLoggerService.js'; import { ApMfmService } from '../ApMfmService.js'; import { ApDbResolverService } from '../ApDbResolverService.js'; @@ -80,7 +80,7 @@ export class ApNoteService { public validateNote(object: IObject, uri: string): Error | null { const expectHost = this.utilityService.extractDbHost(uri); - if (!validPost.includes(getApType(object))) { + if (!isPost(object)) { return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${getApType(object)}`); } diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index 5b6c6c8ca6cb..94f80ee799a3 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -61,10 +61,10 @@ export function getApId(value: string | IObject): string { /** * Get ActivityStreams Object type */ -export function getApType(value: IObject): string { +export function getApType(value: IObject): string | null { if (typeof value.type === 'string') return value.type; if (Array.isArray(value.type) && typeof value.type[0] === 'string') return value.type[0]; - throw new Error('cannot detect type'); + return null; } export function getOneApHrefNullable(value: ApObject | undefined): string | undefined { @@ -106,13 +106,17 @@ export interface IOrderedCollection extends IObject { orderedItems: ApObject; } -export const validPost = ['Note', 'Question', 'Article', 'Audio', 'Document', 'Image', 'Page', 'Video', 'Event']; +// つまるところこれをしないとnull許容でincludesできないので必須 +type ValidArrayIncludesNullable = readonly (string | null)[]; +const validPost = ['Note', 'Question', 'Article', 'Audio', 'Document', 'Image', 'Page', 'Video', 'Event'] as const; +export const isValidPost = (type: string | null): boolean => + (validPost as ValidArrayIncludesNullable).includes(type); export const isPost = (object: IObject): object is IPost => - validPost.includes(getApType(object)); + isValidPost(getApType(object)); export interface IPost extends IObject { - type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video' | 'Event'; + type: (typeof validPost)[number]; source?: { content: string; mediaType: string; @@ -154,13 +158,15 @@ export interface ITombstone extends IObject { export const isTombstone = (object: IObject): object is ITombstone => getApType(object) === 'Tombstone'; -export const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application']; +const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application'] as const; +export const isValidActor = (type: string | null): boolean => + (validActor as ValidArrayIncludesNullable).includes(type); export const isActor = (object: IObject): object is IActor => - validActor.includes(getApType(object)); + isValidActor(getApType(object)); export interface IActor extends IObject { - type: 'Person' | 'Service' | 'Organization' | 'Group' | 'Application'; + type: (typeof validActor)[number]; name?: string; preferredUsername?: string; manuallyApprovesFollowers?: boolean; @@ -240,12 +246,16 @@ export interface IKey extends IObject { publicKeyPem: string | Buffer; } -export interface IApDocument extends IObject { - type: 'Audio' | 'Document' | 'Image' | 'Page' | 'Video'; -} +const validDocument = ['Audio', 'Document', 'Image', 'Page', 'Video'] as const; +export const isValidDocument = (type: string | null): boolean => + (validDocument as ValidArrayIncludesNullable).includes(type); export const isDocument = (object: IObject): object is IApDocument => - ['Audio', 'Document', 'Image', 'Page', 'Video'].includes(getApType(object)); + isValidDocument(getApType(object)); + +export interface IApDocument extends IObject { + type: (typeof validDocument)[number]; +} export interface IApImage extends IApDocument { type: 'Image';