diff --git a/packages/backend/src/core/activitypub/models/ApEventService.ts b/packages/backend/src/core/activitypub/models/ApEventService.ts new file mode 100644 index 0000000000..3a9117a77c --- /dev/null +++ b/packages/backend/src/core/activitypub/models/ApEventService.ts @@ -0,0 +1,55 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { DI } from '@/di-symbols.js'; +import type { EventsRepository, NotesRepository } from '@/models/index.js'; +import type { Config } from '@/config.js'; +import type Logger from '@/logger.js'; +import { isEvent } from '../type.js'; +import { ApLoggerService } from '../ApLoggerService.js'; +import { ApResolverService } from '../ApResolverService.js'; +import type { Resolver } from '../ApResolverService.js'; +import type { IObject } from '../type.js'; +import { bindThis } from '@/decorators.js'; +import { IEvent } from '@/models/entities/Event.js'; + +@Injectable() +export class ApEventService { + private logger: Logger; + + constructor( + @Inject(DI.config) + private config: Config, + + @Inject(DI.notesRepository) + private notesRepository: NotesRepository, + + @Inject(DI.eventsRepository) + private eventsRepository: EventsRepository, + + private apResolverService: ApResolverService, + private apLoggerService: ApLoggerService, + ) { + this.logger = this.apLoggerService.logger; + } + + @bindThis + public async extractEventFromNote(source: string | IObject, resolver?: Resolver): Promise { + if (resolver == null) resolver = this.apResolverService.createResolver(); + + const note = await resolver.resolve(source); + + if (!isEvent(note)) { + throw new Error('invalid type'); + } + + const title = note.name!; + const start = note.startTime!; + const end = note.endTime ?? null; + + return { + title, + start, + end, + metadata: {}, + }; + } +} diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 5ca5f6e843..54185f3889 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -29,6 +29,7 @@ import { ApPersonService } from './ApPersonService.js'; import { extractApHashtags } from './tag.js'; import { ApMentionService } from './ApMentionService.js'; import { ApQuestionService } from './ApQuestionService.js'; +import { ApEventService } from './ApEventService.js'; import { ApImageService } from './ApImageService.js'; import type { Resolver } from '../ApResolverService.js'; import type { IObject, IPost } from '../type.js'; @@ -60,6 +61,7 @@ export class ApNoteService { private apMentionService: ApMentionService, private apImageService: ApImageService, private apQuestionService: ApQuestionService, + private apEventService: ApEventService, private metaService: MetaService, private appLockService: AppLockService, private pollService: PollService, @@ -275,6 +277,7 @@ export class ApNoteService { const apEmojis = emojis.map(emoji => emoji.name); const poll = await this.apQuestionService.extractPollFromQuestion(note, resolver).catch(() => undefined); + const event = await this.apEventService.extractEventFromNote(note, resolver).catch(() => undefined); return await this.noteCreateService.create(actor, { createdAt: note.published ? new Date(note.published) : null, @@ -291,6 +294,7 @@ export class ApNoteService { apHashtags, apEmojis, poll, + event, uri: note.id, url: url, }, silent); diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index 625135da6c..a1d51f1a70 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -133,6 +133,9 @@ export interface IQuestion extends IObject { export const isQuestion = (object: IObject): object is IQuestion => getApType(object) === 'Note' || getApType(object) === 'Question'; +export const isEvent = (object: IObject): object is IObject => + getApType(object) === 'Note' || getApType(object) === 'Event'; + interface IQuestionChoice { name?: string; replies?: ICollection;