summaryrefslogtreecommitdiff
path: root/src/server/api/stream
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2020-11-03 22:02:55 +0900
committersyuilo <syuilotan@yahoo.co.jp>2020-11-03 22:02:55 +0900
commitf8ad303b139a08df9393fb84123a978582c51866 (patch)
treeeb1cc0db99a3b711834c18e7064626be51f92c3c /src/server/api/stream
parentRefactoring (diff)
downloadmisskey-f8ad303b139a08df9393fb84123a978582c51866.tar.gz
misskey-f8ad303b139a08df9393fb84123a978582c51866.tar.bz2
misskey-f8ad303b139a08df9393fb84123a978582c51866.zip
リバーシの観戦者を表示するように
Resolve #1830
Diffstat (limited to 'src/server/api/stream')
-rw-r--r--src/server/api/stream/channels/games/reversi-game.ts58
1 files changed, 56 insertions, 2 deletions
diff --git a/src/server/api/stream/channels/games/reversi-game.ts b/src/server/api/stream/channels/games/reversi-game.ts
index d03501971e..ea62ab1e88 100644
--- a/src/server/api/stream/channels/games/reversi-game.ts
+++ b/src/server/api/stream/channels/games/reversi-game.ts
@@ -5,7 +5,8 @@ import Reversi from '../../../../../games/reversi/core';
import * as maps from '../../../../../games/reversi/maps';
import Channel from '../../channel';
import { ReversiGame } from '../../../../../models/entities/games/reversi/game';
-import { ReversiGames } from '../../../../../models';
+import { ReversiGames, Users } from '../../../../../models';
+import { User } from '../../../../../models/entities/user';
export default class extends Channel {
public readonly chName = 'gamesReversiGame';
@@ -13,18 +14,59 @@ export default class extends Channel {
public static requireCredential = false;
private gameId: ReversiGame['id'] | null = null;
+ private watchers: Record<User['id'], Date> = {};
+ private emitWatchersIntervalId: any;
@autobind
public async init(params: any) {
this.gameId = params.gameId;
// Subscribe game stream
- this.subscriber.on(`reversiGameStream:${this.gameId}`, data => {
+ this.subscriber.on(`reversiGameStream:${this.gameId}`, this.onEvent);
+ this.emitWatchersIntervalId = setInterval(this.emitWatchers, 5000);
+
+ const game = await ReversiGames.findOne(this.gameId!);
+ if (game == null) throw new Error('game not found');
+
+ // 観戦者イベント
+ this.watch(game);
+ }
+
+ @autobind
+ private onEvent(data: any) {
+ if (data.type === 'watching') {
+ const id = data.body;
+ this.watchers[id] = new Date();
+ } else {
this.send(data);
+ }
+ }
+
+ @autobind
+ private async emitWatchers() {
+ const now = new Date();
+
+ // Remove not watching users
+ for (const [userId, date] of Object.entries(this.watchers)) {
+ if (now.getTime() - date.getTime() > 5000) delete this.watchers[userId];
+ }
+
+ const users = await Users.packMany(Object.keys(this.watchers), null, { detail: false });
+
+ this.send({
+ type: 'watchers',
+ body: users,
});
}
@autobind
+ public dispose() {
+ // Unsubscribe events
+ this.subscriber.off(`reversiGameStream:${this.gameId}`, this.onEvent);
+ clearInterval(this.emitWatchersIntervalId);
+ }
+
+ @autobind
public onMessage(type: string, body: any) {
switch (type) {
case 'accept': this.accept(true); break;
@@ -314,5 +356,17 @@ export default class extends Channel {
if (crc32.toString() !== game.crc32) {
this.send('rescue', await ReversiGames.pack(game, this.user));
}
+
+ // ついでに観戦者イベントを発行
+ this.watch(game);
+ }
+
+ @autobind
+ private watch(game: ReversiGame) {
+ if (this.user != null) {
+ if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) {
+ publishReversiGameStream(this.gameId!, 'watching', this.user.id);
+ }
+ }
}
}