mirror of
https://github.com/nullnyat/NullcatChan.git
synced 2025-08-04 10:06:24 +09:00
nanka iroiro
This commit is contained in:
@ -4,6 +4,7 @@ import IModule from '../../module';
|
||||
import MessageLike from '../../message-like';
|
||||
import serifs from '../../serifs';
|
||||
import Friend from '../../friend';
|
||||
import getDate from '../../utils/get-date';
|
||||
|
||||
function zeroPadding(num: number, length: number): string {
|
||||
return ('0000000000' + num).slice(-length);
|
||||
@ -76,12 +77,9 @@ export default class CoreModule implements IModule {
|
||||
return true;
|
||||
}
|
||||
|
||||
const withSan =
|
||||
name.endsWith('さん') ||
|
||||
name.endsWith('くん') ||
|
||||
name.endsWith('君') ||
|
||||
name.endsWith('ちゃん') ||
|
||||
name.endsWith('様');
|
||||
const titles = ['さん', 'くん', '君', 'ちゃん', '様', '先生'];
|
||||
|
||||
const withSan = titles.some(t => name.endsWith(t));
|
||||
|
||||
if (withSan) {
|
||||
msg.friend.updateName(name);
|
||||
@ -101,11 +99,7 @@ export default class CoreModule implements IModule {
|
||||
if (!msg.text) return false;
|
||||
|
||||
const incLove = () => {
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const today = `${y}/${m + 1}/${d}`;
|
||||
const today = getDate();
|
||||
|
||||
const data = msg.friend.getPerModulesData(this);
|
||||
|
||||
@ -146,6 +140,7 @@ export default class CoreModule implements IModule {
|
||||
if (!msg.text) return false;
|
||||
if (!msg.text.includes('なでなで')) return false;
|
||||
|
||||
//#region 1日に1回だけ親愛度を上げる
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
@ -160,6 +155,7 @@ export default class CoreModule implements IModule {
|
||||
|
||||
msg.friend.incLove();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
msg.reply(
|
||||
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 face = faces[Math.floor(Math.random() * faces.length)];
|
||||
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;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -36,7 +36,7 @@ export default class FortuneModule implements IModule {
|
||||
const rng = seedrandom(seed);
|
||||
const omikuji = omikujis[Math.floor(rng() * omikujis.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;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -38,9 +38,9 @@ export default class GuessingGameModule implements IModule {
|
||||
|
||||
if (!msg.isMessage) {
|
||||
if (exist != null) {
|
||||
msg.reply(serifs.GUESSINGGAME_ARLEADY_STARTED);
|
||||
msg.reply(serifs.guessingGame.arleadyStarted);
|
||||
} else {
|
||||
msg.reply(serifs.GUESSINGGAME_PLZ_DM);
|
||||
msg.reply(serifs.guessingGame.plzDm);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -57,7 +57,7 @@ export default class GuessingGameModule implements IModule {
|
||||
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);
|
||||
});
|
||||
|
||||
@ -76,7 +76,7 @@ export default class GuessingGameModule implements IModule {
|
||||
});
|
||||
|
||||
if (msg.text.includes('やめ')) {
|
||||
msg.reply(serifs.GUESSINGGAME_CANCEL);
|
||||
msg.reply(serifs.guessingGame.cancel);
|
||||
exist.isEnded = true;
|
||||
exist.endedAt = Date.now();
|
||||
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]+/);
|
||||
|
||||
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);
|
||||
});
|
||||
} else {
|
||||
@ -104,15 +104,15 @@ export default class GuessingGameModule implements IModule {
|
||||
|
||||
if (exist.secret < g) {
|
||||
text = firsttime
|
||||
? serifs.GUESSINGGAME_LESS.replace('$', g.toString())
|
||||
: serifs.GUESSINGGAME_LESS_AGAIN.replace('$', g.toString());
|
||||
? serifs.guessingGame.less.replace('$', g.toString())
|
||||
: serifs.guessingGame.lessAgain.replace('$', g.toString());
|
||||
} else if (exist.secret > g) {
|
||||
text = firsttime
|
||||
? serifs.GUESSINGGAME_GRATER.replace('$', g.toString())
|
||||
: serifs.GUESSINGGAME_GRATER_AGAIN.replace('$', g.toString());
|
||||
? serifs.guessingGame.grater.replace('$', g.toString())
|
||||
: serifs.guessingGame.graterAgain.replace('$', g.toString());
|
||||
} else {
|
||||
end = true;
|
||||
text = serifs.GUESSINGGAME_CONGRATS.replace('{tries}', exist.tries.length.toString());
|
||||
text = serifs.guessingGame.congrats.replace('{tries}', exist.tries.length.toString());
|
||||
}
|
||||
|
||||
if (end) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
import * as request from 'request-promise-native';
|
||||
import Reversi, { Color } from 'misskey-reversi';
|
||||
import config from '../../config';
|
||||
import serifs from '../../serifs';
|
||||
|
||||
const db = {};
|
||||
|
||||
@ -208,36 +209,36 @@ class Session {
|
||||
private onEnded = async (msg: any) => {
|
||||
// ストリームから切断
|
||||
process.send({
|
||||
type: 'close'
|
||||
type: 'ended'
|
||||
});
|
||||
|
||||
let text: string;
|
||||
|
||||
if (msg.body.game.surrendered) {
|
||||
if (this.isSettai) {
|
||||
text = `(${this.userName}を接待していたら投了されちゃいました... ごめんなさい)`;
|
||||
text = serifs.reversi.settaiButYouSurrendered.replace('{name}', this.userName);
|
||||
} else {
|
||||
text = `${this.userName}が投了しちゃいました`;
|
||||
text = serifs.reversi.youSurrendered.replace('{name}', this.userName);
|
||||
}
|
||||
} else if (msg.body.winnerId) {
|
||||
if (msg.body.winnerId == this.account.id) {
|
||||
if (this.isSettai) {
|
||||
text = `${this.userName}に接待で勝ってしまいました...`;
|
||||
text = serifs.reversi.iWonButSettai.replace('{name}', this.userName);
|
||||
} else {
|
||||
text = `${this.userName}に勝ちました♪`;
|
||||
text = serifs.reversi.iWon.replace('{name}', this.userName);
|
||||
}
|
||||
} else {
|
||||
if (this.isSettai) {
|
||||
text = `(${this.userName}に接待で負けてあげました...♪)`;
|
||||
text = serifs.reversi.iLoseButSettai.replace('{name}', this.userName);
|
||||
} else {
|
||||
text = `${this.userName}に負けました...`;
|
||||
text = serifs.reversi.iLose.replace('{name}', this.userName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.isSettai) {
|
||||
text = `(${this.userName}に接待で引き分けました...)`;
|
||||
text = serifs.reversi.drawnSettai.replace('{name}', this.userName);
|
||||
} else {
|
||||
text = `${this.userName}と引き分けました~`;
|
||||
text = serifs.reversi.drawn.replace('{name}', this.userName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,8 +417,8 @@ class Session {
|
||||
*/
|
||||
private postGameStarted = async () => {
|
||||
const text = this.isSettai
|
||||
? `${this.userName}の接待を始めました!`
|
||||
: `対局を${this.userName}と始めました! (強さ${this.strength})`;
|
||||
? serifs.reversi.startedSettai.replace('{name}', this.userName)
|
||||
: serifs.reversi.started.replace('{name}', this.userName).replace('{strength}', this.strength.toString());
|
||||
|
||||
return await this.post(`${text}\n→[観戦する](${this.url})`);
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ import serifs from '../../serifs';
|
||||
import config from '../../config';
|
||||
import MessageLike from '../../message-like';
|
||||
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 {
|
||||
public name = 'reversi';
|
||||
@ -44,13 +47,13 @@ export default class ReversiModule implements IModule {
|
||||
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 (config.reversiEnabled) {
|
||||
msg.reply(serifs.REVERSI_OK);
|
||||
msg.reply(serifs.reversi.ok);
|
||||
|
||||
this.ai.api('games/reversi/match', {
|
||||
userId: msg.userId
|
||||
});
|
||||
} else {
|
||||
msg.reply(serifs.REVERSI_DECLINE);
|
||||
msg.reply(serifs.reversi.decline);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -157,8 +160,10 @@ export default class ReversiModule implements IModule {
|
||||
type: 'set',
|
||||
pos: msg.pos
|
||||
});
|
||||
} else if (msg.type == 'close') {
|
||||
} else if (msg.type == 'ended') {
|
||||
gw.close();
|
||||
|
||||
this.onGameEnded(game);
|
||||
}
|
||||
});
|
||||
|
||||
@ -189,4 +194,23 @@ export default class ReversiModule implements IModule {
|
||||
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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user