リファクタリングなど

This commit is contained in:
syuilo 2018-08-11 10:42:06 +09:00
parent 569036db73
commit 986fe39762
8 changed files with 303 additions and 228 deletions

10
.editorconfig Normal file
View File

@ -0,0 +1,10 @@
root = true
[*]
indent_style = tab
indent_size = 2
charset = utf-8
insert_final_newline = true
[*.yml]
indent_style = space

15
src/config.ts Normal file
View File

@ -0,0 +1,15 @@
type Config = {
host: string;
i: string;
id: string;
wsUrl: string;
apiUrl: string;
reversiEnabled: boolean;
};
const config = require('../config.json');
config.wsUrl = config.host.replace('http', 'ws');
config.apiUrl = config.host + '/api';
export default config as Config;

View File

@ -1,70 +1,28 @@
import * as childProcess from 'child_process';
import * as WebSocket from 'ws';
import * as request from 'request-promise-native';
const ReconnectingWebSocket = require('../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js');
import serifs from './serifs';
const config = require('../config.json');
import config from './config';
import IModule from './module';
import MessageLike from './message-like';
const wsUrl = config.host.replace('http', 'ws');
const apiUrl = config.host + '/api';
class MessageLike {
private ai: ;
private messageOrNote: any;
public isMessage: boolean;
public get id() {
return this.messageOrNote.id;
}
public get userId() {
return this.messageOrNote.userId;
}
public get text() {
return this.messageOrNote.text;
}
constructor(ai: , messageOrNote: any, isMessage: boolean) {
this.ai = ai;
this.messageOrNote = messageOrNote;
this.isMessage = isMessage;
}
public reply = (text: string) => {
setTimeout(() => {
if (this.isMessage) {
this.ai.sendMessage(this.messageOrNote.userId, {
text: text
});
} else {
this.ai.post({
replyId: this.messageOrNote.id,
text: text
});
}
}, 2000);
}
}
import ReversiModule from './modules/reversi';
/**
*
*/
class {
export default class {
/**
*
*/
private connection: any;
/**
*
*/
private reversiConnection?: any;
private modules: IModule[] = [];
constructor() {
this.connection = new ReconnectingWebSocket(`${wsUrl}/?i=${config.i}`, [], {
this.connection = new ReconnectingWebSocket(`${config.wsUrl}/?i=${config.i}`, [], {
WebSocket: WebSocket
});
@ -83,26 +41,13 @@ class 藍 {
});
if (config.reversiEnabled) {
this.reversiConnection = new ReconnectingWebSocket(`${wsUrl}/games/reversi?i=${config.i}`, [], {
WebSocket: WebSocket
});
this.reversiConnection.addEventListener('open', () => {
console.log('reversi stream opened');
});
this.reversiConnection.addEventListener('close', () => {
console.log('reversi stream closed');
});
this.reversiConnection.addEventListener('message', message => {
const msg = JSON.parse(message.data);
this.onReversiConnectionMessage(msg);
});
}
}
public install = (module: IModule) => {
this.modules.push(module);
}
private onMessage = (msg: any) => {
switch (msg.type) {
// メンションされたとき
@ -131,189 +76,51 @@ class 藍 {
}
}
private onReversiConnectionMessage = (msg: any) => {
switch (msg.type) {
// 招待されたとき
case 'invited': {
this.onReversiInviteMe(msg.body.parent);
break;
}
// マッチしたとき
case 'matched': {
this.onReversiGameStart(msg.body);
break;
}
default:
break;
}
}
private onReversiInviteMe = async (inviter: any) => {
console.log(`Someone invited me: @${inviter.username}`);
if (config.reversiEnabled) {
// 承認
const game = await request.post(`${apiUrl}/games/reversi/match`, {
json: {
i: config.i,
userId: inviter.id
}
});
this.onReversiGameStart(game);
} else {
// todo (リバーシできない旨をメッセージで伝えるなど)
}
}
private onReversiGameStart = (game: any) => {
// ゲームストリームに接続
const gw = new ReconnectingWebSocket(`${wsUrl}/games/reversi-game?i=${config.i}&game=${game.id}`, [], {
WebSocket: WebSocket
});
function send(msg) {
try {
gw.send(JSON.stringify(msg));
} catch (e) {
console.error(e);
}
}
gw.addEventListener('open', () => {
console.log('reversi game stream opened');
// フォーム
const form = [{
id: 'publish',
type: 'switch',
label: '藍が対局情報を投稿するのを許可',
value: true
}, {
id: 'strength',
type: 'radio',
label: '強さ',
value: 3,
items: [{
label: '接待',
value: 0
}, {
label: '弱',
value: 2
}, {
label: '中',
value: 3
}, {
label: '強',
value: 4
}, {
label: '最強',
value: 5
}]
}];
//#region バックエンドプロセス開始
const ai = childProcess.fork(__dirname + '/back.js');
// バックエンドプロセスに情報を渡す
ai.send({
type: '_init_',
game,
form
});
ai.on('message', msg => {
if (msg.type == 'put') {
send({
type: 'set',
pos: msg.pos
});
} else if (msg.type == 'close') {
gw.close();
}
});
// ゲームストリームから情報が流れてきたらそのままバックエンドプロセスに伝える
gw.addEventListener('message', message => {
const msg = JSON.parse(message.data);
ai.send(msg);
});
//#endregion
// フォーム初期化
setTimeout(() => {
send({
type: 'init-form',
body: form
});
}, 1000);
// どんな設定内容の対局でも受け入れる
setTimeout(() => {
send({
type: 'accept'
});
}, 2000);
});
gw.addEventListener('close', () => {
console.log('reversi game stream closed');
});
}
private onMention = (x: MessageLike) => {
private onMention = (msg: MessageLike) => {
// リアクションする
if (!x.isMessage) {
if (!msg.isMessage) {
setTimeout(() => {
request.post(`${apiUrl}/notes/reactions/create`, {
request.post(`${config.apiUrl}/notes/reactions/create`, {
json: {
i: config.i,
noteId: x.id,
noteId: msg.id,
reaction: 'love'
}
});
}, 1000);
}
if (x.text && x.text.indexOf('リバーシ') > -1) {
if (config.reversiEnabled) {
x.reply(serifs.REVERSI_OK);
request.post(`${apiUrl}/games/reversi/match`, {
json: {
i: config.i,
userId: x.userId
}
});
} else {
x.reply(serifs.REVERSI_DECLINE);
}
}
this.modules.filter(m => m.hasOwnProperty('onMention')).some(m => {
return m.onMention(msg);
});
}
public post = (param: any) => {
setTimeout(() => {
request.post(`${apiUrl}/notes/create`, {
json: Object.assign({
i: config.i
}, param)
});
request.post('notes/create', param);
}, 2000);
}
public sendMessage = (userId: any, param: any) => {
setTimeout(() => {
request.post(`${apiUrl}/messaging/messages/create`, {
json: Object.assign({
i: config.i,
userId: userId,
}, param)
});
this.api('messages/create', Object.assign({
userId: userId,
}, param));
}, 2000);
}
public api = (endpoint: string, param) => {
return request.post(`${config.apiUrl}/${endpoint}`, {
json: Object.assign({
i: config.i
}, param)
});
};
}
const ai = new ();
if (config.reversiEnabled) {
const reversiModule = new ReversiModule();
ai.install(reversiModule);
}

40
src/message-like.ts Normal file
View File

@ -0,0 +1,40 @@
import from '.';
export default class MessageLike {
private ai: ;
private messageOrNote: any;
public isMessage: boolean;
public get id() {
return this.messageOrNote.id;
}
public get userId() {
return this.messageOrNote.userId;
}
public get text() {
return this.messageOrNote.text;
}
constructor(ai: , messageOrNote: any, isMessage: boolean) {
this.ai = ai;
this.messageOrNote = messageOrNote;
this.isMessage = isMessage;
}
public reply = (text: string) => {
setTimeout(() => {
if (this.isMessage) {
this.ai.sendMessage(this.messageOrNote.userId, {
text: text
});
} else {
this.ai.post({
replyId: this.messageOrNote.id,
text: text
});
}
}, 2000);
}
}

7
src/module.ts Normal file
View File

@ -0,0 +1,7 @@
import from '.';
import MessageLike from './message-like';
export default interface IModule {
install?: (ai: ) => void;
onMention?: (msg: MessageLike) => boolean;
}

View File

@ -0,0 +1,189 @@
import * as childProcess from 'child_process';
const ReconnectingWebSocket = require('../../../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js');
import from '../..';
import IModule from '../../module';
import serifs from '../../serifs';
import config from '../../config';
import MessageLike from '../../message-like';
export default class ReversiModule implements IModule {
private ai: ;
/**
*
*/
private reversiConnection?: any;
public install = (ai: ) => {
this.ai = ai;
this.reversiConnection = new ReconnectingWebSocket(`${config.wsUrl}/games/reversi?i=${config.i}`, [], {
WebSocket: WebSocket
});
this.reversiConnection.addEventListener('open', () => {
console.log('reversi stream opened');
});
this.reversiConnection.addEventListener('close', () => {
console.log('reversi stream closed');
});
this.reversiConnection.addEventListener('message', message => {
const msg = JSON.parse(message.data);
this.onReversiConnectionMessage(msg);
});
}
public onMention = (msg: MessageLike) => {
if (msg.text && msg.text.indexOf('リバーシ') > -1) {
if (config.reversiEnabled) {
msg.reply(serifs.REVERSI_OK);
this.ai.api('games/reversi/match', {
userId: msg.userId
});
} else {
msg.reply(serifs.REVERSI_DECLINE);
}
return true;
} else {
return false;
}
}
private onReversiConnectionMessage = (msg: any) => {
switch (msg.type) {
// 招待されたとき
case 'invited': {
this.onReversiInviteMe(msg.body.parent);
break;
}
// マッチしたとき
case 'matched': {
this.onReversiGameStart(msg.body);
break;
}
default:
break;
}
}
private onReversiInviteMe = async (inviter: any) => {
console.log(`Someone invited me: @${inviter.username}`);
if (config.reversiEnabled) {
// 承認
const game = await this.ai.api('games/reversi/match', {
userId: inviter.id
});
this.onReversiGameStart(game);
} else {
// todo (リバーシできない旨をメッセージで伝えるなど)
}
}
private onReversiGameStart = (game: any) => {
// ゲームストリームに接続
const gw = new ReconnectingWebSocket(`${config.wsUrl}/games/reversi-game?i=${config.i}&game=${game.id}`, [], {
WebSocket: WebSocket
});
function send(msg) {
try {
gw.send(JSON.stringify(msg));
} catch (e) {
console.error(e);
}
}
gw.addEventListener('open', () => {
console.log('reversi game stream opened');
// フォーム
const form = [{
id: 'publish',
type: 'switch',
label: '藍が対局情報を投稿するのを許可',
value: true
}, {
id: 'strength',
type: 'radio',
label: '強さ',
value: 3,
items: [{
label: '接待',
value: 0
}, {
label: '弱',
value: 2
}, {
label: '中',
value: 3
}, {
label: '強',
value: 4
}, {
label: '最強',
value: 5
}]
}];
//#region バックエンドプロセス開始
const ai = childProcess.fork(__dirname + '/back.js');
// バックエンドプロセスに情報を渡す
ai.send({
type: '_init_',
game,
form
});
ai.on('message', msg => {
if (msg.type == 'put') {
send({
type: 'set',
pos: msg.pos
});
} else if (msg.type == 'close') {
gw.close();
}
});
// ゲームストリームから情報が流れてきたらそのままバックエンドプロセスに伝える
gw.addEventListener('message', message => {
const msg = JSON.parse(message.data);
ai.send(msg);
});
//#endregion
// フォーム初期化
setTimeout(() => {
send({
type: 'init-form',
body: form
});
}, 1000);
// どんな設定内容の対局でも受け入れる
setTimeout(() => {
send({
type: 'accept'
});
}, 2000);
});
gw.addEventListener('close', () => {
console.log('reversi game stream closed');
});
}
}

View File

@ -1,4 +1,11 @@
export default {
/**
*
*/
REVERSI_OK: '良いですよ~',
/**
*
*/
REVERSI_DECLINE: 'ごめんなさい、今リバーシはするなと言われてます...'
};