diff --git a/src/models/repositories/emoji.ts b/src/models/repositories/emoji.ts index c3d7184ec9..1bbe6b8215 100644 --- a/src/models/repositories/emoji.ts +++ b/src/models/repositories/emoji.ts @@ -1,6 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Emoji } from '@/models/entities/emoji'; +export type PackedEmoji = FIXME; + @EntityRepository(Emoji) export class EmojiRepository extends Repository { public async pack( diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts index dc91ad51b8..eb2561be91 100644 --- a/src/models/repositories/games/reversi/game.ts +++ b/src/models/repositories/games/reversi/game.ts @@ -3,6 +3,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../../../index'; import { ReversiGame } from '@/models/entities/games/reversi/game'; +export type PackedReversiGame = FIXME; + @EntityRepository(ReversiGame) export class ReversiGameRepository extends Repository { public async pack( diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 148221dee5..91615091ac 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -4,6 +4,8 @@ import { Users } from '../../../index'; import { awaitAll } from '@/prelude/await-all'; import { User } from '@/models/entities/user'; +export type PackedReversiMatching = FIXME; + @EntityRepository(ReversiMatching) export class ReversiMatchingRepository extends Repository { public async pack( diff --git a/src/server/api/common/read-messaging-message.ts b/src/server/api/common/read-messaging-message.ts index 1dce76d2a9..33f41b2770 100644 --- a/src/server/api/common/read-messaging-message.ts +++ b/src/server/api/common/read-messaging-message.ts @@ -77,7 +77,7 @@ export async function readGroupMessagingMessage( id: In(messageIds) }); - const reads = []; + const reads: MessagingMessage['id'][] = []; for (const message of messages) { if (message.userId === userId) continue; diff --git a/src/server/api/endpoints/antennas/update.ts b/src/server/api/endpoints/antennas/update.ts index ff13e89bcc..d69b4feee6 100644 --- a/src/server/api/endpoints/antennas/update.ts +++ b/src/server/api/endpoints/antennas/update.ts @@ -137,7 +137,7 @@ export default define(meta, async (ps, user) => { notify: ps.notify, }); - publishInternalEvent('antennaUpdated', Antennas.findOneOrFail(antenna.id)); + publishInternalEvent('antennaUpdated', await Antennas.findOneOrFail(antenna.id)); return await Antennas.pack(antenna.id); }); diff --git a/src/server/api/stream/channels/channel.ts b/src/server/api/stream/channels/channel.ts index e6a9a6c696..a5692563f3 100644 --- a/src/server/api/stream/channels/channel.ts +++ b/src/server/api/stream/channels/channel.ts @@ -19,7 +19,7 @@ export default class extends Channel { this.channelId = params.channelId as string; // Subscribe stream - this.subscriber.on('notesStream', this.onNote); + this.subscriber.on('notesStream', e => this.onNote(e)); this.subscriber.on(`channelStream:${this.channelId}`, this.onEvent); this.emitTypersIntervalId = setInterval(this.emitTypers, 5000); } diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 18eba58538..7d2e918af6 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -1,7 +1,6 @@ import { User } from '@/models/entities/user'; import { EventEmitter } from 'events'; import Emitter from 'strict-event-emitter-types'; -import StreamTypes from 'misskey-js/built/streaming.types'; import { Channel } from '@/models/entities/channel'; import { UserProfile } from '@/models/entities/user-profile'; import { PackedUser } from '@/models/repositories/user'; @@ -14,6 +13,16 @@ import { PackedDriveFolder } from '@/models/repositories/drive-folder'; import { DriveFolder } from '@/models/entities/drive-folder'; import { Note } from '@/models/entities/note'; import { Emoji } from '@/models/entities/emoji'; +import { UserList } from '@/models/entities/user-list'; +import { MessagingMessage } from '@/models/entities/messaging-message'; +import { PackedMessagingMessage } from '@/models/repositories/messaging-message'; +import { UserGroup } from '@/models/entities/user-group'; +import { PackedReversiGame } from '@/models/repositories/games/reversi/game'; +import { PackedReversiMatching } from '@/models/repositories/games/reversi/matching'; +import { ReversiGame } from '@/models/entities/games/reversi/game'; +import { AbuseUserReport } from '@/models/entities/abuse-user-report'; +import { PackedEmoji } from '@/models/repositories/emoji'; +import StreamTypes from 'misskey-js/built/streaming.types'; // 辞書(interface or type)から{ type, body }ユニオンを定義 // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type @@ -25,12 +34,6 @@ type EventUnionFromDictionary< // (payload: P) => void からPを取り出す type Payload void> = T extends (payload: infer P) => void ? P : never; -// misskey.jsのstreaming.typesの辞書から{ type, body }ユニオンを定義 -type EventUnionFromMkJSTypes< - T extends { [key: string]: ((payload: any) => void) | (() => void) }, - U = { [K in keyof T]: { type: K; body: Payload} } -> = U[keyof U]; - //#region Stream type-body definitions export interface InternalStreamTypes { antennaCreated: Antenna; @@ -38,6 +41,10 @@ export interface InternalStreamTypes { antennaUpdated: Antenna; } +export interface BroadcastTypes { + emojiAdded: PackedEmoji; +}; + export interface UserStreamTypes { terminate: {}; followChannel: Channel; @@ -75,6 +82,7 @@ export interface MainStreamTypes { readAllChannels: never; unreadChannel: never; myTokenRegenerated: never; + reversiInvited: PackedReversiMatching; } export interface DriveStreamTypes { @@ -117,7 +125,92 @@ export interface NoteStreamTypes { }; } +export interface ChannelStreamTypes { + typing: User['id']; +} + +export interface UserListStreamTypes { + userAdded: PackedUser; + userRemoved: PackedUser; +} + +export interface AntennaStreamTypes { + note: Note; +} + +export interface MessagingStreamTypes { + read: MessagingMessage['id'][]; + typing: User['id']; + message: PackedMessagingMessage; + deleted: MessagingMessage['id']; +} + +export interface GroupMessagingStreamTypes { + read: { + ids: MessagingMessage['id'][]; + userId: User['id']; + }; + typing: User['id']; + message: PackedMessagingMessage; + deleted: MessagingMessage['id']; +} + +export interface MessagingIndexStreamTypes { + read: MessagingMessage['id'][]; + message: PackedMessagingMessage; +} + +export interface ReversiStreamTypes { + matched: PackedReversiGame; + invited: PackedReversiMatching; +} + +export interface ReversiGameStreamTypes { + started: PackedReversiGame; + ended: { + winnerId: User['id'], + game: PackedReversiGame; + }; + updateSettings: { + key: string; + value: FIXME; + }; + initForm: { + userId: User['id']; + form: FIXME; + }; + updateForm: { + userId: User['id']; + id: string; + value: FIXME; + }; + message: { + userId: User['id']; + message: FIXME; + }; + changeAccepts: { + user1: boolean; + user2: boolean; + }; + set: { + at: Date; + color: boolean; + pos: number; + next: boolean; + }; + watching: User['id']; +} + +export interface AdminStreamTypes { + newAbuseUserReport: { + id: AbuseUserReport['id']; + targetUserId: User['id'], + reporterId: User['id'], + comment: string; + } +} //#endregion + //#region 名前とメッセージのペアを中間生成 interface StreamMessages { internal: { @@ -126,7 +219,7 @@ interface StreamMessages { }; broadcast: { name: 'broadcast'; - spec: EventUnionFromMkJSTypes; + spec: EventUnionFromDictionary; }; user: { name: `user:${User['id']}`; @@ -143,11 +236,52 @@ interface StreamMessages { note: { name: `noteStream:${Note['id']}`; spec: EventUnionFromDictionary; + }; + channel: { + name: `channelStream:${Channel['id']}`; + spec: EventUnionFromDictionary; + }; + userList: { + name: `userListStream:${UserList['id']}`; + spec: EventUnionFromDictionary; + }; + antenna: { + name: `antennaStream:${Antenna['id']}`; + spec: EventUnionFromDictionary; + }; + messaging: { + name: `messagingStream:${User['id']}-${User['id']}`; + spec: EventUnionFromDictionary; + }; + groupMessaging: { + name: `messagingStream:${UserGroup['id']}`; + spec: EventUnionFromDictionary; + }; + messagingIndex: { + name: `messagingIndexStream:${User['id']}`; + spec: EventUnionFromDictionary; + }; + reversi: { + name: `reversiStream:${User['id']}`; + spec: EventUnionFromDictionary; + }; + reversiGame: { + name: `reversiGameStream:${ReversiGame['id']}`; + spec: EventUnionFromDictionary; + }; + admin: { + name: `adminStream:${User['id']}`; + spec: EventUnionFromDictionary; } + // and notesStream (specにPackedNoteを突っ込むとなぜかバグる) } - //#endregion // API event definitions type EventsGenerater = { [key in StreamMessages[K]['name']]: (e: StreamMessages[K]['spec']) => void }; -export type StreamEventEmitter = Emitter>; +type NotesStreamEvent = { notesStream: (e: PackedNote) => void }; +export type StreamEventEmitter = Emitter & NotesStreamEvent>; + +// Channel Union +type ChannelsUnionGenerater = StreamMessages[K]['name']; +export type Channels = ChannelsUnionGenerater | 'notesStream'; diff --git a/src/services/stream.ts b/src/services/stream.ts index 4db1a77395..20c019f57d 100644 --- a/src/services/stream.ts +++ b/src/services/stream.ts @@ -7,9 +7,10 @@ import { UserGroup } from '@/models/entities/user-group'; import config from '@/config/index'; import { Antenna } from '@/models/entities/antenna'; import { Channel } from '@/models/entities/channel'; +import { BroadcastTypes, Channels, InternalStreamTypes, UserStreamTypes } from '@/server/api/stream/types'; class Publisher { - private publish = (channel: string, type: string | null, value?: any): void => { + private publish = (channel: Channels, type: string | null, value?: any): void => { const message = type == null ? value : value == null ? { type: type, body: null } : { type: type, body: value }; @@ -20,15 +21,15 @@ class Publisher { })); } - public publishInternalEvent = (type: string, value?: any): void => { + public publishInternalEvent = (type: K, value: InternalStreamTypes[K]): void => { this.publish('internal', type, typeof value === 'undefined' ? null : value); } - public publishUserEvent = (userId: User['id'], type: string, value?: any): void => { + public publishUserEvent = (userId: User['id'], type: K, value: UserStreamTypes[K]): void => { this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishBroadcastStream = (type: string, value?: any): void => { + public publishBroadcastStream = (type: K, value: BroadcastTypes[K]): void => { this.publish('broadcast', type, typeof value === 'undefined' ? null : value); }