Merge subscribe and usersubscribe into just /subscribe

This commit is contained in:
Christopher Cookman 2024-05-21 20:21:08 -06:00
parent d64e402e16
commit 5075a5973d
Signed by: ChrisChrome
GPG key ID: A023A26E42C33A42
2 changed files with 191 additions and 231 deletions

View file

@ -16,78 +16,6 @@
"description": "Custom message to send when alert is sent", "description": "Custom message to send when alert is sent",
"type": 3, "type": 3,
"required": false "required": false
}
]
},
{
"name": "setmessage",
"description": "Set a custom message for a room",
"default_member_permissions": 0,
"options": [
{
"name": "room",
"description": "The room/WFO you want to set a message for",
"type": 3,
"required": true,
"autocomplete": false
},
{
"name": "message",
"description": "Custom message to send when alert is sent",
"type": 3,
"required": true
}
]
},
{
"name": "unsubscribe",
"description": "Unsubscribe from a weather.im room",
"default_member_permissions": 0,
"options": [
{
"name": "room",
"description": "The room/WFO you want to unsubscribe from",
"type": 3,
"required": true,
"autocomplete": false
}
]
},
{
"name": "list",
"description": "List all subscribed rooms for this channel",
"default_member_permissions": 0
},
{
"name": "about",
"description": "About this bot"
},
{
"name": "rooms",
"description": "List all available rooms"
},
{
"name": "setupall",
"description": "[OWNER ONLY] Setup channels in a category for all rooms",
"default_member_permissions": 0,
"type": 1
},
{
"name": "support",
"description": "Get support for the bot",
"type": 1
},
{
"name": "usersubscribe",
"description": "Subscribe to alerts for a room",
"type": 1,
"options": [
{
"name": "room",
"description": "The room/WFO you want to subscribe to",
"type": 3,
"required": true
}, },
{ {
"name": "filter", "name": "filter",
@ -136,21 +64,42 @@
] ]
}, },
{ {
"name": "userunsubscribe", "name": "unsubscribe",
"description": "Unsubscribe from alerts for a room", "description": "Unsubscribe from a weather.im room",
"type": 1, "default_member_permissions": 0,
"options": [ "options": [
{ {
"name": "room", "name": "room",
"description": "The room/WFO you want to unsubscribe from", "description": "The room/WFO you want to unsubscribe from",
"type": 3, "type": 3,
"required": true "required": true,
"autocomplete": false
} }
] ]
}, },
{ {
"name": "userlist", "name": "list",
"description": "List all subscribed alerts for this user", "description": "List all subscribed rooms for this channel",
"default_member_permissions": 0
},
{
"name": "about",
"description": "About this bot"
},
{
"name": "rooms",
"description": "List all available rooms"
},
{
"name": "setupall",
"description": "[OWNER ONLY] Setup channels in a category for all rooms",
"default_member_permissions": 0,
"type": 1
},
{
"name": "support",
"description": "Get support for the bot",
"type": 1 "type": 1
}, },
{ {

317
index.js
View file

@ -18,7 +18,8 @@ const sqlite3 = require("sqlite3").verbose();
const discord = new Discord.Client({ const discord = new Discord.Client({
intents: [ intents: [
"Guilds", "Guilds",
"GuildVoiceStates" "GuildVoiceStates",
"DirectMessages"
] ]
}); });
const { const {
@ -36,8 +37,8 @@ const db = new sqlite3.Database("channels.db", (err) => {
} }
console.log(`${colors.cyan("[INFO]")} Connected to the database`); console.log(`${colors.cyan("[INFO]")} Connected to the database`);
// Create tables if they dont exist // Create tables if they dont exist
db.run(`CREATE TABLE IF NOT EXISTS channels (channelid TEXT, iemchannel TEXT, custommessage TEXT)`); db.run(`CREATE TABLE IF NOT EXISTS channels (channelid TEXT, iemchannel TEXT, custommessage TEXT, minPriority INTEGER, "filter" TEXT, filterevt TEXT);`);
db.run(`CREATE TABLE IF NOT EXISTS userAlerts (userid TEXT, iemchannel TEXT, filter TEXT, filterEvt TEXT, minPriority INT)`); db.run(`CREATE TABLE IF NOT EXISTS userAlerts (userid TEXT, iemchannel TEXT, filter TEXT, filterEvt TEXT, minPriority INT, custommessage TEXT);`);
}); });
@ -398,60 +399,74 @@ xmpp.on("stanza", (stanza) => {
} }
] ]
} }
// Discord Channel Handling
// Run through the database, and find all channels that are linked to the iem channel db.all(`SELECT * FROM channels WHERE iemchannel = ?`, [fromChannel], (err, rows) => {
db.all(`SELECT channelid, custommessage FROM channels WHERE iemchannel = ?`, [fromChannel], (err, rows) => {
if (err) { if (err) {
console.error(err.message); console.error(err.message);
} }
if (!rows) return; // No channels to alert if (!rows) return; // No channels to alert
rows.forEach((row) => { rows.forEach((row) => {
const channel = discord.channels.cache.get(row.channelid); // Get Filters as arrays
if (!channel) {
// Delete the channel from the database and return
return db.run(`DELETE FROM channels WHERE channelid = ?`, [row.channelid], (err) => {
if (err) {
console.error(err.message);
}
console.log(`${colors.cyan("[INFO]")} Deleted channel ${row.channelid} from database`);
});
};
thisMsg = JSON.parse(JSON.stringify(discordMsg));
thisMsg.content = row.custommessage;
channel.send(thisMsg).then((msg) => {
if (msg.channel.type === Discord.ChannelType.GuildAnnouncement) msg.crosspost();
}).catch((err) => {
console.log(`${colors.red("[ERROR]")} Failed to send message to channel ${row.channelid}: ${err.message}`);
});
});
});
// User DM alert handling
db.all(`SELECT userid, filter, minPriority, filterEvt FROM userAlerts WHERE iemchannel = ?`, [fromChannel], (err, rows) => {
if (err) {
console.error(err.message);
}
if (!rows) return; // No users to alert
rows.forEach((row) => {
// Parse filterEvt
if (!row.filterEvt) row.filterEvt = ""; if (!row.filterEvt) row.filterEvt = "";
if (!row.filter) row.filter = "";
let filterEvt = row.filterEvt.split(","); let filterEvt = row.filterEvt.split(",");
let filters = row.filter.split(","); let filters = row.filter.split(",");
let user = discord.users.cache.get(row.userid);
if (!user) return; // Will handle better later
// If priority is less than the min priority, ignore it
if (evt.priority < row.minPriority) return; if (evt.priority < row.minPriority) return;
// If the event type is not in th filter, ignore it. Make sure filterEvt isnt null // If the event type is not in th filter, ignore it. Make sure filterEvt isnt null
if (!filterEvt[0]) filterEvt = []; if (!filterEvt[0]) filterEvt = [];
if (!filterEvt.includes(evt.code) && !filterEvt.length == 0) return; if (!filterEvt.includes(evt.code) && !filterEvt.length == 0) return;
let channel = discord.channels.cache.get(row.channelid);
if (!channel) return console.log(`${colors.red("[ERROR]")} Channel ${row.channelid} not found`);
// fetch the product text // fetch the product text
fetch(`https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id_raw}`).then((res) => { fetch(`https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id_raw}`).then((res) => {
// If neither the body nor the product text contains the filter, ignore it // If neither the body nor the product text contains the filter, ignore it
res.text().then((text) => { res.text().then((text) => {
if (!filters.some((filter) => body.includes(filter)) && !filters.some((filter) => text.includes(filter))) return; if (!filters.some((filter) => body.includes(filter)) && !filters.some((filter) => text.includes(filter))) return;
thisMsg = JSON.parse(JSON.stringify(discordMsg)); thisMsg = JSON.parse(JSON.stringify(discordMsg));
thisMsg.content = row.custommessage || null;
channel.send(thisMsg).catch((err) => {
console.error(err);
}).then((msg) => {
if (msg.channel.type === Discord.ChannelType.GuildAnnouncement) msg.crosspost();
});
});
});
});
});
// User DM alert handling
db.all(`SELECT * FROM userAlerts WHERE iemchannel = ?`, [fromChannel], (err, rows) => {
if (err) {
console.error(err.message);
}
if (!rows) return; // No users to alert
rows.forEach((row) => {
// Get Filters as arrays
if (!row.filterEvt) row.filterEvt = "";
if (!row.filter) row.filter = "";
let filterEvt = row.filterEvt.split(",");
let filters = row.filter.split(",");
// If priority is less than the min priority, ignore it
if (evt.priority < row.minPriority) return;
// If the event type is not in th filter, ignore it. Make sure filterEvt isnt null
if (!filterEvt[0]) filterEvt = [];
if (!filterEvt.includes(evt.code) && !filterEvt.length == 0) return;
let user = discord.users.cache.get(row.userid);
if (!user) return console.log(`${colors.red("[ERROR]")} User ${row.userid} not found`);
// fetch the product text
fetch(`https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id_raw}`).then((res) => {
// If neither the body nor the product text contains the filter, ignore it
res.text().then((text) => {
if (!filters.some((filter) => body.includes(filter)) && !filters.some((filter) => text.includes(filter))) return;
thisMsg = JSON.parse(JSON.stringify(discordMsg));
thisMsg.content = row.custommessage || null;
user.send(thisMsg).catch((err) => { user.send(thisMsg).catch((err) => {
console.error(err); console.error(err);
}); });
@ -668,11 +683,6 @@ discord.on('ready', async () => {
discord.on("interactionCreate", async (interaction) => { discord.on("interactionCreate", async (interaction) => {
switch (interaction.type) { switch (interaction.type) {
case Discord.InteractionType.ApplicationCommand: case Discord.InteractionType.ApplicationCommand:
if (!interaction.channel) return interaction.reply({ content: "This command can only be run in a text channel", ephemeral: true });
if (interaction.channel.type !== Discord.ChannelType.GuildText && interaction.channel.type !== Discord.ChannelType.GuildAnnouncement) {
interaction.reply({ content: "This command can only be run in a text channel", ephemeral: true });
return;
}
switch (interaction.commandName) { switch (interaction.commandName) {
case "subscribe": case "subscribe":
room = getWFOroom(interaction.options.getString("room")); room = getWFOroom(interaction.options.getString("room"));
@ -680,17 +690,23 @@ discord.on("interactionCreate", async (interaction) => {
interaction.reply({ content: "Invalid room", ephemeral: true }); interaction.reply({ content: "Invalid room", ephemeral: true });
return; return;
} }
if (interaction.options.getString("filter")) {
filter = interaction.options.getString("filter").toLowerCase();
} else {
filter = "";
}
minPriority = interaction.options.getInteger("minpriority");
filterEvt = interaction.options.getString("filterevt") || null;
message = interaction.options.getString("message") || null; message = interaction.options.getString("message") || null;
// Check that the channel isn't already subbed to the room if (interaction.inGuild()) {
db.get(`SELECT * FROM channels WHERE channelid = ? AND iemchannel = ?`, [interaction.channel.id, room], (err, row) => { db.get(`SELECT * FROM channels WHERE channelid = ? AND iemchannel = ?`, [interaction.channel.id, room], (err, row) => {
if (err) { if (err) {
console.error(err.message); console.error(err.message);
interaction.reply({ content: "Failed to subscribe to room", ephemeral: true }); interaction.reply({ content: "Failed to subscribe to room", ephemeral: true });
} else if (row) { } else if (row) {
return interaction.reply({ content: `Already subscribed to \`${getWFOByRoom(room).location}\``, ephemeral: true }); return interaction.reply({ content: `Already subscribed to \`${getWFOByRoom(room).location}\`\nIf you want to update a subscribtion, please unsubscribe and resubscribe. This will be made a command eventually.`, ephemeral: true });
} else { }
db.run(`INSERT INTO channels (channelid, iemchannel, custommessage, filter, filterevt, minPriority) VALUES (?, ?, ?, ? ,? ,?)`, [interaction.channel.id, room, message, filter, filterEvt, minPriority], (err) => {
db.run(`INSERT INTO channels (channelid, iemchannel, custommessage) VALUES (?, ?, ?)`, [interaction.channel.id, room, message], (err) => {
if (err) { if (err) {
console.error(err.message); console.error(err.message);
interaction.reply({ content: "Failed to subscribe to room", ephemeral: true }); interaction.reply({ content: "Failed to subscribe to room", ephemeral: true });
@ -698,8 +714,25 @@ discord.on("interactionCreate", async (interaction) => {
interaction.reply({ content: `Subscribed to \`${getWFOByRoom(room).location}\``, ephemeral: true }); interaction.reply({ content: `Subscribed to \`${getWFOByRoom(room).location}\``, ephemeral: true });
} }
}); });
} });
}); } else { // We're in a DM
db.get(`SELECT * FROM userAlerts WHERE userid = ? AND iemchannel = ?`, [interaction.user.id, room], (err, row) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to subscribe to room", ephemeral: true });
} else if (row) {
return interaction.reply({ content: `Already subscribed to \`${getWFOByRoom(room).location}\`\nIf you want to update a subscribtion, please unsubscribe and resubscribe. This will be made a command eventually.`, ephemeral: true });
}
db.run(`INSERT INTO userAlerts (userid, iemchannel, custommessage, filter, filterEvt, minPriority) VALUES (?, ?, ?, ? ,?, ?)`, [interaction.user.id, room, message, filter, filterEvt, minPriority], (err) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to subscribe to room", ephemeral: true });
} else {
interaction.reply({ content: `Subscribed to \`${getWFOByRoom(room).location}\``, ephemeral: true });
}
});
});
}
break; break;
case "unsubscribe": case "unsubscribe":
// Check that the room is valid // Check that the room is valid
@ -708,58 +741,92 @@ discord.on("interactionCreate", async (interaction) => {
interaction.reply({ content: "Invalid room", ephemeral: true }); interaction.reply({ content: "Invalid room", ephemeral: true });
return; return;
} }
// Check that the channel is subbed to the room if (interaction.inGuild()) {
db.get(`SELECT * FROM channels WHERE channelid = ? AND iemchannel = ?`, [interaction.channel.id, room], (err, row) => { // Check if subbed
if (err) { db.get(`SELECT * FROM channels WHERE channelid = ? AND iemchannel = ?`, [interaction.channel.id, room], (err, row) => {
console.error(err.message); if (err) {
interaction.reply({ content: "Failed to unsubscribe from room", ephemeral: true }); console.error(err.message);
} else if (!row) { interaction.reply({ content: "Failed to unsubscribe from room", ephemeral: true });
return interaction.reply({ content: `Not subscribed to \`${getWFOByRoom(room).location}\``, ephemeral: true }); }
} else { if (!row) {
return interaction.reply({ content: `Not subscribed to \`${getWFOByRoom(room).location}\``, ephemeral: true });
}
db.run(`DELETE FROM channels WHERE channelid = ? AND iemchannel = ?`, [interaction.channel.id, room], (err) => { db.run(`DELETE FROM channels WHERE channelid = ? AND iemchannel = ?`, [interaction.channel.id, room], (err) => {
if (err) { if (err) {
console.error(err.message); console.error(err.message);
interaction.reply({ content: "Failed to unsubscribe from room", ephemeral: true }); interaction.reply({ content: "Failed to unsubscribe from room", ephemeral: true });
} else {
interaction.reply({ content: `Unsubscribed from \`${getWFOByRoom(room).location}\``, ephemeral: true });
} }
interaction.reply({ content: `Unsubscribed from \`${getWFOByRoom(room).location}\``, ephemeral: true });
}); });
} });
}); } else {
db.get(`SELECT * FROM userAlerts WHERE userid = ? AND iemchannel = ?`, [interaction.user.id, room], (err, row) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to unsubscribe from room", ephemeral: true });
}
if (!row) {
return interaction.reply({ content: `Not subscribed to \`${getWFOByRoom(room).location}\``, ephemeral: true });
}
db.run(`DELETE FROM userAlerts WHERE userid = ? AND iemchannel = ?`, [interaction.user.id, room], (err) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to unsubscribe from room", ephemeral: true });
}
interaction.reply({ content: `Unsubscribed from \`${getWFOByRoom(room).location}\``, ephemeral: true });
});
});
}
break; break;
case "list": case "list":
db.all(`SELECT iemchannel, custommessage FROM channels WHERE channelid = ?`, [interaction.channel.id], (err, rows) => { // List all the subscribed rooms
if (err) { if (interaction.inGuild()) {
console.error(err.message); db.all(`SELECT * FROM channels WHERE channelid = ?`, [interaction.channel.id], (err, rows) => {
interaction.reply({ content: "Failed to list subscribed rooms", ephemeral: true }); if (err) {
} else { console.error(err.message);
let message = ""; interaction.reply({ content: "Failed to get subscribed rooms", ephemeral: true });
rows.forEach((row) => {
message += `\`${row.iemchannel}\`: ${getWFOByRoom(row.iemchannel).location || "Unknown"} Custom Message: \`${row.custommessage || "None"}\`\n`;
});
if (message === "") {
message = "No subscribed rooms";
} }
interaction.reply({ content: message, ephemeral: true }); if (!rows) {
} return interaction.reply({ content: "No subscribed rooms", ephemeral: true });
}); }
break; let roomList = [];
case "setmessage": rows.forEach((row) => {
room = getWFOroom(interaction.options.getString("room")); roomList.push({
if (!iem.find((channel) => channel.jid.split("@")[0] === room)) { name: `${row.iemchannel}: ${getWFOByRoom(row.iemchannel).location}`,
interaction.reply({ content: "Invalid room", ephemeral: true }); value: `Message: \`\`${row.custommessage || "None"}\`\`\nFilter: \`\`${row.filter || "None"}\`\`\nEvent Filter: \`\`${row.filterEvt || "None"}\`\`\nMin Priority: \`\`${row.minPriority || "None"}\`\``
return; });
});
const embed = {
title: "Subscribed Rooms",
fields: roomList,
color: 0x00ff00
}
interaction.reply({ embeds: [embed], ephemeral: true });
});
} else {
db.all(`SELECT * FROM userAlerts WHERE userid = ?`, [interaction.user.id], (err, rows) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to get subscribed rooms", ephemeral: true });
}
if (!rows) {
return interaction.reply({ content: "No subscribed rooms", ephemeral: true });
}
let roomList = [];
rows.forEach((row) => {
roomList.push({
name: `${row.iemchannel}: ${getWFOByRoom(row.iemchannel).location}`,
value: `Message: \`\`${row.custommessage || "None"}\`\`\nFilter: \`\`${row.filter || "None"}\`\`\nEvent Filter: \`\`${row.filterEvt || "None"}\`\`\nMin Priority: \`\`${row.minPriority || "None"}\`\``
});
});
const embed = {
title: "Subscribed Rooms",
fields: roomList,
color: 0x00ff00
}
interaction.reply({ embeds: [embed], ephemeral: true });
});
} }
message = interaction.options.getString("message");
db.run(`UPDATE channels SET custommessage = ? WHERE channelid = ? AND iemchannel = ?`, [message, interaction.channel.id, room], (err) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to set message", ephemeral: true });
} else {
interaction.reply({ content: `Message for ${getWFOByRoom(room).location} to \`${message}\``, ephemeral: true });
}
});
break; break;
case "about": case "about":
// Send an embed showing info about the bot, including number of guilds, number of subscribed rooms, etc // Send an embed showing info about the bot, including number of guilds, number of subscribed rooms, etc
@ -976,62 +1043,6 @@ discord.on("interactionCreate", async (interaction) => {
interaction.reply({ content: "Failed to set volume", ephemeral: true }); interaction.reply({ content: "Failed to set volume", ephemeral: true });
} }
break; break;
case "usersubscribe":
room = getWFOroom(interaction.options.getString("room"));
if (!iem.find((channel) => channel.jid.split("@")[0] === room)) {
interaction.reply({ content: "Invalid room", ephemeral: true });
return;
}
if (interaction.options.getString("filter")) {
filter = interaction.options.getString("filter").toLowerCase();
} else {
filter = "";
}
minPriority = interaction.options.getInteger("minpriority");
filterEvt = interaction.options.getString("filterevt") || null;
db.run(`INSERT INTO userAlerts (userid, iemchannel, filter, minPriority, filterEvt) VALUES (?, ?, ?, ?, ?)`, [interaction.user.id, room, filter, minPriority, filterEvt], (err) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to subscribe to alerts", ephemeral: true });
} else {
interaction.reply({ content: `Subscribed to alerts for \`${getWFOByRoom(room).location}\``, ephemeral: true });
}
});
break;
case "userunsubscribe":
room = getWFOroom(interaction.options.getString("room"));
if (!iem.find((channel) => channel.jid.split("@")[0] === room)) {
interaction.reply({ content: "Invalid room", ephemeral: true });
return;
}
db.run(`DELETE FROM userAlerts WHERE userid = ? AND iemchannel = ?`, [interaction.user.id, room], (err) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to unsubscribe from alerts", ephemeral: true });
} else {
interaction.reply({ content: `Unsubscribed from alerts for \`${getWFOByRoom(room).location}\``, ephemeral: true });
}
});
break;
case "userlist":
db.all(`SELECT iemchannel, filter, minPriority, filterEvt FROM userAlerts WHERE userid = ?`, [interaction.user.id], (err, rows) => {
if (err) {
console.error(err.message);
interaction.reply({ content: "Failed to list subscribed alerts", ephemeral: true });
} else {
let message = "";
rows.forEach((row) => {
message += `\`${row.iemchannel}\`: ${getWFOByRoom(row.iemchannel).location || "Unknown"} Filter: \`${row.filter}\` Min Priority: \`${row.minPriority}\` Filter EVT: \`${row.filterEvt}\`\n`;
}
);
if (message === "") {
message = "No subscribed alerts";
}
interaction.reply({ content: message, ephemeral: true });
}
});
break;
case "outlook": case "outlook":
day = interaction.options.getInteger("day"); day = interaction.options.getInteger("day");
type = interaction.options.getString("type"); type = interaction.options.getString("type");