wip
This commit is contained in:
@@ -233,6 +233,26 @@ const endpoints: Endpoint[] = [
|
||||
kind: 'notification-read'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'othello/match',
|
||||
withCredential: true
|
||||
},
|
||||
|
||||
{
|
||||
name: 'othello/match/cancel',
|
||||
withCredential: true
|
||||
},
|
||||
|
||||
{
|
||||
name: 'othello/invitations',
|
||||
withCredential: true
|
||||
},
|
||||
|
||||
{
|
||||
name: 'othello/games',
|
||||
withCredential: true
|
||||
},
|
||||
|
||||
{
|
||||
name: 'mute/create',
|
||||
withCredential: true,
|
||||
|
22
src/api/endpoints/othello/games.ts
Normal file
22
src/api/endpoints/othello/games.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import $ from 'cafy';
|
||||
import Game, { pack } from '../../models/othello-game';
|
||||
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
// Get 'my' parameter
|
||||
const [my = false, myErr] = $(params.my).boolean().$;
|
||||
if (myErr) return rej('invalid my param');
|
||||
|
||||
const q = my ? {
|
||||
$or: [{
|
||||
black_user_id: user._id
|
||||
}, {
|
||||
white_user_id: user._id
|
||||
}]
|
||||
} : {};
|
||||
|
||||
// Fetch games
|
||||
const games = await Game.find(q);
|
||||
|
||||
// Reponse
|
||||
res(Promise.all(games.map(async (g) => await pack(g, user))));
|
||||
});
|
11
src/api/endpoints/othello/invitations.ts
Normal file
11
src/api/endpoints/othello/invitations.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import Matching, { pack as packMatching } from '../../models/othello-matching';
|
||||
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
// Find session
|
||||
const invitations = await Matching.find({
|
||||
child_id: user._id
|
||||
});
|
||||
|
||||
// Reponse
|
||||
res(Promise.all(invitations.map(async (i) => await packMatching(i, user))));
|
||||
});
|
@@ -1,6 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import Matching from '../../models/othello-matchig';
|
||||
import Game, { pack } from '../../models/othello-game';
|
||||
import Matching, { pack as packMatching } from '../../models/othello-matching';
|
||||
import Game, { pack as packGame } from '../../models/othello-game';
|
||||
import User from '../../models/user';
|
||||
import { publishOthelloStream } from '../../event';
|
||||
|
||||
@@ -33,17 +33,14 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
created_at: new Date(),
|
||||
black_user_id: parentIsBlack ? exist.parent_id : user._id,
|
||||
white_user_id: parentIsBlack ? user._id : exist.parent_id,
|
||||
turn_user_id: parentIsBlack ? exist.parent_id : user._id,
|
||||
logs: []
|
||||
});
|
||||
|
||||
const packedGame = await pack(game);
|
||||
|
||||
// Reponse
|
||||
res(packedGame);
|
||||
res(await packGame(game, user));
|
||||
|
||||
publishOthelloStream(exist.parent_id, 'matched', {
|
||||
game
|
||||
});
|
||||
publishOthelloStream(exist.parent_id, 'matched', await packGame(game, exist.parent_id));
|
||||
} else {
|
||||
// Fetch child
|
||||
const child = await User.findOne({
|
||||
@@ -64,17 +61,16 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
});
|
||||
|
||||
// セッションを作成
|
||||
await Matching.insert({
|
||||
const matching = await Matching.insert({
|
||||
created_at: new Date(),
|
||||
parent_id: user._id,
|
||||
child_id: child._id
|
||||
});
|
||||
|
||||
// Reponse
|
||||
res(204);
|
||||
res();
|
||||
|
||||
// 招待
|
||||
publishOthelloStream(child._id, 'invited', {
|
||||
user_id: user._id
|
||||
});
|
||||
publishOthelloStream(child._id, 'invited', await packMatching(matching, child));
|
||||
}
|
||||
});
|
||||
|
9
src/api/endpoints/othello/match/cancel.ts
Normal file
9
src/api/endpoints/othello/match/cancel.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import Matching from '../../../models/othello-matching';
|
||||
|
||||
module.exports = (params, user) => new Promise(async (res, rej) => {
|
||||
await Matching.remove({
|
||||
parent_id: user._id
|
||||
});
|
||||
|
||||
res();
|
||||
});
|
@@ -42,6 +42,10 @@ class MisskeyEvent {
|
||||
this.publish(`othello-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
|
||||
}
|
||||
|
||||
public publishOthelloGameStream(gameId: ID, type: string, value?: any): void {
|
||||
this.publish(`othello-game-stream:${gameId}`, type, typeof value === 'undefined' ? null : value);
|
||||
}
|
||||
|
||||
public publishChannelStream(channelId: ID, type: string, value?: any): void {
|
||||
this.publish(`channel-stream:${channelId}`, type, typeof value === 'undefined' ? null : value);
|
||||
}
|
||||
@@ -71,4 +75,6 @@ export const publishMessagingIndexStream = ev.publishMessagingIndexStream.bind(e
|
||||
|
||||
export const publishOthelloStream = ev.publishOthelloStream.bind(ev);
|
||||
|
||||
export const publishOthelloGameStream = ev.publishOthelloGameStream.bind(ev);
|
||||
|
||||
export const publishChannelStream = ev.publishChannelStream.bind(ev);
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import deepcopy = require('deepcopy');
|
||||
import db from '../../db/mongodb';
|
||||
import { IUser, pack as packUser } from './user';
|
||||
|
||||
const Game = db.get<IGame>('othello_games');
|
||||
export default Game;
|
||||
@@ -15,19 +16,30 @@ export interface IGame {
|
||||
|
||||
/**
|
||||
* Pack an othello game for API response
|
||||
*
|
||||
* @param {any} game
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
export const pack = (
|
||||
game: any
|
||||
game: any,
|
||||
me?: string | mongo.ObjectID | IUser
|
||||
) => new Promise<any>(async (resolve, reject) => {
|
||||
|
||||
// Me
|
||||
const meId: mongo.ObjectID = me
|
||||
? mongo.ObjectID.prototype.isPrototypeOf(me)
|
||||
? me as mongo.ObjectID
|
||||
: typeof me === 'string'
|
||||
? new mongo.ObjectID(me)
|
||||
: (me as IUser)._id
|
||||
: null;
|
||||
|
||||
const _game = deepcopy(game);
|
||||
|
||||
// Rename _id to id
|
||||
_game.id = _game._id;
|
||||
delete _game._id;
|
||||
|
||||
// Populate user
|
||||
_game.black_user = await packUser(_game.black_user_id, meId);
|
||||
_game.white_user = await packUser(_game.white_user_id, meId);
|
||||
|
||||
resolve(_game);
|
||||
});
|
||||
|
@@ -1,11 +1,42 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import deepcopy = require('deepcopy');
|
||||
import db from '../../db/mongodb';
|
||||
import { IUser, pack as packUser } from './user';
|
||||
|
||||
const Matching = db.get<IMatching>('othello_matchings');
|
||||
export default Matching;
|
||||
|
||||
export interface IMatching {
|
||||
_id: mongo.ObjectID;
|
||||
created_at: Date;
|
||||
parent_id: mongo.ObjectID;
|
||||
child_id: mongo.ObjectID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack an othello matching for API response
|
||||
*/
|
||||
export const pack = (
|
||||
matching: any,
|
||||
me?: string | mongo.ObjectID | IUser
|
||||
) => new Promise<any>(async (resolve, reject) => {
|
||||
|
||||
// Me
|
||||
const meId: mongo.ObjectID = me
|
||||
? mongo.ObjectID.prototype.isPrototypeOf(me)
|
||||
? me as mongo.ObjectID
|
||||
: typeof me === 'string'
|
||||
? new mongo.ObjectID(me)
|
||||
: (me as IUser)._id
|
||||
: null;
|
||||
|
||||
const _matching = deepcopy(matching);
|
||||
|
||||
delete _matching._id;
|
||||
|
||||
// Populate user
|
||||
_matching.parent = await packUser(_matching.parent_id, meId);
|
||||
_matching.child = await packUser(_matching.child_id, meId);
|
||||
|
||||
resolve(_matching);
|
||||
});
|
||||
|
@@ -1,12 +1,69 @@
|
||||
import * as websocket from 'websocket';
|
||||
import * as redis from 'redis';
|
||||
import Game from '../models/othello-game';
|
||||
import { publishOthelloGameStream } from '../event';
|
||||
import Othello from '../../common/othello';
|
||||
|
||||
export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient): void {
|
||||
const game = request.resourceURL.query.game;
|
||||
export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void {
|
||||
const gameId = request.resourceURL.query.game;
|
||||
|
||||
// Subscribe game stream
|
||||
subscriber.subscribe(`misskey:othello-game-stream:${game}`);
|
||||
subscriber.subscribe(`misskey:othello-game-stream:${gameId}`);
|
||||
subscriber.on('message', (_, data) => {
|
||||
connection.send(data);
|
||||
});
|
||||
|
||||
connection.on('message', async (data) => {
|
||||
const msg = JSON.parse(data.utf8Data);
|
||||
|
||||
switch (msg.type) {
|
||||
case 'set':
|
||||
if (msg.pos == null) return;
|
||||
const pos = msg.pos;
|
||||
|
||||
const game = await Game.findOne({ _id: gameId });
|
||||
|
||||
const o = new Othello();
|
||||
|
||||
game.logs.forEach(log => {
|
||||
o.set(log.color, log.pos);
|
||||
});
|
||||
|
||||
const myColor = game.black_user_id.equals(user._id) ? 'black' : 'white';
|
||||
const opColor = myColor == 'black' ? 'white' : 'black';
|
||||
|
||||
if (!o.canReverse(myColor, pos)) return;
|
||||
o.set(myColor, pos);
|
||||
|
||||
let turn;
|
||||
if (o.getPattern(opColor).length > 0) {
|
||||
turn = myColor == 'black' ? game.white_user_id : game.black_user_id;
|
||||
} else {
|
||||
turn = myColor == 'black' ? game.black_user_id : game.white_user_id;
|
||||
}
|
||||
|
||||
const log = {
|
||||
at: new Date(),
|
||||
color: myColor,
|
||||
pos
|
||||
};
|
||||
|
||||
await Game.update({
|
||||
_id: gameId
|
||||
}, {
|
||||
$set: {
|
||||
turn_user_id: turn
|
||||
},
|
||||
$push: {
|
||||
logs: log
|
||||
}
|
||||
});
|
||||
|
||||
publishOthelloGameStream(gameId, 'set', {
|
||||
color: myColor,
|
||||
pos
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -2,10 +2,8 @@ import * as websocket from 'websocket';
|
||||
import * as redis from 'redis';
|
||||
|
||||
export default function(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void {
|
||||
const otherparty = request.resourceURL.query.otherparty;
|
||||
|
||||
// Subscribe matching stream
|
||||
subscriber.subscribe(`misskey:othello-matching:${user._id}-${otherparty}`);
|
||||
// Subscribe othello stream
|
||||
subscriber.subscribe(`misskey:othello-stream:${user._id}`);
|
||||
subscriber.on('message', (_, data) => {
|
||||
connection.send(data);
|
||||
});
|
@@ -11,7 +11,7 @@ import driveStream from './stream/drive';
|
||||
import messagingStream from './stream/messaging';
|
||||
import messagingIndexStream from './stream/messaging-index';
|
||||
import othelloGameStream from './stream/othello-game';
|
||||
import othelloMatchingStream from './stream/othello-matching';
|
||||
import othelloStream from './stream/othello';
|
||||
import serverStream from './stream/server';
|
||||
import requestsStream from './stream/requests';
|
||||
import channelStream from './stream/channel';
|
||||
@@ -65,7 +65,7 @@ module.exports = (server: http.Server) => {
|
||||
request.resourceURL.pathname === '/messaging' ? messagingStream :
|
||||
request.resourceURL.pathname === '/messaging-index' ? messagingIndexStream :
|
||||
request.resourceURL.pathname === '/othello-game' ? othelloGameStream :
|
||||
request.resourceURL.pathname === '/othello-matching' ? othelloMatchingStream :
|
||||
request.resourceURL.pathname === '/othello' ? othelloStream :
|
||||
null;
|
||||
|
||||
if (channel !== null) {
|
||||
|
Reference in New Issue
Block a user