From 4ca2435359297fba86e63b8e8d858af5bd175527 Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Sun, 19 May 2024 10:06:21 -0600 Subject: [PATCH 1/7] Impliment /outlook --- data/outlook.json | 22 ++++++ index.js | 171 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 157 insertions(+), 36 deletions(-) create mode 100644 data/outlook.json diff --git a/data/outlook.json b/data/outlook.json new file mode 100644 index 0000000..6e72a92 --- /dev/null +++ b/data/outlook.json @@ -0,0 +1,22 @@ +{ + "storm": [ + "https://www.spc.noaa.gov/products/outlook/day1otlk.gif", + "https://www.spc.noaa.gov/products/outlook/day2otlk.gif", + "https://www.spc.noaa.gov/products/outlook/day3otlk.gif", + "https://www.spc.noaa.gov/products/exper/day4-8/day4prob.gif", + "https://www.spc.noaa.gov/products/exper/day4-8/day5prob.gif", + "https://www.spc.noaa.gov/products/exper/day4-8/day6prob.gif", + "https://www.spc.noaa.gov/products/exper/day4-8/day7prob.gif", + "https://www.spc.noaa.gov/products/exper/day4-8/day8prob.gif" + ], + "fire": [ + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day1otlk_fire.gif", + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day2otlk_fire.gif", + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day3otlk_fire.gif", + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day4otlk_fire.gif", + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day5otlk_fire.gif", + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day6otlk_fire.gif", + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day7otlk_fire.gif", + "https://www.spc.noaa.gov/products/exper/fire_wx/imgs/day8otlk_fire.gif" + ] +} \ No newline at end of file diff --git a/index.js b/index.js index ddb0ed3..f7108f4 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ const config = require("./config.json"); const wfos = require("./data/wfos.json"); const blacklist = require("./data/blacklist.json"); const events = require("./data/events.json"); +const outlookURLs = require("./data/outlook.json"); const { client, xml } = require("@xmpp/client"); const fetch = require("node-fetch"); const html = require("html-entities") @@ -39,6 +40,15 @@ const db = new sqlite3.Database("channels.db", (err) => { // Random funcs +function toTitleCase(str) { + return str.replace( + /\w\S*/g, + function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + } + ); +} + const parseProductID = function (product_id) { const [timestamp, station, wmo, pil] = product_id.split("-"); return { @@ -346,7 +356,7 @@ xmpp.on("stanza", (stanza) => { // Send discord msg let embed = { - description: ` ${bodyData.string}`, + description: ` ${bodyData.string}`, color: parseInt(config.priorityColors[evt.priority].replace("#", ""), 16) || 0x000000, timestamp: product_id.timestamp, footer: { @@ -691,6 +701,69 @@ discord.on('ready', async () => { "name": "userlist", "description": "List all subscribed alerts for this user", "type": 1 + }, + { + "name": "outlook", + "description": "Get day 1-8 storm or fire outlook from the SPC", + "type": 1, + "options": [ + { + "name": "day", + "description": "Day of outlook", + "type": 4, + "required": true, + "choices": [ + { + "name": "Day 1", + "value": 0 + }, + { + "name": "Day 2", + "value": 1 + }, + { + "name": "Day 3", + "value": 2 + }, + { + "name": "Day 4", + "value": 3 + }, + { + "name": "Day 5", + "value": 4 + }, + { + "name": "Day 6", + "value": 5 + }, + { + "name": "Day 7", + "value": 6 + }, + { + "name": "Day 8", + "value": 7 + } + ] + }, + { + "name": "type", + "description": "Type of outlook", + "type": 3, + "required": true, + "choices": [ + { + "name": "Fire", + "value": "fire" + }, + { + "name": "Storm", + "value": "storm" + } + ] + } + ] } ]; @@ -781,7 +854,7 @@ discord.on('ready', async () => { }); }; }); - }); + }); }); discord.on("interactionCreate", async (interaction) => { @@ -976,7 +1049,7 @@ discord.on("interactionCreate", async (interaction) => { chunks.push(iem.slice(i, i + chunkSize)); console.log(iem.slice(i, i + chunkSize)) } - + chunks.forEach((chunk, index) => { @@ -1147,42 +1220,68 @@ discord.on("interactionCreate", async (interaction) => { } }); break; - } - break; - case Discord.InteractionType.MessageComponent: - if (interaction.customId) { - const product_id = interaction.customId; - const url = `https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id}`; - await interaction.deferReply({ ephemeral: true }); - fetch(url).then((res) => { - if (res.status !== 200) { - interaction.reply({ content: "Failed to get product text", ephemeral: true }); - return; - } - // Retruns raw text, paginate it into multiple embeds if needed - res.text().then(async (text) => { - const pages = text.match(/[\s\S]{1,2000}(?=\n|$)/g); - // const embeds = pages.map((page, ind) => ({ - // title: `Product Text for ${product_id} Pg ${ind + 1}/${pages.length}`, - // description: `\`\`\`${page}\`\`\``, - // color: 0x00ff00 - // })); - const messages = pages.map((page, ind) => { - return `\`\`\`${page}\`\`\`` - }) - messages.forEach(async (message) => { - interaction.followUp({ content: message, ephemeral: true }); - }) + case "outlook": + day = interaction.options.getInteger("day"); + type = interaction.options.getString("type"); + if (day < 0 || day > 7) return interaction.reply({ content: "Invalid day", ephemeral: true }); + if (type !== "fire" && type !== "storm") return interaction.reply({ content: "Invalid type", ephemeral: true }); + url = outlookURLs[type][day]; + await interaction.deferReply({ ephemeral: true }); + fetch(url).then((res) => { + if (res.status !== 200) { + interaction.editReply({ content: "Failed to get outlook", ephemeral: true }); + return; + } + // Returns image, send embed with image as attachment (we need to bypass discord cache) + res.buffer().then(async (buffer) => { + const attachment = new Discord.MessageAttachment(buffer, `${type}_${day}.png`); + const embed = { + title: `${toTitleCase(type)} Outlook Day ${day}`, + image: { + url: `attachment://${type}_${day}.png` + }, + color: 0x00ff00 + } + interaction.editReply({ embeds: [embed], files: [attachment] }); + }); + }).catch((err) => { + interaction.editReply({ content: "Failed to get outlook", ephemeral: true }); }); - }).catch((err) => { - interaction.reply({ content: "Failed to get product text", ephemeral: true }); - console.log(`${colors.red("[ERROR]")} Failed to get product text: ${err.message}`); - }); + break; + case Discord.InteractionType.MessageComponent: + if (interaction.customId) { + const product_id = interaction.customId; + const url = `https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id}`; + await interaction.deferReply({ ephemeral: true }); + fetch(url).then((res) => { + if (res.status !== 200) { + interaction.reply({ content: "Failed to get product text", ephemeral: true }); + return; + } + // Retruns raw text, paginate it into multiple embeds if needed + res.text().then(async (text) => { + const pages = text.match(/[\s\S]{1,2000}(?=\n|$)/g); + // const embeds = pages.map((page, ind) => ({ + // title: `Product Text for ${product_id} Pg ${ind + 1}/${pages.length}`, + // description: `\`\`\`${page}\`\`\``, + // color: 0x00ff00 + // })); + const messages = pages.map((page, ind) => { + return `\`\`\`${page}\`\`\`` + }) + messages.forEach(async (message) => { + interaction.followUp({ content: message, ephemeral: true }); + }) + }); + }).catch((err) => { + interaction.reply({ content: "Failed to get product text", ephemeral: true }); + console.log(`${colors.red("[ERROR]")} Failed to get product text: ${err.message}`); + }); + } + break; } - break; - } -}); + }); discord.on("guildCreate", (guild) => { // Get the main guild From fdd435c44af69e53ef97a4ce7d8a96d591391447 Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Sun, 19 May 2024 10:12:57 -0600 Subject: [PATCH 2/7] Whoops --- index.js | 66 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/index.js b/index.js index f7108f4..1632b75 100644 --- a/index.js +++ b/index.js @@ -1248,40 +1248,42 @@ discord.on("interactionCreate", async (interaction) => { interaction.editReply({ content: "Failed to get outlook", ephemeral: true }); }); break; - case Discord.InteractionType.MessageComponent: - if (interaction.customId) { - const product_id = interaction.customId; - const url = `https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id}`; - await interaction.deferReply({ ephemeral: true }); - fetch(url).then((res) => { - if (res.status !== 200) { - interaction.reply({ content: "Failed to get product text", ephemeral: true }); - return; - } - // Retruns raw text, paginate it into multiple embeds if needed - res.text().then(async (text) => { - const pages = text.match(/[\s\S]{1,2000}(?=\n|$)/g); - // const embeds = pages.map((page, ind) => ({ - // title: `Product Text for ${product_id} Pg ${ind + 1}/${pages.length}`, - // description: `\`\`\`${page}\`\`\``, - // color: 0x00ff00 - // })); - const messages = pages.map((page, ind) => { - return `\`\`\`${page}\`\`\`` - }) - messages.forEach(async (message) => { - interaction.followUp({ content: message, ephemeral: true }); - }) - }); - }).catch((err) => { - interaction.reply({ content: "Failed to get product text", ephemeral: true }); - console.log(`${colors.red("[ERROR]")} Failed to get product text: ${err.message}`); - }); - } - break; } + case Discord.InteractionType.MessageComponent: + if (interaction.customId) { + const product_id = interaction.customId; + const url = `https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id}`; + await interaction.deferReply({ ephemeral: true }); + fetch(url).then((res) => { + if (res.status !== 200) { + interaction.reply({ content: "Failed to get product text", ephemeral: true }); + return; + } + // Retruns raw text, paginate it into multiple embeds if needed + res.text().then(async (text) => { + const pages = text.match(/[\s\S]{1,2000}(?=\n|$)/g); + // const embeds = pages.map((page, ind) => ({ + // title: `Product Text for ${product_id} Pg ${ind + 1}/${pages.length}`, + // description: `\`\`\`${page}\`\`\``, + // color: 0x00ff00 + // })); + const messages = pages.map((page, ind) => { + return `\`\`\`${page}\`\`\`` + }) + messages.forEach(async (message) => { + interaction.followUp({ content: message, ephemeral: true }); + }) + }); + }).catch((err) => { + interaction.reply({ content: "Failed to get product text", ephemeral: true }); + console.log(`${colors.red("[ERROR]")} Failed to get product text: ${err.message}`); + }); + } + break; + } - }); + +}); discord.on("guildCreate", (guild) => { // Get the main guild From 14faf62e909bf0ce45f371552e233675bbcf55e8 Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Sun, 19 May 2024 10:24:48 -0600 Subject: [PATCH 3/7] I don't like Discord attachments. --- index.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 1632b75..21857fa 100644 --- a/index.js +++ b/index.js @@ -1234,13 +1234,18 @@ discord.on("interactionCreate", async (interaction) => { } // Returns image, send embed with image as attachment (we need to bypass discord cache) res.buffer().then(async (buffer) => { - const attachment = new Discord.MessageAttachment(buffer, `${type}_${day}.png`); - const embed = { - title: `${toTitleCase(type)} Outlook Day ${day}`, - image: { - url: `attachment://${type}_${day}.png` - }, - color: 0x00ff00 + const message = { + embeds: [{ + title: `${toTitleCase(type)} Outlook Day ${day}`, + image: { + url: `attachment://${type}_${day}.png` + }, + color: 0x00ff00 + }], + files: [{ + attachment: buffer, + name: `${type}_${day}.png` + }] } interaction.editReply({ embeds: [embed], files: [attachment] }); }); From b86eabcf1b11c350557bb4f0992af19854769978 Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Sun, 19 May 2024 10:25:39 -0600 Subject: [PATCH 4/7] Buh --- index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 21857fa..8819659 100644 --- a/index.js +++ b/index.js @@ -1234,7 +1234,7 @@ discord.on("interactionCreate", async (interaction) => { } // Returns image, send embed with image as attachment (we need to bypass discord cache) res.buffer().then(async (buffer) => { - const message = { + interaction.editReply({ embeds: [{ title: `${toTitleCase(type)} Outlook Day ${day}`, image: { @@ -1246,8 +1246,7 @@ discord.on("interactionCreate", async (interaction) => { attachment: buffer, name: `${type}_${day}.png` }] - } - interaction.editReply({ embeds: [embed], files: [attachment] }); + }); }); }).catch((err) => { interaction.editReply({ content: "Failed to get outlook", ephemeral: true }); From b49d1c9a58c666099fd0a83814efc34d9dc93d2a Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Sun, 19 May 2024 10:26:14 -0600 Subject: [PATCH 5/7] Make output of outlook not ephemeral --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 8819659..9796ef1 100644 --- a/index.js +++ b/index.js @@ -1245,7 +1245,8 @@ discord.on("interactionCreate", async (interaction) => { files: [{ attachment: buffer, name: `${type}_${day}.png` - }] + }], + ephemeral: false }); }); }).catch((err) => { From 6332006702094d30bcbc6ddb2191889a2c798301 Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Sun, 19 May 2024 10:26:51 -0600 Subject: [PATCH 6/7] Guh --- index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 9796ef1..70c1f3f 100644 --- a/index.js +++ b/index.js @@ -1226,7 +1226,7 @@ discord.on("interactionCreate", async (interaction) => { if (day < 0 || day > 7) return interaction.reply({ content: "Invalid day", ephemeral: true }); if (type !== "fire" && type !== "storm") return interaction.reply({ content: "Invalid type", ephemeral: true }); url = outlookURLs[type][day]; - await interaction.deferReply({ ephemeral: true }); + await interaction.deferReply(); fetch(url).then((res) => { if (res.status !== 200) { interaction.editReply({ content: "Failed to get outlook", ephemeral: true }); @@ -1245,8 +1245,7 @@ discord.on("interactionCreate", async (interaction) => { files: [{ attachment: buffer, name: `${type}_${day}.png` - }], - ephemeral: false + }] }); }); }).catch((err) => { From 99667e4890d67238503db88ff6239a177aadc7cb Mon Sep 17 00:00:00 2001 From: ChrisChrome Date: Sun, 19 May 2024 10:27:44 -0600 Subject: [PATCH 7/7] Fix day being -1 --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 70c1f3f..4d388e5 100644 --- a/index.js +++ b/index.js @@ -1236,7 +1236,7 @@ discord.on("interactionCreate", async (interaction) => { res.buffer().then(async (buffer) => { interaction.editReply({ embeds: [{ - title: `${toTitleCase(type)} Outlook Day ${day}`, + title: `${toTitleCase(type)} Outlook Day ${day + 1}`, image: { url: `attachment://${type}_${day}.png` },