From 37666a89770fbe20aba2c5446ef6f4485ae24bc4 Mon Sep 17 00:00:00 2001 From: Smith Date: Tue, 5 Apr 2022 17:12:43 +0200 Subject: [PATCH] discord bot, index redirect, refactoring --- index.html | 5 +- server.js | 13 +-- server.ts | 16 +-- src/discord-bot.js | 205 +++++++++++++++++++++++++------------- src/discord-bot.ts | 238 ++++++++++++++++++++++++++++++-------------- src/game-server.js | 40 ++++---- src/game-server.ts | 42 ++++---- src/lib/hhmmss.js | 12 ++- src/lib/hhmmss.ts | 12 +-- src/telegram-bot.js | 93 +++++++++-------- src/telegram-bot.ts | 100 ++++++++++--------- src/watcher.js | 24 +++-- src/watcher.ts | 12 ++- 13 files changed, 494 insertions(+), 318 deletions(-) diff --git a/index.html b/index.html index b87a2fe..db3be96 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,8 @@ + - gsw...index +

Please follow this link.

- \ No newline at end of file + diff --git a/server.js b/server.js index 3a27de3..69bdf0b 100644 --- a/server.js +++ b/server.js @@ -11,8 +11,8 @@ const watcher_1 = require("./src/watcher"); const CACHE_MAX_AGE = parseInt(process.env.CACHE_MAX_AGE || '0', 10); const APP_HOST = process.env.app_host || '0.0.0.0'; const APP_PORT = parseInt(process.env.app_port || '8080', 10); -const DBG = Boolean(process.env.DBG || false); const SECRET = process.env.SECRET || 'secret'; +const DBG = Boolean(process.env.DBG || false); (0, http_1.createServer)(async (req, res) => { if (DBG) console.log('DBG: %j %j', (new Date()), req.url); @@ -24,17 +24,6 @@ const SECRET = process.env.SECRET || 'secret'; }); fs_1.default.createReadStream('./index.html').pipe(res); } - else if (reqUrl.pathname === '/discord/post') { //DEBUG - console.log('REQ.HEADERS', req.headers); - let body = ''; - req.on('data', (chunk) => { - body += chunk; // convert Buffer to string - }); - req.on('end', () => { - console.log('POST.DATA:', String(body)); - res.end(''); - }); - } else if (reqUrl.pathname === '/ping') { console.log('ping'); res.end('pong'); diff --git a/server.ts b/server.ts index 180c5f2..6b2e433 100644 --- a/server.ts +++ b/server.ts @@ -4,14 +4,13 @@ import { URL } from 'url'; import 'dotenv/config'; -import { main, WatcherConfig } from './src/watcher'; +import { main } from './src/watcher'; const CACHE_MAX_AGE = parseInt(process.env.CACHE_MAX_AGE || '0', 10); const APP_HOST = process.env.app_host || '0.0.0.0'; const APP_PORT = parseInt(process.env.app_port || '8080', 10); - -const DBG = Boolean(process.env.DBG || false); const SECRET = process.env.SECRET || 'secret'; +const DBG = Boolean(process.env.DBG || false); createServer(async (req, res) => { if (DBG) console.log('DBG: %j %j', (new Date()), req.url); @@ -24,17 +23,6 @@ createServer(async (req, res) => { }); fs.createReadStream('./index.html').pipe(res); } - else if (reqUrl.pathname === '/discord/post') {//DEBUG - console.log('REQ.HEADERS', req.headers); - let body = ''; - req.on('data', (chunk) => { - body += chunk; // convert Buffer to string - }); - req.on('end', () => { - console.log('POST.DATA:', String(body)); - res.end(''); - }); - } else if (reqUrl.pathname === '/ping') { console.log('ping'); res.end('pong'); diff --git a/src/discord-bot.js b/src/discord-bot.js index 5c115ca..58dbd89 100644 --- a/src/discord-bot.js +++ b/src/discord-bot.js @@ -1,81 +1,150 @@ "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.serverUpdate = exports.init = void 0; const discord_js_1 = require("discord.js"); -//https://github.com/soulkobk/DiscordBot_GameStatus -const prefix = '@gsw'; -let client; -function init(token) { - client = new discord_js_1.Client({ - //messageEditHistoryMaxSize: 0, - //ws: {intents: ['GUILDS', 'GUILD_MESSAGES']} +const lowdb_1 = require("@commonify/lowdb"); +const hhmmss_1 = __importDefault(require("./lib/hhmmss")); +const DATA_PATH = process.env.DATA_PATH || './data/'; +const DBG = Boolean(process.env.DBG || false); +const adapter = new lowdb_1.JSONFile(DATA_PATH + 'discord.json'); +const db = new lowdb_1.Low(adapter); +const serverInfoMessages = []; +let bot; +async function init(token) { + console.log('discord-bot starting...'); + bot = new discord_js_1.Client({ + messageEditHistoryMaxSize: 0, + ws: { intents: ['GUILDS', 'GUILD_MESSAGES'] } }); - console.log(' dc.init'); //DEBUG - client.on('ready', () => { - console.log(' dc.client.READY'); //DEBUG + bot.on('error', e => { + console.error('discord-bot ERROR', e.message || e); }); - client.on('message', msg => { - if (msg.content === 'ping') { - msg.reply('pong'); + await new Promise((resolve, reject) => { + bot.once('ready', () => { + console.log('discord-bot ready', bot.user); + bot.removeListener('error', reject); + resolve(); + }); + bot.once('error', reject); + if (DBG) { + bot.on('message', msg => { + if (msg.content === 'ping') { + msg.reply('pong'); + } + }); } + return bot.login(token); }); - // client.on('messageCreate', (message) => { - // console.log('!!!!!dc.messageCreate', message.author, message.content);//DEBUG - // if (message.author.bot) return; - // if (!message.content.startsWith(prefix)) return; - // const commandBody = message.content.slice(prefix.length); - // const args = commandBody.split(' '); - // const command = String(args.shift()).toLowerCase(); - // if (command === 'ping') { - // const timeTaken = Date.now() - message.createdTimestamp; - // message.reply(`Pong! ${timeTaken}ms`); - // } - // }); - return client.login(token); + await db.read(); + db.data = db.data || []; } exports.init = init; async function serverUpdate(gs) { - if (!gs.info) - return; - console.log('discord.serverUpdate', gs.config.host, gs.config.port, gs.config.discord); - /* - for (const cid of gs.config.discord.chatIds) { - let m = await getServerInfoMessage(cid, gs.config.host, gs.config.port); - - const stats = gs.history.stats(); - let statsText = ''; - if (stats.length > 0) { - const s = stats.pop(); - if (s) { - statsText = ' (hourly max: ' + s.max + ', hourly avg: ' + s.avg.toFixed(1) + ')'; - } - } - - const infoText: string[] = [ - gs.niceName, - gs.info.game + ' / ' + gs.info.map, - gs.info.connect, - 'Players ' + gs.info.playersNum + '/' + gs.info.playersMax + statsText - ]; - - if (gs.info?.players.length > 0) { - infoText.push('```'); - for(const p of gs.info?.players) { - let playerLine = ''; - if (p.raw?.time !== undefined) { - playerLine += '[' + hhmmss(p.raw.time) + '] '; - } - playerLine += p.name; - if (p.raw?.score !== undefined) { - playerLine += ' [score: ' + p.raw.score + ']'; - } - infoText.push(playerLine); - } - infoText.push('```'); - } - - m.setText(infoText.join('\n')); - } - */ + if (DBG) + console.log('discord.serverUpdate', gs.config.host, gs.config.port, gs.config.discord); + for (const cid of gs.config.discord.channelIds) { + let m = await getServerInfoMessage(cid, gs.config.host, gs.config.port); + m.updatePost(gs); + } } exports.serverUpdate = serverUpdate; +async function getServerInfoMessage(cid, host, port) { + let m = serverInfoMessages.find(n => { + return n.channelId === cid && n.host === host && n.port === port; + }); + if (!m) { + m = new ServerInfoMessage(cid, host, port); + let msgId; + if (db.data) { + const md = db.data.find(d => { + return d.channelId === cid && d.host === host && d.port === port; + }); + if (md) { + msgId = md.messageId; + } + } + await m.init(msgId); + serverInfoMessages.push(m); + } + return m; +} +class ServerInfoMessage { + constructor(channelId, host, port) { + this.messageId = '0'; + this.channelId = channelId; + this.host = host; + this.port = port; + } + async init(msgId) { + this.channel = await bot.channels.fetch(this.channelId); + if (msgId) { + this.messageId = msgId; + this.message = await this.channel.messages.fetch(msgId); + } + else { + let embed = new discord_js_1.MessageEmbed(); + embed.setTitle('Initializing server info... ' + (new Date()).toISOString()); + embed.setColor('#00ff00'); + this.message = await this.channel.send({ embed }); + this.messageId = this.message.id; + } + if (db.data) { + const mi = db.data.findIndex(d => { + return d.channelId === this.channelId && d.host === this.host && d.port === this.port; + }); + if (mi === -1 || mi === undefined) { + db.data.push({ + channelId: this.channelId, + host: this.host, + port: this.port, + messageId: this.messageId + }); + } + else { + db.data[mi].messageId = this.messageId; + } + await db.write(); + } + } + async updatePost(gs) { + var _a, _b, _c, _d; + if (!this.message) + return; + const embed = new discord_js_1.MessageEmbed(); + embed.setTitle(gs.niceName + ' offline...'); + embed.setColor('#ff0000'); + embed.setFooter('Last updated'); + embed.setTimestamp(); + if (gs.info && gs.online) { + embed.setTitle(gs.niceName); + embed.setColor('#000000'); + embed.addField('Game', gs.info.game, true); + embed.addField('Map', gs.info.map, true); + embed.addField('Connect', 'steam://connect/' + gs.info.connect); + if (((_a = gs.info) === null || _a === void 0 ? void 0 : _a.players.length) > 0) { + const pNames = []; + const pTimes = []; + const pScores = []; + let c = 0; + for (const p of (_b = gs.info) === null || _b === void 0 ? void 0 : _b.players) { + c++; + pNames.push(p.name || 'n/a'); + pTimes.push((0, hhmmss_1.default)(((_c = p.raw) === null || _c === void 0 ? void 0 : _c.time) || 0)); + pScores.push(((_d = p.raw) === null || _d === void 0 ? void 0 : _d.score) || '0'); + } + embed.addField('Players ' + gs.info.playersNum + '/' + gs.info.playersMax, '```\n' + pNames.join('\n').slice(0, 1016) + '\n```', true); + embed.addField('Time', '```\n' + pTimes.join('\n').slice(0, 1016) + '\n```', true); + embed.addField('Score', '```\n' + pScores.join('\n').slice(0, 1016) + '\n```', true); + } + } + try { + await this.message.edit(null, { embed }); + } + catch (e) { + console.log(e.message || e); + } + } +} diff --git a/src/discord-bot.ts b/src/discord-bot.ts index 3fba9cb..fe48a73 100644 --- a/src/discord-bot.ts +++ b/src/discord-bot.ts @@ -1,89 +1,183 @@ -import {Client, MessageEmbed, Intents} from 'discord.js'; +import { Client, MessageEmbed, TextChannel, Message } from 'discord.js'; +import { Low, JSONFile } from '@commonify/lowdb'; import { GameServer } from './game-server'; +import hhmmss from './lib/hhmmss'; -//https://github.com/soulkobk/DiscordBot_GameStatus -const prefix = '@gsw'; -let client: Client; +const DATA_PATH = process.env.DATA_PATH || './data/'; +const DBG = Boolean(process.env.DBG || false); -export function init(token: string) { - client = new Client({ - //messageEditHistoryMaxSize: 0, - //ws: {intents: ['GUILDS', 'GUILD_MESSAGES']} +interface DiscordData { + channelId: string; + host: string; + port: number; + messageId: string; +} + +const adapter = new JSONFile(DATA_PATH + 'discord.json'); +const db = new Low(adapter); + +const serverInfoMessages: ServerInfoMessage[] = []; + +let bot: Client; +export async function init(token: string) { + console.log('discord-bot starting...'); + bot = new Client({ + messageEditHistoryMaxSize: 0, + ws: { intents: ['GUILDS', 'GUILD_MESSAGES'] } }); - console.log(' dc.init');//DEBUG + bot.on('error', e => { + console.error('discord-bot ERROR', e.message || e); + }); - client.on('ready', ()=> { - console.log(' dc.client.READY');//DEBUG - }) + await new Promise((resolve, reject) => { + bot.once('ready', () => { + console.log('discord-bot ready', bot.user); - client.on('message', msg => { - if (msg.content === 'ping') { - msg.reply('pong'); + bot.removeListener('error', reject); + resolve(); + }); + + bot.once('error', reject); + + if (DBG) { + bot.on('message', msg => { + if (msg.content === 'ping') { + msg.reply('pong'); + } + }); } + + return bot.login(token); }); - // client.on('messageCreate', (message) => { - // console.log('!!!!!dc.messageCreate', message.author, message.content);//DEBUG - - // if (message.author.bot) return; - // if (!message.content.startsWith(prefix)) return; - - // const commandBody = message.content.slice(prefix.length); - // const args = commandBody.split(' '); - // const command = String(args.shift()).toLowerCase(); - - // if (command === 'ping') { - // const timeTaken = Date.now() - message.createdTimestamp; - // message.reply(`Pong! ${timeTaken}ms`); - // } - // }); - - return client.login(token); + await db.read(); + db.data = db.data || []; } export async function serverUpdate(gs: GameServer) { - if (!gs.info) return; + if (DBG) console.log('discord.serverUpdate', gs.config.host, gs.config.port, gs.config.discord); - console.log('discord.serverUpdate', gs.config.host, gs.config.port, gs.config.discord); -/* - for (const cid of gs.config.discord.chatIds) { + for (const cid of gs.config.discord.channelIds) { let m = await getServerInfoMessage(cid, gs.config.host, gs.config.port); - - const stats = gs.history.stats(); - let statsText = ''; - if (stats.length > 0) { - const s = stats.pop(); - if (s) { - statsText = ' (hourly max: ' + s.max + ', hourly avg: ' + s.avg.toFixed(1) + ')'; - } - } - - const infoText: string[] = [ - gs.niceName, - gs.info.game + ' / ' + gs.info.map, - gs.info.connect, - 'Players ' + gs.info.playersNum + '/' + gs.info.playersMax + statsText - ]; - - if (gs.info?.players.length > 0) { - infoText.push('```'); - for(const p of gs.info?.players) { - let playerLine = ''; - if (p.raw?.time !== undefined) { - playerLine += '[' + hhmmss(p.raw.time) + '] '; - } - playerLine += p.name; - if (p.raw?.score !== undefined) { - playerLine += ' [score: ' + p.raw.score + ']'; - } - infoText.push(playerLine); - } - infoText.push('```'); - } - - m.setText(infoText.join('\n')); + m.updatePost(gs); } - */ -} \ No newline at end of file +} + +async function getServerInfoMessage(cid: string, host: string, port: number) { + let m = serverInfoMessages.find(n => { + return n.channelId === cid && n.host === host && n.port === port; + }); + + if (!m) { + m = new ServerInfoMessage(cid, host, port); + + let msgId; + if (db.data) { + const md = db.data.find(d => { + return d.channelId === cid && d.host === host && d.port === port; + }); + if (md) { + msgId = md.messageId; + } + } + + await m.init(msgId); + + serverInfoMessages.push(m); + } + + return m; +} + +class ServerInfoMessage { + public channelId: string; + public host: string; + public port: number; + public messageId: string = '0'; + private channel?: TextChannel; + private message?: Message; + + constructor(channelId: string, host: string, port: number) { + this.channelId = channelId; + this.host = host; + this.port = port; + } + + async init(msgId?: string) { + this.channel = await bot.channels.fetch(this.channelId) as TextChannel; + + if (msgId) { + this.messageId = msgId; + this.message = await this.channel.messages.fetch(msgId); + } else { + let embed = new MessageEmbed(); + embed.setTitle('Initializing server info... ' + (new Date()).toISOString()); + embed.setColor('#00ff00'); + + this.message = await this.channel.send({ embed }); + this.messageId = this.message.id; + } + + if (db.data) { + const mi = db.data.findIndex(d => { + return d.channelId === this.channelId && d.host === this.host && d.port === this.port; + }); + + if (mi === -1 || mi === undefined) { + db.data.push({ + channelId: this.channelId, + host: this.host, + port: this.port, + messageId: this.messageId + }); + } else { + db.data[mi].messageId = this.messageId; + } + + await db.write(); + } + } + + async updatePost(gs: GameServer) { + if (!this.message) return; + const embed = new MessageEmbed(); + embed.setTitle(gs.niceName + ' offline...'); + embed.setColor('#ff0000'); + embed.setFooter('Last updated'); + embed.setTimestamp(); + + if (gs.info && gs.online) { + embed.setTitle(gs.niceName); + embed.setColor('#000000'); + + embed.addField('Game', gs.info.game, true); + embed.addField('Map', gs.info.map, true); + embed.addField('Connect', 'steam://connect/' + gs.info.connect); + + if (gs.info?.players.length > 0) { + const pNames: string[] = []; + const pTimes: string[] = []; + const pScores: string[] = []; + let c = 0; + for (const p of gs.info?.players) { + c++; + pNames.push(p.name || 'n/a'); + pTimes.push(hhmmss(p.raw?.time || 0)); + pScores.push(p.raw?.score || '0'); + } + + embed.addField('Players ' + gs.info.playersNum + '/' + gs.info.playersMax, '```\n' + pNames.join('\n').slice(0, 1016) + '\n```', true); + embed.addField('Time', '```\n' + pTimes.join('\n').slice(0, 1016) + '\n```', true); + embed.addField('Score', '```\n' + pScores.join('\n').slice(0, 1016) + '\n```', true); + } + } + + try { + await this.message.edit(null, { embed }); + } catch (e: any) { + console.log(e.message || e); + } + } +} diff --git a/src/game-server.js b/src/game-server.js index af09a65..715f2cf 100644 --- a/src/game-server.js +++ b/src/game-server.js @@ -27,24 +27,26 @@ function saveDb() { exports.saveDb = saveDb; class GameServer { constructor(config) { - console.log('game-server.init', config.host, config.port, config.type, config.appId); + this.online = false; + console.log('game-server init', config.host, config.port, config.type, config.appId); this.config = config; this.history = new ServerHistory(config.host + ':' + config.port); + this._niceName = config.host + ':' + config.port; } async update() { - let info; - info = await this.gamedig(); + let info = await this.gamedig(); if (!info && STEAM_WEB_API_KEY) { info = await this.steam(); } if (info) { + this.online = true; this.info = info; this.history.add(info); } else { - console.error('game-server.update no info!'); + this.online = false; + console.error('game-server not available', this.config.host, this.config.port); } - return; } async gamedig() { try { @@ -111,21 +113,25 @@ class GameServer { } get niceName() { var _a; - let nn = ((_a = this.info) === null || _a === void 0 ? void 0 : _a.name) || ''; - for (let i = 0; i < nn.length; i++) { - if (nn[i] == '^') { - nn = nn.slice(0, i) + ' ' + nn.slice(i + 2); - } - else if (nn[i] == '█') { - nn = nn.slice(0, i) + ' ' + nn.slice(i + 1); - } - else if (nn[i] == '�') { - nn = nn.slice(0, i) + ' ' + nn.slice(i + 2); + let nn = (_a = this.info) === null || _a === void 0 ? void 0 : _a.name; + if (nn) { + for (let i = 0; i < nn.length; i++) { + if (nn[i] == '^') { + nn = nn.slice(0, i) + ' ' + nn.slice(i + 2); + } + else if (nn[i] == '█') { + nn = nn.slice(0, i) + ' ' + nn.slice(i + 1); + } + else if (nn[i] == '�') { + nn = nn.slice(0, i) + ' ' + nn.slice(i + 2); + } + ; } ; + if (nn) + this._niceName = nn; } - ; - return nn; + return this._niceName; } } exports.GameServer = GameServer; diff --git a/src/game-server.ts b/src/game-server.ts index 89be253..9325d1f 100644 --- a/src/game-server.ts +++ b/src/game-server.ts @@ -55,29 +55,31 @@ export class GameServer { public info?: Info; public config: WatcherConfig; public history: ServerHistory; + private _niceName: string; + public online: boolean = false; constructor(config: WatcherConfig) { - console.log('game-server.init', config.host, config.port, config.type, config.appId); + console.log('game-server init', config.host, config.port, config.type, config.appId); this.config = config; this.history = new ServerHistory(config.host + ':' + config.port); + this._niceName = config.host + ':' + config.port; } async update() { - let info: Info | null; - info = await this.gamedig(); + let info = await this.gamedig(); if (!info && STEAM_WEB_API_KEY) { info = await this.steam(); } if (info) { + this.online = true; this.info = info; this.history.add(info); } else { - console.error('game-server.update no info!'); + this.online = false; + console.error('game-server not available', this.config.host, this.config.port); } - - return; } async gamedig(): Promise { @@ -88,7 +90,7 @@ export class GameServer { type: this.config.type, }) as qRes; - const raw = res.raw as { game: string; folder: string;}; + const raw = res.raw as { game: string; folder: string; }; const game = raw.game || raw.folder || this.config.type; const players: Player[] = res.players;//todo: map / filter @@ -151,19 +153,23 @@ export class GameServer { } get niceName() { - let nn = this.info?.name || ''; + let nn = this.info?.name; - for (let i = 0; i < nn.length; i++) { - if (nn[i] == '^') { - nn = nn.slice(0, i) + ' ' + nn.slice(i+2); - } else if (nn[i] == '█') { - nn = nn.slice(0, i) + ' ' + nn.slice(i+1); - } else if (nn[i] == '�') { - nn = nn.slice(0, i) + ' ' + nn.slice(i+2); + if (nn) { + for (let i = 0; i < nn.length; i++) { + if (nn[i] == '^') { + nn = nn.slice(0, i) + ' ' + nn.slice(i + 2); + } else if (nn[i] == '█') { + nn = nn.slice(0, i) + ' ' + nn.slice(i + 1); + } else if (nn[i] == '�') { + nn = nn.slice(0, i) + ' ' + nn.slice(i + 2); + }; }; - }; - return nn; + if (nn) this._niceName = nn; + } + + return this._niceName; } } @@ -197,7 +203,7 @@ class ServerHistory { const d = new Date(); const dh = this.yyyymmddhh(d); - + if (!db.data.population[this.id]) { db.data.population[this.id] = []; } diff --git a/src/lib/hhmmss.js b/src/lib/hhmmss.js index e0fabea..efd3989 100644 --- a/src/lib/hhmmss.js +++ b/src/lib/hhmmss.js @@ -4,12 +4,14 @@ exports.default = (sec_num) => { let hours = Math.floor(sec_num / 3600); let minutes = Math.floor((sec_num - (hours * 3600)) / 60); let secs = Math.floor(sec_num - (hours * 3600) - (minutes * 60)); - //if (hours < 10) {hours = `0${hours}`;} - if (hours == 0) { - hours = ''; + if (hours === 0) { + hours = '00'; + } + else if (hours < 10) { + hours = `0${hours}`; } else { - hours = `${hours}:`; + hours = `${hours}`; } if (minutes < 10) { minutes = `0${minutes}`; @@ -17,5 +19,5 @@ exports.default = (sec_num) => { if (secs < 10) { secs = `0${secs}`; } - return [hours, minutes, ':', secs].join(''); + return [hours, ':', minutes, ':', secs].join(''); }; diff --git a/src/lib/hhmmss.ts b/src/lib/hhmmss.ts index aca2410..97fa5ef 100644 --- a/src/lib/hhmmss.ts +++ b/src/lib/hhmmss.ts @@ -3,10 +3,10 @@ export default (sec_num: number) => { let minutes: number | string = Math.floor((sec_num - (hours * 3600)) / 60); let secs: number | string = Math.floor(sec_num - (hours * 3600) - (minutes * 60)); - //if (hours < 10) {hours = `0${hours}`;} - if (hours == 0) {hours = '';} - else {hours = `${hours}:`;} - if (minutes < 10) { minutes = `0${minutes}`; } - if (secs < 10) { secs = `0${secs}`; } - return [hours, minutes, ':', secs].join(''); + if (hours === 0) { hours = '00' } + else if (hours < 10) { hours = `0${hours}` } + else { hours = `${hours}` } + if (minutes < 10) { minutes = `0${minutes}` } + if (secs < 10) { secs = `0${secs}` } + return [hours, ':', minutes, ':', secs].join(''); } diff --git a/src/telegram-bot.js b/src/telegram-bot.js index cb07c09..f076c53 100644 --- a/src/telegram-bot.js +++ b/src/telegram-bot.js @@ -5,9 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.serverUpdate = exports.init = void 0; const grammy_1 = require("grammy"); -const hhmmss_1 = __importDefault(require("./lib/hhmmss")); const lowdb_1 = require("@commonify/lowdb"); +const hhmmss_1 = __importDefault(require("./lib/hhmmss")); const DATA_PATH = process.env.DATA_PATH || './data/'; +const DBG = Boolean(process.env.DBG || false); const adapter = new lowdb_1.JSONFile(DATA_PATH + 'telegram.json'); const db = new lowdb_1.Low(adapter); const serverInfoMessages = []; @@ -15,14 +16,21 @@ let bot; async function init(token) { console.log('telegram-bot starting...'); bot = new grammy_1.Bot(token); + bot.catch(e => { + console.error('telegram-bot ERROR', e.message || e); + }); const me = await bot.api.getMe(); console.log('telegram-bot ready', me); - // bot.on('message:text', ctx => {ctx.reply('echo: ' + ctx.message.text);}); - // bot.command('start', ctx => ctx.reply('cmd.start.response')); - // bot.start(); + if (DBG) { + bot.on('message:text', ctx => { + if (ctx.message.text === 'ping') + ctx.reply('pong'); + }); + // bot.command('ping', ctx => ctx.reply('/pong')); + bot.start(); + } await db.read(); db.data = db.data || []; - return; } exports.init = init; async function getServerInfoMessage(cid, host, port) { @@ -46,42 +54,11 @@ async function getServerInfoMessage(cid, host, port) { return m; } async function serverUpdate(gs) { - var _a, _b, _c, _d; - if (!gs.info) - return; - console.log('telegram.serverUpdate', gs.config.host, gs.config.port, gs.config.telegram); + if (DBG) + console.log('telegram.serverUpdate', gs.config.host, gs.config.port, gs.config.telegram); for (const cid of gs.config.telegram.chatIds) { let m = await getServerInfoMessage(cid, gs.config.host, gs.config.port); - const stats = gs.history.stats(); - let statsText = ''; - if (stats.length > 0) { - const s = stats.pop(); - if (s) { - statsText = ' (hourly max: ' + s.max + ', hourly avg: ' + s.avg.toFixed(1) + ')'; - } - } - const infoText = [ - gs.niceName, - gs.info.game + ' / ' + gs.info.map, - gs.info.connect, - 'Players ' + gs.info.playersNum + '/' + gs.info.playersMax + statsText - ]; - if (((_a = gs.info) === null || _a === void 0 ? void 0 : _a.players.length) > 0) { - infoText.push('```'); - for (const p of (_b = gs.info) === null || _b === void 0 ? void 0 : _b.players) { - let playerLine = ''; - if (((_c = p.raw) === null || _c === void 0 ? void 0 : _c.time) !== undefined) { - playerLine += '[' + (0, hhmmss_1.default)(p.raw.time) + '] '; - } - playerLine += p.name; - if (((_d = p.raw) === null || _d === void 0 ? void 0 : _d.score) !== undefined) { - playerLine += ' [score: ' + p.raw.score + ']'; - } - infoText.push(playerLine); - } - infoText.push('```'); - } - m.setText(infoText.join('\n')); + m.updatePost(gs); } } exports.serverUpdate = serverUpdate; @@ -118,10 +95,42 @@ class ServerInfoMessage { await db.write(); } } - async setText(text) { - console.log('setText', this.host, this.port); + async updatePost(gs) { + var _a, _b; + let infoText = gs.niceName + ' offline...'; + if (gs.info && gs.online) { + const stats = gs.history.stats(); + let statsText = ''; + if (stats.length > 0) { + const s = stats.slice(-1).pop(); + if (s) { + statsText = ' (hourly avg/max: ' + s.avg.toFixed(1) + '/' + s.max + ') '; + } + } + infoText = [ + gs.niceName, + gs.info.game + ' / ' + gs.info.map, + gs.info.connect, + 'Players ' + gs.info.playersNum + '/' + gs.info.playersMax + statsText + ].join('\n'); + if (gs.info.players.length > 0 && gs.info.players[0].name !== undefined) { + const pnArr = []; + for (const p of gs.info.players) { + let playerLine = ''; + if (((_a = p.raw) === null || _a === void 0 ? void 0 : _a.time) !== undefined) { + playerLine += (0, hhmmss_1.default)(p.raw.time) + ' '; + } + playerLine += p.name; + if (((_b = p.raw) === null || _b === void 0 ? void 0 : _b.score) !== undefined) { + playerLine += ' (' + p.raw.score + ')'; + } + pnArr.push(playerLine); + } + infoText += '```\n' + pnArr.join('\n').slice(0, 4088 - infoText.length) + '\n```'; + } + } try { - await bot.api.editMessageText(this.chatId, this.messageId, text, { parse_mode: 'Markdown' }); + await bot.api.editMessageText(this.chatId, this.messageId, infoText, { parse_mode: 'Markdown' }); } catch (e) { console.log(e.message || e); diff --git a/src/telegram-bot.ts b/src/telegram-bot.ts index d02aa63..976a6bf 100644 --- a/src/telegram-bot.ts +++ b/src/telegram-bot.ts @@ -1,9 +1,10 @@ import { Bot } from 'grammy'; +import { Low, JSONFile } from '@commonify/lowdb'; import { GameServer } from './game-server'; import hhmmss from './lib/hhmmss'; -import { Low, JSONFile } from '@commonify/lowdb'; const DATA_PATH = process.env.DATA_PATH || './data/'; +const DBG = Boolean(process.env.DBG || false); interface TelegramData { chatId: string; @@ -22,17 +23,24 @@ export async function init(token: string) { console.log('telegram-bot starting...'); bot = new Bot(token); + bot.catch(e => { + console.error('telegram-bot ERROR', e.message || e); + }); + const me = await bot.api.getMe(); console.log('telegram-bot ready', me); - // bot.on('message:text', ctx => {ctx.reply('echo: ' + ctx.message.text);}); - // bot.command('start', ctx => ctx.reply('cmd.start.response')); - // bot.start(); + if(DBG) { + bot.on('message:text', ctx => { + if (ctx.message.text === 'ping') + ctx.reply('pong'); + }); + // bot.command('ping', ctx => ctx.reply('/pong')); + bot.start(); + } await db.read(); db.data = db.data || []; - - return; } async function getServerInfoMessage(cid: string, host: string, port: number) { @@ -62,46 +70,11 @@ async function getServerInfoMessage(cid: string, host: string, port: number) { } export async function serverUpdate(gs: GameServer) { - if (!gs.info) return; - - console.log('telegram.serverUpdate', gs.config.host, gs.config.port, gs.config.telegram); + if (DBG) console.log('telegram.serverUpdate', gs.config.host, gs.config.port, gs.config.telegram); for (const cid of gs.config.telegram.chatIds) { let m = await getServerInfoMessage(cid, gs.config.host, gs.config.port); - - const stats = gs.history.stats(); - let statsText = ''; - if (stats.length > 0) { - const s = stats.pop(); - if (s) { - statsText = ' (hourly max: ' + s.max + ', hourly avg: ' + s.avg.toFixed(1) + ')'; - } - } - - const infoText: string[] = [ - gs.niceName, - gs.info.game + ' / ' + gs.info.map, - gs.info.connect, - 'Players ' + gs.info.playersNum + '/' + gs.info.playersMax + statsText - ]; - - if (gs.info?.players.length > 0) { - infoText.push('```'); - for(const p of gs.info?.players) { - let playerLine = ''; - if (p.raw?.time !== undefined) { - playerLine += '[' + hhmmss(p.raw.time) + '] '; - } - playerLine += p.name; - if (p.raw?.score !== undefined) { - playerLine += ' [score: ' + p.raw.score + ']'; - } - infoText.push(playerLine); - } - infoText.push('```'); - } - - m.setText(infoText.join('\n')); + m.updatePost(gs); } } @@ -145,10 +118,45 @@ class ServerInfoMessage { } } - async setText(text: string) { - console.log('setText', this.host, this.port); + async updatePost(gs: GameServer) { + let infoText = gs.niceName + ' offline...'; + + if (gs.info && gs.online) { + const stats = gs.history.stats(); + let statsText = ''; + if (stats.length > 0) { + const s = stats.slice(-1).pop(); + if (s) { + statsText = ' (hourly avg/max: ' + s.avg.toFixed(1) + '/' + s.max + ') '; + } + } + + infoText = [ + gs.niceName, + gs.info.game + ' / ' + gs.info.map, + gs.info.connect, + 'Players ' + gs.info.playersNum + '/' + gs.info.playersMax + statsText + ].join('\n'); + + if (gs.info.players.length > 0 && gs.info.players[0].name !== undefined) { + const pnArr: string[] = []; + for(const p of gs.info.players) { + let playerLine = ''; + if (p.raw?.time !== undefined) { + playerLine += hhmmss(p.raw.time) + ' '; + } + playerLine += p.name; + if (p.raw?.score !== undefined) { + playerLine += ' (' + p.raw.score + ')'; + } + pnArr.push(playerLine); + } + infoText += '```\n' + pnArr.join('\n').slice(0, 4088 - infoText.length) + '\n```'; + } + } + try { - await bot.api.editMessageText(this.chatId, this.messageId, text, {parse_mode: 'Markdown'}); + await bot.api.editMessageText(this.chatId, this.messageId, infoText, {parse_mode: 'Markdown'}); } catch (e: any) { console.log(e.message || e); } diff --git a/src/watcher.js b/src/watcher.js index d1b472f..4d90633 100644 --- a/src/watcher.js +++ b/src/watcher.js @@ -1,7 +1,11 @@ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -25,10 +29,11 @@ const discordBot = __importStar(require("./discord-bot")); const telegramBot = __importStar(require("./telegram-bot")); const fs_1 = require("fs"); const { readFile } = fs_1.promises; -const REFRESH_TIME_MINUTES = parseInt(process.env.REFRESH_TIME_MINUTES || '1', 10); +const REFRESH_TIME_MINUTES = parseInt(process.env.REFRESH_TIME_MINUTES || '5', 10); const DISCORD_BOT_TOKEN = process.env.DISCORD_BOT_TOKEN || ''; const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN || ''; const GSW_CONFIG = process.env.GSW_CONFIG || './config/default.config.json'; +const DBG = Boolean(process.env.DBG || false); class Watcher { constructor() { this.servers = []; @@ -47,8 +52,9 @@ class Watcher { this.servers.push(gs); } } - check() { - console.log('watcher checking...'); + async check() { + if (DBG) + console.log('watcher checking...'); const promises = []; for (const gs of this.servers) { promises.push(gs.update().then(() => { @@ -60,24 +66,20 @@ class Watcher { } })); } - return Promise.allSettled(promises).then(() => (0, game_server_1.saveDb)()); + await Promise.allSettled(promises); + await (0, game_server_1.saveDb)(); } } let loop = null; async function main() { - console.log('reading config...', GSW_CONFIG); + console.log('reading config', GSW_CONFIG); const buffer = await readFile(GSW_CONFIG); - console.log('buffer', buffer.toString()); - try { const conf = JSON.parse(buffer.toString()); const watcher = new Watcher(); await watcher.init(conf); console.log('starting loop...', REFRESH_TIME_MINUTES); loop = setInterval(async () => { await watcher.check(); }, 1000 * 60 * REFRESH_TIME_MINUTES); await watcher.check(); - } catch (e) { - console.error(e.message || e); - } // return watcher; } exports.main = main; diff --git a/src/watcher.ts b/src/watcher.ts index d6596e8..40e775d 100644 --- a/src/watcher.ts +++ b/src/watcher.ts @@ -5,10 +5,11 @@ import * as telegramBot from './telegram-bot'; import { promises as fs } from 'fs'; const { readFile } = fs; -const REFRESH_TIME_MINUTES = parseInt(process.env.REFRESH_TIME_MINUTES || '1', 10); +const REFRESH_TIME_MINUTES = parseInt(process.env.REFRESH_TIME_MINUTES || '5', 10); const DISCORD_BOT_TOKEN = process.env.DISCORD_BOT_TOKEN || ''; const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN || ''; const GSW_CONFIG = process.env.GSW_CONFIG || './config/default.config.json'; +const DBG = Boolean(process.env.DBG || false); export interface WatcherConfig { host: string; @@ -45,8 +46,8 @@ class Watcher { } } - check() { - console.log('watcher checking...'); + async check() { + if (DBG) console.log('watcher checking...'); const promises: Promise[] = []; for (const gs of this.servers) { @@ -61,13 +62,14 @@ class Watcher { })); } - return Promise.allSettled(promises).then(() => saveDb()); + await Promise.allSettled(promises); + await saveDb(); } } let loop = null; export async function main() { - console.log('reading config...', GSW_CONFIG); + console.log('reading config', GSW_CONFIG); const buffer = await readFile(GSW_CONFIG); const conf = JSON.parse(buffer.toString());