Skip to content

Commit d16b6dc

Browse files
committed
Add 'gman who is on valheim' command, reposting the status embed
1 parent 630521c commit d16b6dc

File tree

1 file changed

+149
-51
lines changed

1 file changed

+149
-51
lines changed

gateway/src/routes/messages.js

Lines changed: 149 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ const {
2121
let mainChannel;
2222
let 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+
2438
client.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(/(?:(?:\bwho.*on\w*\b)|(?:\bserver status (?:of\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

140199
router.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

154213
let lastNickname = "";
155214
async 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

217278
const 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

275373
module.exports = {

0 commit comments

Comments
 (0)