From 36450d7fac926b3685a7c4de0d612daefb41c142 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Thu, 18 Jan 2024 16:02:24 +0900
Subject: [PATCH] wip

---
 packages/backend/src/core/ReversiService.ts   |  4 +-
 .../src/server/api/stream/ChannelsService.ts  |  6 ++
 .../src/server/api/stream/channels/reversi.ts | 82 +++++++++++++++++++
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts
index 8f9ac25fc3..c2b611ce5e 100644
--- a/packages/backend/src/core/ReversiService.ts
+++ b/packages/backend/src/core/ReversiService.ts
@@ -197,9 +197,9 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 				if (o.isEnded) {
 					let winner;
 					if (o.winner === true) {
-						winner = freshGame.black == 1 ? freshGame.user1Id : freshGame.user2Id;
+						winner = freshGame.black === 1 ? freshGame.user1Id : freshGame.user2Id;
 					} else if (o.winner === false) {
-						winner = freshGame.black == 1 ? freshGame.user2Id : freshGame.user1Id;
+						winner = freshGame.black === 1 ? freshGame.user2Id : freshGame.user1Id;
 					} else {
 						winner = null;
 					}
diff --git a/packages/backend/src/server/api/stream/ChannelsService.ts b/packages/backend/src/server/api/stream/ChannelsService.ts
index 3bc5380132..998429dd0a 100644
--- a/packages/backend/src/server/api/stream/ChannelsService.ts
+++ b/packages/backend/src/server/api/stream/ChannelsService.ts
@@ -19,6 +19,8 @@ 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 { ReversiChannelService } from './channels/reversi.js';
+import { ReversiGameChannelService } from './channels/reversi-game.js';
 import { type MiChannelService } from './channel.js';
 
 @Injectable()
@@ -38,6 +40,8 @@ export class ChannelsService {
 		private serverStatsChannelService: ServerStatsChannelService,
 		private queueStatsChannelService: QueueStatsChannelService,
 		private adminChannelService: AdminChannelService,
+		private reversiChannelService: ReversiChannelService,
+		private reversiGameChannelService: ReversiGameChannelService,
 	) {
 	}
 
@@ -58,6 +62,8 @@ export class ChannelsService {
 			case 'serverStats': return this.serverStatsChannelService;
 			case 'queueStats': return this.queueStatsChannelService;
 			case 'admin': return this.adminChannelService;
+			case 'reversi': return this.reversiChannelService;
+			case 'reversiGame': return this.reversiGameChannelService;
 
 			default:
 				throw new Error(`no such channel: ${name}`);
diff --git a/packages/backend/src/server/api/stream/channels/reversi.ts b/packages/backend/src/server/api/stream/channels/reversi.ts
index e69de29bb2..eea9ba17c8 100644
--- a/packages/backend/src/server/api/stream/channels/reversi.ts
+++ b/packages/backend/src/server/api/stream/channels/reversi.ts
@@ -0,0 +1,82 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import * as CRC32 from 'crc-32';
+import type { MiReversiGame, MiUser, ReversiGamesRepository } from '@/models/_.js';
+import type { Packed } from '@/misc/json-schema.js';
+import { DI } from '@/di-symbols.js';
+import { bindThis } from '@/decorators.js';
+import { ReversiService } from '@/core/ReversiService.js';
+import Channel, { type MiChannelService } from '../channel.js';
+
+class ReversiChannel extends Channel {
+	public readonly chName = 'reversi';
+	public static shouldShare = true;
+	public static requireCredential = true as const;
+	public static kind = 'read:account';
+
+	constructor(
+		private reversiService: ReversiService,
+		private reversiGamesRepository: ReversiGamesRepository,
+
+		id: string,
+		connection: Channel['connection'],
+	) {
+		super(id, connection);
+	}
+
+	@bindThis
+	public async init(params: any) {
+		this.subscriber.on(`reversiStream:${this.user.id}`, this.send);
+	}
+
+	@bindThis
+	public async async onMessage(type: string, body: any) {
+		switch (type) {
+			case 'ping': {
+				if (body.id == null) return;
+				const matching = await ReversiMatchings.findOne({
+					parentId: this.user!.id,
+					childId: body.id,
+				});
+				if (matching == null) return;
+				publishMainStream(matching.childId, 'reversiInvited', await ReversiMatchings.pack(matching, { id: matching.childId }));
+				break;
+			}
+		}
+	}
+
+	@bindThis
+	public dispose() {
+		// Unsubscribe events
+		this.subscriber.off(`reversiStream:${this.user.id}`, this.send);
+	}
+}
+
+@Injectable()
+export class ReversiChannelService implements MiChannelService<true> {
+	public readonly shouldShare = ReversiChannel.shouldShare;
+	public readonly requireCredential = ReversiChannel.requireCredential;
+	public readonly kind = ReversiChannel.kind;
+
+	constructor(
+		@Inject(DI.reversiGamesRepository)
+		private reversiGamesRepository: ReversiGamesRepository,
+
+		private reversiService: ReversiService,
+	) {
+	}
+
+	@bindThis
+	public create(id: string, connection: Channel['connection']): ReversiChannel {
+		return new ReversiChannel(
+			this.reversiService,
+			this.reversiGamesRepository,
+			id,
+			connection,
+		);
+	}
+}