diff --git a/locales/index.d.ts b/locales/index.d.ts index 0c6e73aac4..b9c2125ae6 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1174,10 +1174,6 @@ export interface Locale extends ILocale { * 保存しました */ "saved": string; - /** - * チャット - */ - "messaging": string; /** * アップロード */ @@ -8722,6 +8718,14 @@ export interface Locale extends ILocale { * 違反を報告する */ "write:report-abuse": string; + /** + * チャットを操作する + */ + "write:chat": string; + /** + * チャットを閲覧する + */ + "read:chat": string; }; "_auth": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 492d700f7d..d60425566e 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -289,7 +289,6 @@ deleteAreYouSure: "「{x}」を削除しますか?" resetAreYouSure: "リセットしますか?" areYouSure: "よろしいですか?" saved: "保存しました" -messaging: "チャット" upload: "アップロード" keepOriginalUploading: "オリジナル画像を保持" keepOriginalUploadingDescription: "画像をアップロードする時にオリジナル版を保持します。オフにするとアップロード時にブラウザでWeb公開用画像を生成します。" diff --git a/packages/backend/src/server/api/stream/ChannelsService.ts b/packages/backend/src/server/api/stream/ChannelsService.ts index 253409259f..9ec0a25171 100644 --- a/packages/backend/src/server/api/stream/ChannelsService.ts +++ b/packages/backend/src/server/api/stream/ChannelsService.ts @@ -19,6 +19,7 @@ import { AntennaChannelService } from './channels/antenna.js'; import { DriveChannelService } from './channels/drive.js'; import { HashtagChannelService } from './channels/hashtag.js'; import { RoleTimelineChannelService } from './channels/role-timeline.js'; +import { ChatChannelService } from './channels/chat.js'; import { ReversiChannelService } from './channels/reversi.js'; import { ReversiGameChannelService } from './channels/reversi-game.js'; import { type MiChannelService } from './channel.js'; @@ -40,6 +41,7 @@ export class ChannelsService { private serverStatsChannelService: ServerStatsChannelService, private queueStatsChannelService: QueueStatsChannelService, private adminChannelService: AdminChannelService, + private chatChannelService: ChatChannelService, private reversiChannelService: ReversiChannelService, private reversiGameChannelService: ReversiGameChannelService, ) { @@ -62,6 +64,7 @@ export class ChannelsService { case 'serverStats': return this.serverStatsChannelService; case 'queueStats': return this.queueStatsChannelService; case 'admin': return this.adminChannelService; + case 'chat': return this.chatChannelService; case 'reversi': return this.reversiChannelService; case 'reversiGame': return this.reversiGameChannelService; diff --git a/packages/backend/src/server/api/stream/channels/chat.ts b/packages/backend/src/server/api/stream/channels/chat.ts new file mode 100644 index 0000000000..de453323e1 --- /dev/null +++ b/packages/backend/src/server/api/stream/channels/chat.ts @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { bindThis } from '@/decorators.js'; +import type { GlobalEvents } from '@/core/GlobalEventService.js'; +import type { JsonObject } from '@/misc/json-value.js'; +import Channel, { type MiChannelService } from '../channel.js'; + +class ChatChannel extends Channel { + public readonly chName = 'chat'; + public static shouldShare = false; + public static requireCredential = true as const; + public static kind = 'read:chat'; + private otherId: string; + + constructor( + id: string, + connection: Channel['connection'], + ) { + super(id, connection); + } + + @bindThis + public async init(params: JsonObject) { + if (typeof params.otherId !== 'string') return; + this.otherId = params.otherId; + + this.subscriber.on(`chatStream:${this.user.id}-${this.otherId}`, this.onEvent); + } + + @bindThis + private async onEvent(data: GlobalEvents['chat']['payload']) { + this.send(data.type, data.body); + } + + @bindThis + public dispose() { + // Unsubscribe events + this.subscriber.off(`chatStream:${this.user.id}-${this.otherId}`, this.onEvent); + } +} + +@Injectable() +export class ChatChannelService implements MiChannelService { + public readonly shouldShare = ChatChannel.shouldShare; + public readonly requireCredential = ChatChannel.requireCredential; + public readonly kind = ChatChannel.kind; + + constructor( + ) { + } + + @bindThis + public create(id: string, connection: Channel['connection']): ChatChannel { + return new ChatChannel( + id, + connection, + ); + } +}