fix/retry-sending-failed-msgs (#1)
Some checks are pending
ptero-push / build (push) Waiting to run
Some checks are pending
ptero-push / build (push) Waiting to run
Reviewed-on: #1 Co-authored-by: ChrisChrome <chris@chrischro.me> Co-committed-by: ChrisChrome <chris@chrischro.me>
This commit is contained in:
parent
6706ab2809
commit
f865daaf3b
|
|
@ -297,5 +297,19 @@
|
|||
"required": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "devtest",
|
||||
"description": "[BOT OWNER ONLY] Test the bot with a sample message",
|
||||
"default_member_permissions": 0,
|
||||
"type": 1,
|
||||
"options": [
|
||||
{
|
||||
"name": "randstr",
|
||||
"description": "override random string in test message for testing",
|
||||
"type": 3,
|
||||
"required": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
102
index.js
102
index.js
|
|
@ -358,6 +358,14 @@ Image and product text are optional, but if they exist, they will be in the data
|
|||
var sent = {}
|
||||
|
||||
const handleDiscord = function (data, randStr) {
|
||||
/*
|
||||
Example data object:
|
||||
{
|
||||
type: 'iem-message',
|
||||
data: {
|
||||
channel: { room: 'botstalk', location: 'All_Bots_Talk' },
|
||||
*/
|
||||
|
||||
const rawBody = data.data.body;
|
||||
const text = data.data.productText;
|
||||
const product_id_raw = data.data.raw
|
||||
|
|
@ -448,59 +456,34 @@ const handleDiscord = function (data, randStr) {
|
|||
}
|
||||
}
|
||||
}, 10 * 60 * 1000);
|
||||
let errCount = 0;
|
||||
function sendMessage() {
|
||||
channel.send(thisMsg).catch((err) => {
|
||||
console.error(err);
|
||||
}).then((msg) => {
|
||||
if (msg.channel.type === Discord.ChannelType.GuildAnnouncement) msg.crosspost();
|
||||
}).catch(() => {
|
||||
console.log(`${colors.yellow("[WARN]")} Failed to send message to ${channel.guild.name}/${channel.name} (${channel.guild.id}/${channel.id})`);
|
||||
if (errCount < 3) {
|
||||
errCount++;
|
||||
setTimeout(sendMessage, 5000); // Retry after 5 seconds
|
||||
} else {
|
||||
const logChannel = discord.guilds.cache.get(config.discord.mainGuild).channels.cache.get(config.discord.logChannel);
|
||||
logChannel.send({
|
||||
embeds: [
|
||||
{
|
||||
title: "Failed to send message",
|
||||
description: `There is likely an issue with permissions. Please notify the server owner if possible.
|
||||
Guild: ${channel.guild.name} (${channel.guild.id})
|
||||
Channel: ${channel.name} (${channel.id})
|
||||
Guild Owner: <@${channel.guild.ownerId}> (${channel.guild.ownerId})
|
||||
description: `Failed to send message after 3 attempts, skipping for now. Channel may be deleted or bot may have lost access.\n
|
||||
Channel: ${channel.guild.name}/${channel.name} (${channel.guild.id}/${channel.id})
|
||||
Sub Info: \`\`\`json\n${JSON.stringify(row)}\`\`\``,
|
||||
color: 0xff0000
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
discord.users.fetch(channel.guild.ownerId).then((user) => {
|
||||
user.send({
|
||||
embeds: [
|
||||
{
|
||||
title: "Issue with your subscribed channel.",
|
||||
description: `There is likely an issue with permissions. Please check that I can send messages in <#${channel.id}>\nYour subscription has been removed, and you will need to resubscribe to get alerts.`,
|
||||
color: 0xff0000,
|
||||
fields: [
|
||||
{
|
||||
name: "Guild",
|
||||
value: `${channel.guild.name} (${channel.guild.id})`
|
||||
},
|
||||
{
|
||||
name: "Channel",
|
||||
value: `${channel.name} (${channel.id})`
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
]
|
||||
}).catch((err) => {
|
||||
console.log(`${colors.red("[ERROR]")} Failed to send message to ${channel.guild.ownerId}`);
|
||||
}).then(() => {
|
||||
if (channel.guildId == config.discord.mainGuild) return;
|
||||
db.run(`DELETE FROM channels WHERE channelid = ? AND iemchannel = ?`, [channel.id, fromChannel], (err) => {
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
}
|
||||
console.log(`${colors.cyan("[INFO]")} Deleted channel ${channel.id} from database`);
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
sendMessage()
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -548,8 +531,15 @@ const handleDiscord = function (data, randStr) {
|
|||
if (!filters.some((filter) => body.string.toLowerCase().includes(filter)) && !filters.some((filter) => text.toLowerCase().includes(filter))) return;
|
||||
thisMsg = JSON.parse(JSON.stringify(discordMsg));
|
||||
thisMsg.content = row.custommessage || null;
|
||||
let errCount = 0;
|
||||
|
||||
function sendMessage() {
|
||||
user.send(thisMsg).catch((err) => {
|
||||
console.log(`${colors.yellow("[WARN]")} Failed to send message to ${user.tag} (${user.id})`);
|
||||
if (errCount < 3) {
|
||||
errCount++;
|
||||
setTimeout(sendMessage, 5000); // Retry after 5 seconds
|
||||
} else {
|
||||
const logChannel = discord.guilds.cache.get(config.discord.mainGuild).channels.cache.get(config.discord.logChannel);
|
||||
logChannel.send({
|
||||
embeds: [
|
||||
|
|
@ -561,14 +551,11 @@ const handleDiscord = function (data, randStr) {
|
|||
color: 0xff0000
|
||||
}
|
||||
]
|
||||
})
|
||||
db.run(`DELETE FROM userAlerts WHERE userid = ?`, [row.userid], (err) => {
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
}
|
||||
console.log(`${colors.cyan("[INFO]")} Deleted all subs for user ${user.id} from database`);
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
sendMessage();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
@ -1429,13 +1416,42 @@ discord.on("interactionCreate", async (interaction) => {
|
|||
}]
|
||||
}
|
||||
bugReportChannel.send(report).then(() => {
|
||||
interaction.reply({ content: "Bug report sent! Thank you for your feedback.", embeds: report.embeds});
|
||||
interaction.reply({ content: "Bug report sent! Thank you for your feedback.", embeds: report.embeds });
|
||||
}).catch((err) => {
|
||||
interaction.reply({ content: "Failed to send bug report. Please try again later.", ephemeral: true });
|
||||
console.error(`${colors.red("[ERROR]")} Failed to send bug report: ${err.message}`);
|
||||
});
|
||||
break;
|
||||
|
||||
case "devtest":
|
||||
if (interaction.user.id !== config.discord.owner) return interaction.reply({ content: "You are not the bot owner.", ephemeral: true });
|
||||
// Test suite;
|
||||
let output = "Dev Test Started:\n";
|
||||
await interaction.reply({ content: output, ephemeral: true });
|
||||
//1. Add current channel to db with a fake room (discordtest)
|
||||
db.run(`INSERT INTO channels (channelid, iemchannel) VALUES (?, ?)`, [interaction.channel.id, "discordtest"], async (err) => {
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
await interaction.editReply({ content: output + "Failed to add channel to database.", ephemeral: true });
|
||||
return; // Stop the test. grr
|
||||
} else {
|
||||
output += "Added channel to database.\n";
|
||||
interaction.editReply({ content: output, ephemeral: true });
|
||||
|
||||
//2. directly trigger handleDiscord with a fake message for the fake room.
|
||||
|
||||
let randStr = interaction.options.getString("randstr") || Math.random().toString(36).substring(2, 15)
|
||||
handleDiscord(require("./testmsg.json"), randStr);
|
||||
output += "Triggered handleDiscord with test message.\n";
|
||||
interaction.editReply({ content: output, ephemeral: true });
|
||||
setTimeout(() => {
|
||||
// 3. At this point the dev needs to verify that the message sent, or didnt send if testing retry code. Just end at this point.
|
||||
output += "Dev Test Completed. Please verify the message was sent correctly.";
|
||||
interaction.editReply({ content: output, ephemeral: true });
|
||||
}, 2500);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Discord.InteractionType.MessageComponent:
|
||||
if (!interaction.customId) return;
|
||||
|
|
|
|||
35
testmsg.json
Normal file
35
testmsg.json
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"type": "iem-message",
|
||||
"data": {
|
||||
"channel": {
|
||||
"room": "discordtest",
|
||||
"location": "Discord Test Room"
|
||||
},
|
||||
"fromChannel": "discordtest",
|
||||
"event": {
|
||||
"text": "Severe Thunderstorm Warning",
|
||||
"priority": 4,
|
||||
"code": "SVR"
|
||||
},
|
||||
"body": {
|
||||
"string": "!!!DISCORD TEST MESSAGE!!! DMX issues Severe Thunderstorm Warning (SVR) for Polk County until Jun 12, 16:15 UTC ",
|
||||
"url": "https://mesonet.agron.iastate.edu/vtec/f/2026-O-NEW-KDMX-SV-W-0123_2026-06-12T1545Z"
|
||||
},
|
||||
"timestamp": "2026-06-12T15:45:00.000Z",
|
||||
"wmo": "WUUS53",
|
||||
"pil": "SVRDMX",
|
||||
"station": "KDMX",
|
||||
"product_data": {
|
||||
"timestamp": "2026-06-12T15:45:00.000Z",
|
||||
"originalTimestamp": "202606121545",
|
||||
"station": "KDMX",
|
||||
"wmo": "WUUS53",
|
||||
"pil": "SVRDMX"
|
||||
},
|
||||
"raw": "202606121545-KDMX-WUUS53-SVRDMX",
|
||||
"rawBody": "!!!DISCORD TEST MESSAGE!!! DMX issues Severe Thunderstorm Warning (SVR) for Polk County until Jun 12, 16:15 UTC https://mesonet.agron.iastate.edu/vtec/f/2026-O-NEW-KDMX-SV-W-0123_2026-06-12T1545Z",
|
||||
"image": "https://mesonet.agron.iastate.edu/plotting/auto/plot/208/network:WFO::wfo:DMX::year:2026::phenomenav:SV::significancev:W::etn:123::valid:2026-06-12%201545::_r:86.png",
|
||||
"productText": "!!!DISCORD TEST MESSAGE!!!\n\n796 \nWUUS53 KDMX 121545\nSVRDMX\nIAC153-121615-\n/O.NEW.KDMX.SV.W.0123.260612T1545Z-260612T1615Z/\nBULLETIN - IMMEDIATE BROADCAST REQUESTED\nSevere Thunderstorm Warning\nNational Weather Service Des Moines IA\n1045 AM CDT Fri Jun 12 2026\n\nThe National Weather Service in Des Moines has issued a\n\n* Severe Thunderstorm Warning for...\n Polk County in central Iowa...\n\n* Until 1115 AM CDT.\n\n* At 1045 AM CDT, a severe thunderstorm was located near Ankeny,\n moving east at 35 mph.\n\n* HAZARD...60 mph wind gusts and quarter size hail.\n\n$$\n"
|
||||
}
|
||||
}
|
||||
|
||||
33
wstest.js
Normal file
33
wstest.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
const WebSocket = require('ws');
|
||||
const config = require('./config.json');
|
||||
|
||||
const ws = new WebSocket(
|
||||
config.WS_URL || "wss://iembot.dev/iem",
|
||||
{
|
||||
headers: {
|
||||
"user-agent": "IEM-Alerter-DiscordBot/1.0 (+https://git.chrischro.me/iem-alerter/discord-bot; contact: me@ko4wal.radio)"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ws.on('open', () => {
|
||||
console.log('Connected to WebSocket');
|
||||
ws.send(JSON.stringify({ type: 'subscribe', channel: '*' }));
|
||||
});
|
||||
|
||||
ws.on('message', (rawData) => {
|
||||
try {
|
||||
const data = JSON.parse(rawData);
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
} catch (err) {
|
||||
console.log('Raw (non-JSON):', rawData.toString());
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
console.log('WebSocket connection closed.');
|
||||
});
|
||||
|
||||
ws.on('error', (err) => {
|
||||
console.error('WebSocket error:', err);
|
||||
});
|
||||
Loading…
Reference in a new issue