@@ -21,6 +21,20 @@ const {
2121let mainChannel ;
2222let channels = { } ;
2323
24+ async function getMainChannel ( ) {
25+ if ( mainChannel ) {
26+ return mainChannel ;
27+ }
28+ return new Promise ( function ( resolve , reject ) {
29+ ( function waitFor ( ) {
30+ if ( mainChannel ) {
31+ return resolve ( mainChannel ) ;
32+ }
33+ setTimeout ( waitFor , 100 ) ;
34+ } ) ( ) ;
35+ } ) ;
36+ }
37+
2438client . on ( "ready" , async ( ) => {
2539 console . log ( `Discord logged in as ${ client . user . tag } !` ) ;
2640 try {
@@ -114,6 +128,51 @@ client.on("message", async (msg) => {
114128 ) ;
115129 msg . reply ( `Next map queued: ${ nextMapMatch [ 1 ] } ` ) ;
116130 }
131+ const whoseOnServerMatch = msg . content . match ( / (?: (?: \b w h o .* o n \w * \b ) | (?: \b s e r v e r s t a t u s (?: o f \b ) ? ) ) ? ( .* ?) \? ? $ / ) ;
132+ if ( whoseOnServerMatch ) {
133+ async function repostGameInfo ( gameId ) {
134+ if ( gameMessageMeta [ gameId ] && gameMessageMeta [ gameId ] . message ) {
135+ await gameMessageMeta [ gameId ] . message . delete ( ) ;
136+ delete gameMessageMeta [ gameId ] . message ;
137+ }
138+ pollGameHealth ( knownGameApis [ gameId ] ) ;
139+ }
140+ const searchTerm = whoseOnServerMatch ? whoseOnServerMatch [ 1 ] . toLowerCase ( ) : '' ;
141+ if ( ! searchTerm || searchTerm . includes ( 'online' ) || searchTerm . includes ( 'active' ) ) {
142+ // hit all online ones
143+ Object . entries ( gameMessageMeta ) . map ( ( [ id , meta ] ) => {
144+ if ( meta . message && meta . lastResponse && meta . lastResponse . playerCount > 0 ) {
145+ repostGameInfo ( id )
146+ }
147+ } )
148+ }
149+ else if ( whoseOnServerMatch [ 1 ] ) {
150+ let foundGameId ;
151+ for ( let gameId in knownGameApis ) {
152+ if (
153+ gameId . toLowerCase ( ) == searchTerm ||
154+ knownGameApis [ gameId ] . name . toLowerCase ( ) == searchTerm
155+ ) {
156+ foundGameId = gameId ;
157+ break ;
158+ }
159+ }
160+ if ( ! foundGameId ) {
161+ for ( let gameId in knownGameApis ) {
162+ if (
163+ gameId . toLowerCase ( ) . includes ( searchTerm ) ||
164+ knownGameApis [ gameId ] . name . toLowerCase ( ) . includes ( searchTerm )
165+ ) {
166+ foundGameId = gameId ;
167+ break ;
168+ }
169+ }
170+ }
171+ if ( foundGameId ) {
172+ await repostGameInfo ( foundGameId ) ;
173+ }
174+ }
175+ }
117176 }
118177 if ( msgContainsGman || msg . channel . id === mainChannel . id ) {
119178 debugLog (
@@ -139,7 +198,7 @@ client
139198
140199router . post ( "/" , async function ( req , response ) {
141200 sendMessage ( req . body . nick , req . body . message , req . body . channel ) . catch ( ( err ) =>
142- console . log (
201+ console . warn (
143202 `Discord: failed to send message ${ req . body . nick } : ${ req . body . message } because: ${ err } `
144203 )
145204 ) ;
@@ -153,7 +212,9 @@ router.get("/send", async function (req, response) {
153212
154213let lastNickname = "" ;
155214async function sendMessage ( nickname , message , channelId ) {
156- const channel = channelId ? await getChannel ( channelId ) : mainChannel ;
215+ const channel = channelId
216+ ? await getChannel ( channelId )
217+ : await getMainChannel ( ) ;
157218 debugLog ( `Discord sending ${ nickname } : ${ message } ` ) ;
158219 if ( ! channel ) {
159220 console . warn ( "Discord: Not connected to channel" , channelId ) ;
@@ -215,61 +276,98 @@ function initWebsocketListener(httpServer) {
215276}
216277
217278const gameMessageMeta = { } ;
218- function initPlayerStatusPoller ( knownGameApis ) {
219- async function pollGameHealth ( { id, game, name, url } ) {
220- if ( id === "valheim-zach" ) {
221- return ;
222- }
223- if ( ! gameMessageMeta [ id ] ) {
224- gameMessageMeta [ id ] = { } ;
279+ let knownGameApis = { } ;
280+ async function pollGameHealth ( { id, game, name, url } ) {
281+ if ( id === "valheim-zach" ) {
282+ return ;
283+ }
284+ if ( ! gameMessageMeta [ id ] ) {
285+ gameMessageMeta [ id ] = { } ;
286+ }
287+ const { data } = await axios ( {
288+ method : "GET" ,
289+ url : `${ url } /control` ,
290+ timeout : 8000 ,
291+ } ) ;
292+ if ( data . status === "running" ) {
293+ const players = data . players || [ ] ;
294+ const embed = new Discord . MessageEmbed ( )
295+ . setTitle ( `${ name } is running` )
296+ . setDescription ( data . connectUrl || "" )
297+ . setThumbnail ( `https://gmanman.nebtown.info/icons/${ game } .png` ) ;
298+ if ( data . playerCount > 0 ) {
299+ embed . addField (
300+ `Players: ${ data . playerCount } ` ,
301+ players
302+ . map ( ( { name } ) => name )
303+ . filter ( Boolean )
304+ . join ( ", " ) || "-" ,
305+ true
306+ ) ;
225307 }
226- const { data } = await axios ( {
227- method : "GET" ,
228- url : `${ url } /control` ,
229- timeout : 8000 ,
230- } ) ;
231- if ( data . status === "running" ) {
232- console . log ( "found running" , data ) ;
233- const players = data . players || [ ] ;
234- const embed = new Discord . MessageEmbed ( )
235- . setTitle ( `${ name } is running` )
236- . setDescription ( data . connectUrl || "" )
237- . setThumbnail ( `https://gmanman.nebtown.info/icons/${ game } .png` ) ;
238- if ( data . playerCount > 0 ) {
239- embed . addField (
240- `Players: ${ data . playerCount } ` ,
241- players
242- . map ( ( { name } ) => name )
243- . filter ( Boolean )
244- . join ( ", " ) || "-" ,
245- true
308+ try {
309+ if ( ! gameMessageMeta [ id ] . message ) {
310+ gameMessageMeta [ id ] . message = await sendMessage ( "" , embed ) ;
311+ } else {
312+ gameMessageMeta [ id ] . message = await gameMessageMeta [ id ] . message . edit (
313+ embed
246314 ) ;
247315 }
248- try {
249- if ( ! gameMessageMeta [ id ] . message ) {
250- gameMessageMeta [ id ] . message = await sendMessage ( "" , embed ) ;
251- } else {
252- gameMessageMeta [ id ] . message = await gameMessageMeta [ id ] . message . edit (
253- embed
316+ } catch ( err ) {
317+ console . error ( "Failed to edit message: " , err ) ;
318+ }
319+ } else if ( [ "stopping" , "stopped" ] . includes ( data . status ) ) {
320+ if ( gameMessageMeta [ id ] . message ) {
321+ const embed = new Discord . MessageEmbed ( ) . setTitle ( `${ name } was running` ) ;
322+ await gameMessageMeta [ id ] . message . edit ( embed ) ;
323+ delete gameMessageMeta [ id ] . message ;
324+ }
325+ }
326+ gameMessageMeta [ id ] . lastResponse = data ;
327+ }
328+ const savedMessagesFilePath = "/tmp/gmanman-gateway-known-messages.json" ;
329+ async function fileExists ( path ) {
330+ return ! ! ( await fs . promises . stat ( path ) . catch ( ( e ) => false ) ) ;
331+ }
332+ async function initPlayerStatusPoller ( _knownGameApis ) {
333+ knownGameApis = _knownGameApis ;
334+
335+ try {
336+ const messagesStr =
337+ ( await fileExists ( savedMessagesFilePath ) ) &&
338+ ( await fs . promises . readFile ( savedMessagesFilePath ) ) ;
339+ if ( messagesStr ) {
340+ const storedMessages = JSON . parse ( messagesStr ) ;
341+ const mainChannel = await getMainChannel ( ) ;
342+ await Promise . all (
343+ Object . keys ( storedMessages ) . map ( async ( id ) => {
344+ if ( ! gameMessageMeta [ id ] ) {
345+ gameMessageMeta [ id ] = { } ;
346+ }
347+ gameMessageMeta [ id ] . message = await mainChannel . messages . fetch (
348+ storedMessages [ id ]
254349 ) ;
255- }
256- } catch ( err ) {
257- console . error ( "Failed to edit message: " , err ) ;
258- }
259- } else if ( [ "stopping" , "stopped" ] . includes ( data . status ) ) {
260- if ( gameMessageMeta [ id ] . message ) {
261- const embed = new Discord . MessageEmbed ( ) . setTitle (
262- `${ name } was running`
263- ) ;
264- await gameMessageMeta [ id ] . message . edit ( embed ) ;
265- delete gameMessageMeta [ id ] . message ;
266- }
350+ } )
351+ ) ;
267352 }
268- gameMessageMeta [ id ] . lastStatus = data . status ;
353+ } catch ( e ) {
354+ console . warn ( "initPlayerStatusPoller reading storedMessages error:" , e ) ;
269355 }
270- setInterval ( ( ) => {
271- Object . values ( knownGameApis ) . map ( pollGameHealth ) ;
272- } , 10000 ) ;
356+
357+ setInterval ( async ( ) => {
358+ await Promise . all ( Object . values ( knownGameApis ) . map ( pollGameHealth ) ) ;
359+ await fs . promises . writeFile (
360+ savedMessagesFilePath ,
361+ JSON . stringify (
362+ Object . keys ( gameMessageMeta ) . reduce ( ( carry , id ) => {
363+ if ( gameMessageMeta [ id ] . message ) {
364+ carry [ id ] = gameMessageMeta [ id ] . message . id ;
365+ }
366+ return carry ;
367+ } , { } )
368+ )
369+ ) ;
370+ } , 8000 ) ;
273371}
274372
275373module . exports = {
0 commit comments