mirror of
https://github.com/syuilo/ai.git
synced 2024-11-09 23:48:01 +00:00
nanka iroiro
This commit is contained in:
parent
736693db5f
commit
cc335a6fde
|
@ -5,7 +5,6 @@ type Config = {
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
keywordEnabled: boolean;
|
keywordEnabled: boolean;
|
||||||
reversiEnabled: boolean;
|
reversiEnabled: boolean;
|
||||||
serverMonitoring: boolean;
|
|
||||||
mecab?: string;
|
mecab?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import 藍 from './ai';
|
import 藍 from './ai';
|
||||||
import IModule from './module';
|
import IModule from './module';
|
||||||
|
import getDate from './utils/get-date';
|
||||||
|
import { User } from './misskey/user';
|
||||||
|
|
||||||
export type FriendDoc = {
|
export type FriendDoc = {
|
||||||
userId: string;
|
userId: string;
|
||||||
user: any;
|
user: User;
|
||||||
name?: string;
|
name?: string;
|
||||||
love?: number;
|
love?: number;
|
||||||
lastLoveIncrementedAt?: string;
|
lastLoveIncrementedAt?: string;
|
||||||
|
@ -50,7 +52,7 @@ export default class Friend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateUser = (user: any) => {
|
public updateUser = (user: User) => {
|
||||||
this.doc.user = user;
|
this.doc.user = user;
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
@ -79,11 +81,7 @@ export default class Friend {
|
||||||
}
|
}
|
||||||
|
|
||||||
public incLove = () => {
|
public incLove = () => {
|
||||||
const now = new Date();
|
const today = getDate();
|
||||||
const y = now.getFullYear();
|
|
||||||
const m = now.getMonth();
|
|
||||||
const d = now.getDate();
|
|
||||||
const today = `${y}/${m + 1}/${d}`;
|
|
||||||
|
|
||||||
if (this.doc.lastLoveIncrementedAt != today) {
|
if (this.doc.lastLoveIncrementedAt != today) {
|
||||||
this.doc.todayLoveIncrements = 0;
|
this.doc.todayLoveIncrements = 0;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import config from './config';
|
||||||
|
|
||||||
import CoreModule from './modules/core';
|
import CoreModule from './modules/core';
|
||||||
import ReversiModule from './modules/reversi';
|
import ReversiModule from './modules/reversi';
|
||||||
import ServerModule from './modules/server';
|
|
||||||
import PingModule from './modules/ping';
|
import PingModule from './modules/ping';
|
||||||
import EmojiModule from './modules/emoji';
|
import EmojiModule from './modules/emoji';
|
||||||
import FortuneModule from './modules/fortune';
|
import FortuneModule from './modules/fortune';
|
||||||
|
@ -36,7 +35,6 @@ promiseRetry(retry => {
|
||||||
ai.install(new GuessingGameModule());
|
ai.install(new GuessingGameModule());
|
||||||
ai.install(new ReversiModule());
|
ai.install(new ReversiModule());
|
||||||
ai.install(new TimerModule());
|
ai.install(new TimerModule());
|
||||||
if (config.serverMonitoring) ai.install(new ServerModule());
|
|
||||||
if (config.keywordEnabled) ai.install(new KeywordModule());
|
if (config.keywordEnabled) ai.install(new KeywordModule());
|
||||||
|
|
||||||
console.log('--- ai started! ---');
|
console.log('--- ai started! ---');
|
||||||
|
|
5
src/misskey/user.ts
Normal file
5
src/misskey/user.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export type User = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
username: string;
|
||||||
|
};
|
|
@ -4,6 +4,7 @@ import IModule from '../../module';
|
||||||
import MessageLike from '../../message-like';
|
import MessageLike from '../../message-like';
|
||||||
import serifs from '../../serifs';
|
import serifs from '../../serifs';
|
||||||
import Friend from '../../friend';
|
import Friend from '../../friend';
|
||||||
|
import getDate from '../../utils/get-date';
|
||||||
|
|
||||||
function zeroPadding(num: number, length: number): string {
|
function zeroPadding(num: number, length: number): string {
|
||||||
return ('0000000000' + num).slice(-length);
|
return ('0000000000' + num).slice(-length);
|
||||||
|
@ -76,12 +77,9 @@ export default class CoreModule implements IModule {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const withSan =
|
const titles = ['さん', 'くん', '君', 'ちゃん', '様', '先生'];
|
||||||
name.endsWith('さん') ||
|
|
||||||
name.endsWith('くん') ||
|
const withSan = titles.some(t => name.endsWith(t));
|
||||||
name.endsWith('君') ||
|
|
||||||
name.endsWith('ちゃん') ||
|
|
||||||
name.endsWith('様');
|
|
||||||
|
|
||||||
if (withSan) {
|
if (withSan) {
|
||||||
msg.friend.updateName(name);
|
msg.friend.updateName(name);
|
||||||
|
@ -101,11 +99,7 @@ export default class CoreModule implements IModule {
|
||||||
if (!msg.text) return false;
|
if (!msg.text) return false;
|
||||||
|
|
||||||
const incLove = () => {
|
const incLove = () => {
|
||||||
const now = new Date();
|
const today = getDate();
|
||||||
const y = now.getFullYear();
|
|
||||||
const m = now.getMonth();
|
|
||||||
const d = now.getDate();
|
|
||||||
const today = `${y}/${m + 1}/${d}`;
|
|
||||||
|
|
||||||
const data = msg.friend.getPerModulesData(this);
|
const data = msg.friend.getPerModulesData(this);
|
||||||
|
|
||||||
|
@ -146,6 +140,7 @@ export default class CoreModule implements IModule {
|
||||||
if (!msg.text) return false;
|
if (!msg.text) return false;
|
||||||
if (!msg.text.includes('なでなで')) return false;
|
if (!msg.text.includes('なでなで')) return false;
|
||||||
|
|
||||||
|
//#region 1日に1回だけ親愛度を上げる
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const y = now.getFullYear();
|
const y = now.getFullYear();
|
||||||
const m = now.getMonth();
|
const m = now.getMonth();
|
||||||
|
@ -160,6 +155,7 @@ export default class CoreModule implements IModule {
|
||||||
|
|
||||||
msg.friend.incLove();
|
msg.friend.incLove();
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
msg.reply(
|
msg.reply(
|
||||||
msg.friend.love >= 5 ? serifs.core.nadenade2 :
|
msg.friend.love >= 5 ? serifs.core.nadenade2 :
|
||||||
|
|
|
@ -128,7 +128,7 @@ export default class EmojiModule implements IModule {
|
||||||
const hand = hands[Math.floor(Math.random() * hands.length)];
|
const hand = hands[Math.floor(Math.random() * hands.length)];
|
||||||
const face = faces[Math.floor(Math.random() * faces.length)];
|
const face = faces[Math.floor(Math.random() * faces.length)];
|
||||||
const emoji = Array.isArray(hand) ? hand[0] + face + hand[1] : hand + face + hand;
|
const emoji = Array.isArray(hand) ? hand[0] + face + hand[1] : hand + face + hand;
|
||||||
msg.reply(serifs.EMOJI_SUGGEST.replace('$', emoji));
|
msg.reply(serifs.emoji.suggest.replace('$', emoji));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default class FortuneModule implements IModule {
|
||||||
const rng = seedrandom(seed);
|
const rng = seedrandom(seed);
|
||||||
const omikuji = omikujis[Math.floor(rng() * omikujis.length)];
|
const omikuji = omikujis[Math.floor(rng() * omikujis.length)];
|
||||||
const item = items[Math.floor(rng() * items.length)];
|
const item = items[Math.floor(rng() * items.length)];
|
||||||
msg.reply(`**${omikuji}🎉**\nラッキーアイテム: ${item}`, serifs.FORTUNE_CW);
|
msg.reply(`**${omikuji}🎉**\nラッキーアイテム: ${item}`, serifs.fortune.cw);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -38,9 +38,9 @@ export default class GuessingGameModule implements IModule {
|
||||||
|
|
||||||
if (!msg.isMessage) {
|
if (!msg.isMessage) {
|
||||||
if (exist != null) {
|
if (exist != null) {
|
||||||
msg.reply(serifs.GUESSINGGAME_ARLEADY_STARTED);
|
msg.reply(serifs.guessingGame.arleadyStarted);
|
||||||
} else {
|
} else {
|
||||||
msg.reply(serifs.GUESSINGGAME_PLZ_DM);
|
msg.reply(serifs.guessingGame.plzDm);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -57,7 +57,7 @@ export default class GuessingGameModule implements IModule {
|
||||||
endedAt: null
|
endedAt: null
|
||||||
});
|
});
|
||||||
|
|
||||||
msg.reply(serifs.GUESSINGGAME_STARTED).then(reply => {
|
msg.reply(serifs.guessingGame.started).then(reply => {
|
||||||
this.ai.subscribeReply(this, msg.userId, msg.isMessage, msg.isMessage ? msg.userId : reply.id);
|
this.ai.subscribeReply(this, msg.userId, msg.isMessage, msg.isMessage ? msg.userId : reply.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ export default class GuessingGameModule implements IModule {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (msg.text.includes('やめ')) {
|
if (msg.text.includes('やめ')) {
|
||||||
msg.reply(serifs.GUESSINGGAME_CANCEL);
|
msg.reply(serifs.guessingGame.cancel);
|
||||||
exist.isEnded = true;
|
exist.isEnded = true;
|
||||||
exist.endedAt = Date.now();
|
exist.endedAt = Date.now();
|
||||||
this.guesses.update(exist);
|
this.guesses.update(exist);
|
||||||
|
@ -87,7 +87,7 @@ export default class GuessingGameModule implements IModule {
|
||||||
const guess = msg.text.toLowerCase().replace(this.ai.account.username.toLowerCase(), '').match(/[0-9]+/);
|
const guess = msg.text.toLowerCase().replace(this.ai.account.username.toLowerCase(), '').match(/[0-9]+/);
|
||||||
|
|
||||||
if (guess == null) {
|
if (guess == null) {
|
||||||
msg.reply(serifs.GUESSINGGAME_NAN).then(reply => {
|
msg.reply(serifs.guessingGame.nan).then(reply => {
|
||||||
this.ai.subscribeReply(this, msg.userId, msg.isMessage, reply.id);
|
this.ai.subscribeReply(this, msg.userId, msg.isMessage, reply.id);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,15 +104,15 @@ export default class GuessingGameModule implements IModule {
|
||||||
|
|
||||||
if (exist.secret < g) {
|
if (exist.secret < g) {
|
||||||
text = firsttime
|
text = firsttime
|
||||||
? serifs.GUESSINGGAME_LESS.replace('$', g.toString())
|
? serifs.guessingGame.less.replace('$', g.toString())
|
||||||
: serifs.GUESSINGGAME_LESS_AGAIN.replace('$', g.toString());
|
: serifs.guessingGame.lessAgain.replace('$', g.toString());
|
||||||
} else if (exist.secret > g) {
|
} else if (exist.secret > g) {
|
||||||
text = firsttime
|
text = firsttime
|
||||||
? serifs.GUESSINGGAME_GRATER.replace('$', g.toString())
|
? serifs.guessingGame.grater.replace('$', g.toString())
|
||||||
: serifs.GUESSINGGAME_GRATER_AGAIN.replace('$', g.toString());
|
: serifs.guessingGame.graterAgain.replace('$', g.toString());
|
||||||
} else {
|
} else {
|
||||||
end = true;
|
end = true;
|
||||||
text = serifs.GUESSINGGAME_CONGRATS.replace('{tries}', exist.tries.length.toString());
|
text = serifs.guessingGame.congrats.replace('{tries}', exist.tries.length.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end) {
|
if (end) {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import * as request from 'request-promise-native';
|
import * as request from 'request-promise-native';
|
||||||
import Reversi, { Color } from 'misskey-reversi';
|
import Reversi, { Color } from 'misskey-reversi';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
|
import serifs from '../../serifs';
|
||||||
|
|
||||||
const db = {};
|
const db = {};
|
||||||
|
|
||||||
|
@ -208,36 +209,36 @@ class Session {
|
||||||
private onEnded = async (msg: any) => {
|
private onEnded = async (msg: any) => {
|
||||||
// ストリームから切断
|
// ストリームから切断
|
||||||
process.send({
|
process.send({
|
||||||
type: 'close'
|
type: 'ended'
|
||||||
});
|
});
|
||||||
|
|
||||||
let text: string;
|
let text: string;
|
||||||
|
|
||||||
if (msg.body.game.surrendered) {
|
if (msg.body.game.surrendered) {
|
||||||
if (this.isSettai) {
|
if (this.isSettai) {
|
||||||
text = `(${this.userName}を接待していたら投了されちゃいました... ごめんなさい)`;
|
text = serifs.reversi.settaiButYouSurrendered.replace('{name}', this.userName);
|
||||||
} else {
|
} else {
|
||||||
text = `${this.userName}が投了しちゃいました`;
|
text = serifs.reversi.youSurrendered.replace('{name}', this.userName);
|
||||||
}
|
}
|
||||||
} else if (msg.body.winnerId) {
|
} else if (msg.body.winnerId) {
|
||||||
if (msg.body.winnerId == this.account.id) {
|
if (msg.body.winnerId == this.account.id) {
|
||||||
if (this.isSettai) {
|
if (this.isSettai) {
|
||||||
text = `${this.userName}に接待で勝ってしまいました...`;
|
text = serifs.reversi.iWonButSettai.replace('{name}', this.userName);
|
||||||
} else {
|
} else {
|
||||||
text = `${this.userName}に勝ちました♪`;
|
text = serifs.reversi.iWon.replace('{name}', this.userName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.isSettai) {
|
if (this.isSettai) {
|
||||||
text = `(${this.userName}に接待で負けてあげました...♪)`;
|
text = serifs.reversi.iLoseButSettai.replace('{name}', this.userName);
|
||||||
} else {
|
} else {
|
||||||
text = `${this.userName}に負けました...`;
|
text = serifs.reversi.iLose.replace('{name}', this.userName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.isSettai) {
|
if (this.isSettai) {
|
||||||
text = `(${this.userName}に接待で引き分けました...)`;
|
text = serifs.reversi.drawnSettai.replace('{name}', this.userName);
|
||||||
} else {
|
} else {
|
||||||
text = `${this.userName}と引き分けました~`;
|
text = serifs.reversi.drawn.replace('{name}', this.userName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,8 +417,8 @@ class Session {
|
||||||
*/
|
*/
|
||||||
private postGameStarted = async () => {
|
private postGameStarted = async () => {
|
||||||
const text = this.isSettai
|
const text = this.isSettai
|
||||||
? `${this.userName}の接待を始めました!`
|
? serifs.reversi.startedSettai.replace('{name}', this.userName)
|
||||||
: `対局を${this.userName}と始めました! (強さ${this.strength})`;
|
: serifs.reversi.started.replace('{name}', this.userName).replace('{strength}', this.strength.toString());
|
||||||
|
|
||||||
return await this.post(`${text}\n→[観戦する](${this.url})`);
|
return await this.post(`${text}\n→[観戦する](${this.url})`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ import serifs from '../../serifs';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
import MessageLike from '../../message-like';
|
import MessageLike from '../../message-like';
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
|
import Friend from '../../friend';
|
||||||
|
import getDate from '../../utils/get-date';
|
||||||
|
import { User } from '../../misskey/user';
|
||||||
|
|
||||||
export default class ReversiModule implements IModule {
|
export default class ReversiModule implements IModule {
|
||||||
public name = 'reversi';
|
public name = 'reversi';
|
||||||
|
@ -44,13 +47,13 @@ export default class ReversiModule implements IModule {
|
||||||
public onMention = (msg: MessageLike) => {
|
public onMention = (msg: MessageLike) => {
|
||||||
if (msg.text && (msg.text.includes('リバーシ') || msg.text.includes('りばーし') || msg.text.includes('オセロ') || msg.text.includes('おせろ') || msg.text.toLowerCase().includes('reversi'))) {
|
if (msg.text && (msg.text.includes('リバーシ') || msg.text.includes('りばーし') || msg.text.includes('オセロ') || msg.text.includes('おせろ') || msg.text.toLowerCase().includes('reversi'))) {
|
||||||
if (config.reversiEnabled) {
|
if (config.reversiEnabled) {
|
||||||
msg.reply(serifs.REVERSI_OK);
|
msg.reply(serifs.reversi.ok);
|
||||||
|
|
||||||
this.ai.api('games/reversi/match', {
|
this.ai.api('games/reversi/match', {
|
||||||
userId: msg.userId
|
userId: msg.userId
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
msg.reply(serifs.REVERSI_DECLINE);
|
msg.reply(serifs.reversi.decline);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -157,8 +160,10 @@ export default class ReversiModule implements IModule {
|
||||||
type: 'set',
|
type: 'set',
|
||||||
pos: msg.pos
|
pos: msg.pos
|
||||||
});
|
});
|
||||||
} else if (msg.type == 'close') {
|
} else if (msg.type == 'ended') {
|
||||||
gw.close();
|
gw.close();
|
||||||
|
|
||||||
|
this.onGameEnded(game);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -189,4 +194,23 @@ export default class ReversiModule implements IModule {
|
||||||
console.log('reversi game stream closed');
|
console.log('reversi game stream closed');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onGameEnded(game: any) {
|
||||||
|
const user = game.user1Id == this.ai.account.id ? game.user2 : game.user1;
|
||||||
|
|
||||||
|
//#region 1日に1回だけ親愛度を上げる
|
||||||
|
const today = getDate();
|
||||||
|
|
||||||
|
const friend = new Friend(this.ai, { user: user });
|
||||||
|
|
||||||
|
const data = friend.getPerModulesData(this);
|
||||||
|
|
||||||
|
if (data.lastPlayedAt != today) {
|
||||||
|
data.lastPlayedAt = today;
|
||||||
|
friend.setPerModulesData(this, data);
|
||||||
|
|
||||||
|
friend.incLove();
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,162 +0,0 @@
|
||||||
import * as childProcess from 'child_process';
|
|
||||||
import * as WebSocket from 'ws';
|
|
||||||
import 藍 from '../../ai';
|
|
||||||
import IModule from '../../module';
|
|
||||||
import serifs from '../../serifs';
|
|
||||||
import config from '../../config';
|
|
||||||
import MessageLike from '../../message-like';
|
|
||||||
const ReconnectingWebSocket = require('../../../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs.js');
|
|
||||||
|
|
||||||
export default class ServerModule implements IModule {
|
|
||||||
public name = 'server';
|
|
||||||
|
|
||||||
private ai: 藍;
|
|
||||||
private connection?: any;
|
|
||||||
private preventScheduleReboot = false;
|
|
||||||
private rebootTimer: NodeJS.Timer;
|
|
||||||
private rebootTimerSub: NodeJS.Timer;
|
|
||||||
private recentStat: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1秒後とのログ1分間分
|
|
||||||
*/
|
|
||||||
private statsLogs: any[] = [];
|
|
||||||
|
|
||||||
public install = (ai: 藍) => {
|
|
||||||
this.ai = ai;
|
|
||||||
|
|
||||||
this.connection = new ReconnectingWebSocket(`${config.wsUrl}/server-stats`, [], {
|
|
||||||
WebSocket: WebSocket
|
|
||||||
});
|
|
||||||
|
|
||||||
this.connection.addEventListener('open', () => {
|
|
||||||
console.log('server-stats stream opened');
|
|
||||||
});
|
|
||||||
|
|
||||||
this.connection.addEventListener('close', () => {
|
|
||||||
console.log('server-stats stream closed');
|
|
||||||
});
|
|
||||||
|
|
||||||
this.connection.addEventListener('message', message => {
|
|
||||||
const msg = JSON.parse(message.data);
|
|
||||||
|
|
||||||
this.onConnectionMessage(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
this.statsLogs.unshift(this.recentStat);
|
|
||||||
if (this.statsLogs.length > 60) this.statsLogs.pop();
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
this.check();
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private check = () => {
|
|
||||||
const average = (arr) => arr.reduce((a, b) => a + b) / arr.length;
|
|
||||||
|
|
||||||
const memPercentages = this.statsLogs.map(s => (s.mem.used / s.mem.total) * 100);
|
|
||||||
const memPercentage = average(memPercentages);
|
|
||||||
if (memPercentage >= 90) {
|
|
||||||
this.scheduleReboot('mem');
|
|
||||||
}
|
|
||||||
|
|
||||||
const cpuPercentages = this.statsLogs.map(s => s.cpu_usage * 100);
|
|
||||||
const cpuPercentage = average(cpuPercentages);
|
|
||||||
if (cpuPercentage >= 70) {
|
|
||||||
this.scheduleReboot('cpu');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`CPU: ${cpuPercentage}% | MEM: ${memPercentage}%`);
|
|
||||||
}
|
|
||||||
|
|
||||||
private onConnectionMessage = (msg: any) => {
|
|
||||||
switch (msg.type) {
|
|
||||||
|
|
||||||
case 'stats': {
|
|
||||||
this.onStats(msg.body);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private onStats = async (stats: any) => {
|
|
||||||
this.recentStat = stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
private scheduleReboot = (reason: string) => {
|
|
||||||
if (this.preventScheduleReboot) return;
|
|
||||||
|
|
||||||
this.preventScheduleReboot = true;
|
|
||||||
|
|
||||||
this.ai.post({
|
|
||||||
text: reason == 'cpu' ? serifs.REBOOT_SCHEDULED_CPU : serifs.REBOOT_SCHEDULED_MEM
|
|
||||||
}).then(post => {
|
|
||||||
this.ai.subscribeReply(this, 'reboot', false, post.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.rebootTimer = setTimeout(() => {
|
|
||||||
childProcess.exec('forever restartall');
|
|
||||||
}, 1000 * 60);
|
|
||||||
|
|
||||||
this.rebootTimerSub = setTimeout(() => {
|
|
||||||
this.ai.post({
|
|
||||||
cw: serifs.REBOOT,
|
|
||||||
text: serifs.REBOOT_DETAIL
|
|
||||||
});
|
|
||||||
}, 1000 * 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
public onReplyThisModule = (msg: MessageLike) => {
|
|
||||||
if (msg.text == null) return;
|
|
||||||
|
|
||||||
if (msg.text.includes('やめ') || msg.text.includes('まって')) {
|
|
||||||
if (msg.user.isAdmin) {
|
|
||||||
msg.reply(serifs.REBOOT_CANCEL_REQUESTED_ACCEPT);
|
|
||||||
|
|
||||||
this.ai.post({
|
|
||||||
text: serifs.REBOOT_CANCELED
|
|
||||||
});
|
|
||||||
|
|
||||||
this.cancelReboot();
|
|
||||||
} else {
|
|
||||||
msg.reply(serifs.REBOOT_CANCEL_REQUESTED_REJECT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ai.unsubscribeReply(this, 'reboot');
|
|
||||||
}
|
|
||||||
|
|
||||||
public onMention = (msg: MessageLike) => {
|
|
||||||
if (msg.text && msg.text.includes('再起動しないで')) {
|
|
||||||
if (msg.user.isAdmin) {
|
|
||||||
msg.reply(serifs.REBOOT_CANCEL_REQUESTED_ACCEPT);
|
|
||||||
|
|
||||||
this.ai.post({
|
|
||||||
text: serifs.REBOOT_CANCELED
|
|
||||||
});
|
|
||||||
|
|
||||||
this.cancelReboot();
|
|
||||||
} else {
|
|
||||||
msg.reply(serifs.REBOOT_CANCEL_REQUESTED_REJECT);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private cancelReboot = () => {
|
|
||||||
clearTimeout(this.rebootTimer);
|
|
||||||
clearTimeout(this.rebootTimerSub);
|
|
||||||
|
|
||||||
// 10分間延期
|
|
||||||
setTimeout(() => {
|
|
||||||
this.preventScheduleReboot = false;
|
|
||||||
}, 1000 * 60 * 10);
|
|
||||||
}
|
|
||||||
}
|
|
185
src/serifs.ts
185
src/serifs.ts
|
@ -23,93 +23,142 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* リバーシへの誘いを承諾するとき
|
* リバーシ
|
||||||
*/
|
*/
|
||||||
REVERSI_OK: '良いですよ~',
|
reversi: {
|
||||||
|
/**
|
||||||
|
* リバーシへの誘いを承諾するとき
|
||||||
|
*/
|
||||||
|
ok: '良いですよ~',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* リバーシへの誘いを断るとき
|
||||||
|
*/
|
||||||
|
decline: 'ごめんなさい、今リバーシはするなと言われてます...',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 対局開始
|
||||||
|
*/
|
||||||
|
started: '対局を{name}と始めました! (強さ{strength})',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接待開始
|
||||||
|
*/
|
||||||
|
startedSettai: '({name}の接待を始めました)',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 勝ったとき
|
||||||
|
*/
|
||||||
|
iWon: '{name}に勝ちました♪',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接待のつもりが勝ってしまったとき
|
||||||
|
*/
|
||||||
|
iWonButSettai: '({name}に接待で勝ってしまいました...)',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 負けたとき
|
||||||
|
*/
|
||||||
|
iLose: '{name}に負けました...',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接待で負けてあげたとき
|
||||||
|
*/
|
||||||
|
iLoseButSettai: '({name}に接待で負けてあげました...♪)',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 引き分けたとき
|
||||||
|
*/
|
||||||
|
drawn: '{name}と引き分けました~',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接待で引き分けたとき
|
||||||
|
*/
|
||||||
|
drawnSettai: '({name}に接待で引き分けました...)',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 相手が投了したとき
|
||||||
|
*/
|
||||||
|
youSurrendered: '{name}が投了しちゃいました',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接待してたら相手が投了したとき
|
||||||
|
*/
|
||||||
|
settaiButYouSurrendered: '({name}を接待していたら投了されちゃいました... ごめんなさい)',
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* リバーシへの誘いを断るとき
|
* 数当てゲーム
|
||||||
*/
|
*/
|
||||||
REVERSI_DECLINE: 'ごめんなさい、今リバーシはするなと言われてます...',
|
guessingGame: {
|
||||||
|
/**
|
||||||
|
* やろうと言われたけど既にやっているとき
|
||||||
|
*/
|
||||||
|
arleadyStarted: 'え、ゲームは既に始まってますよ!',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (メモリが足りないので)再起動がスケジュールされたとき
|
* タイムライン上で誘われたとき
|
||||||
*/
|
*/
|
||||||
REBOOT_SCHEDULED_MEM: 'サーバーの空きメモリが少なくなってきたので、1分後にサーバー再起動しますね!',
|
plzDm: 'メッセージでやりましょう!',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (CPU使用率が高いので)再起動がスケジュールされたとき
|
* ゲーム開始
|
||||||
*/
|
*/
|
||||||
REBOOT_SCHEDULED_CPU: 'サーバーの負荷が高いので、1分後にサーバー再起動しますね!',
|
started: '0~100の秘密の数を当ててみてください♪',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* まもなく再起動されるとき
|
* 数字じゃない返信があったとき
|
||||||
*/
|
*/
|
||||||
REBOOT: 'では、まもなくサーバーを再起動します!',
|
nan: '数字でお願いします!「やめる」と言ってゲームをやめることもできますよ!',
|
||||||
REBOOT_DETAIL: '(私も再起動に巻き込まれちゃうので、サーバーの再起動が完了したことのお知らせはできません...)',
|
|
||||||
|
|
||||||
REBOOT_CANCEL_REQUESTED_ACCEPT: 'わかりました。再起動の予定を取り消しました!',
|
/**
|
||||||
REBOOT_CANCEL_REQUESTED_REJECT: 'ごめんなさい、再起動の取り消しは管理者のみが行えます...',
|
* 中止を要求されたとき
|
||||||
|
*/
|
||||||
|
cancel: 'わかりました~。ありがとうございました♪',
|
||||||
|
|
||||||
REBOOT_CANCELED: '再起動が取り消されました。お騒がせしました',
|
/**
|
||||||
|
* 小さい数を言われたとき
|
||||||
|
*/
|
||||||
|
grater: '$より大きいですね',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小さい数を言われたとき(2度目)
|
||||||
|
*/
|
||||||
|
graterAgain: 'もう一度言いますが$より大きいですよ!',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大きい数を言われたとき
|
||||||
|
*/
|
||||||
|
less: '$より小さいですね',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大きい数を言われたとき(2度目)
|
||||||
|
*/
|
||||||
|
lessAgain: 'もう一度言いますが$より小さいですよ!',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正解したとき
|
||||||
|
*/
|
||||||
|
congrats: '正解です🎉 ({tries}回目で当てました)',
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 絵文字生成
|
* 絵文字生成
|
||||||
*/
|
*/
|
||||||
EMOJI_SUGGEST: 'こんなのはどうですか?→$',
|
emoji: {
|
||||||
|
suggest: 'こんなのはどうですか?→$',
|
||||||
FORTUNE_CW: '私が今日のあなたの運勢を占いました...',
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数当てゲームをやろうと言われたけど既にやっているとき
|
* 占い
|
||||||
*/
|
*/
|
||||||
GUESSINGGAME_ARLEADY_STARTED: 'え、ゲームは既に始まってますよ!',
|
fortune: {
|
||||||
|
cw: '私が今日のあなたの運勢を占いました...',
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* タイムライン上で数当てゲームに誘われたとき
|
* タイマー
|
||||||
*/
|
*/
|
||||||
GUESSINGGAME_PLZ_DM: 'メッセージでやりましょう!',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲーム開始
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_STARTED: '0~100の秘密の数を当ててみてください♪',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲームで数字じゃない返信があったとき
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_NAN: '数字でお願いします!「やめる」と言ってゲームをやめることもできますよ!',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲーム中止を要求されたとき
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_CANCEL: 'わかりました~。ありがとうございました♪',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲームで小さい数を言われたとき
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_GRATER: '$より大きいですね',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲームで小さい数を言われたとき(2度目)
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_GRATER_AGAIN: 'もう一度言いますが$より大きいですよ!',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲームで大きい数を言われたとき
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_LESS: '$より小さいですね',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲームで大きい数を言われたとき(2度目)
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_LESS_AGAIN: 'もう一度言いますが$より小さいですよ!',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数当てゲームで正解したとき
|
|
||||||
*/
|
|
||||||
GUESSINGGAME_CONGRATS: '正解です🎉 ({tries}回目で当てました)',
|
|
||||||
|
|
||||||
timer: {
|
timer: {
|
||||||
set: 'わかりました!',
|
set: 'わかりました!',
|
||||||
invalid: 'うーん...?',
|
invalid: 'うーん...?',
|
||||||
|
|
8
src/utils/get-date.ts
Normal file
8
src/utils/get-date.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
export default function (): string {
|
||||||
|
const now = new Date();
|
||||||
|
const y = now.getFullYear();
|
||||||
|
const m = now.getMonth();
|
||||||
|
const d = now.getDate();
|
||||||
|
const today = `${y}/${m + 1}/${d}`;
|
||||||
|
return today;
|
||||||
|
}
|
Loading…
Reference in a new issue