import { Inject, Injectable } from '@nestjs/common'; import Redis from 'ioredis'; import type { User } from '@/models/entities/User.js'; import type { Note } from '@/models/entities/Note.js'; import type { UserList } from '@/models/entities/UserList.js'; import type { UserGroup } from '@/models/entities/UserGroup.js'; import type { Antenna } from '@/models/entities/Antenna.js'; import type { Channel } from '@/models/entities/Channel.js'; import type { StreamChannels, AdminStreamTypes, AntennaStreamTypes, BroadcastTypes, ChannelStreamTypes, DriveStreamTypes, GroupMessagingStreamTypes, InternalStreamTypes, MainStreamTypes, MessagingIndexStreamTypes, MessagingStreamTypes, NoteStreamTypes, UserListStreamTypes, UserStreamTypes, } from '@/server/api/stream/types.js'; import type { Packed } from '@/misc/schema.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; @Injectable() export class GlobalEventService { constructor( @Inject(DI.config) private config: Config, @Inject(DI.redis) private redisClient: Redis.Redis, ) { } private publish(channel: StreamChannels, type: string | null, value?: any): void { const message = type == null ? value : value == null ? { type: type, body: null } : { type: type, body: value }; this.redisClient.publish(this.config.host, JSON.stringify({ channel: channel, message: message, })); } public publishInternalEvent(type: K, value?: InternalStreamTypes[K]): void { this.publish('internal', type, typeof value === 'undefined' ? null : value); } public publishUserEvent(userId: User['id'], type: K, value?: UserStreamTypes[K]): void { this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value); } public publishBroadcastStream(type: K, value?: BroadcastTypes[K]): void { this.publish('broadcast', type, typeof value === 'undefined' ? null : value); } public publishMainStream(userId: User['id'], type: K, value?: MainStreamTypes[K]): void { this.publish(`mainStream:${userId}`, type, typeof value === 'undefined' ? null : value); } public publishDriveStream(userId: User['id'], type: K, value?: DriveStreamTypes[K]): void { this.publish(`driveStream:${userId}`, type, typeof value === 'undefined' ? null : value); } public publishNoteStream(noteId: Note['id'], type: K, value?: NoteStreamTypes[K]): void { this.publish(`noteStream:${noteId}`, type, { id: noteId, body: value, }); } public publishChannelStream(channelId: Channel['id'], type: K, value?: ChannelStreamTypes[K]): void { this.publish(`channelStream:${channelId}`, type, typeof value === 'undefined' ? null : value); } public publishUserListStream(listId: UserList['id'], type: K, value?: UserListStreamTypes[K]): void { this.publish(`userListStream:${listId}`, type, typeof value === 'undefined' ? null : value); } public publishAntennaStream(antennaId: Antenna['id'], type: K, value?: AntennaStreamTypes[K]): void { this.publish(`antennaStream:${antennaId}`, type, typeof value === 'undefined' ? null : value); } public publishMessagingStream(userId: User['id'], otherpartyId: User['id'], type: K, value?: MessagingStreamTypes[K]): void { this.publish(`messagingStream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value); } public publishGroupMessagingStream(groupId: UserGroup['id'], type: K, value?: GroupMessagingStreamTypes[K]): void { this.publish(`messagingStream:${groupId}`, type, typeof value === 'undefined' ? null : value); } public publishMessagingIndexStream(userId: User['id'], type: K, value?: MessagingIndexStreamTypes[K]): void { this.publish(`messagingIndexStream:${userId}`, type, typeof value === 'undefined' ? null : value); } public publishNotesStream(note: Packed<'Note'>): void { this.publish('notesStream', null, note); } public publishAdminStream(userId: User['id'], type: K, value?: AdminStreamTypes[K]): void { this.publish(`adminStream:${userId}`, type, typeof value === 'undefined' ? null : value); } }