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..4d388e5 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,8 +1220,39 @@ discord.on("interactionCreate", async (interaction) => { } }); break; + 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(); + 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) => { + interaction.editReply({ + embeds: [{ + title: `${toTitleCase(type)} Outlook Day ${day + 1}`, + image: { + url: `attachment://${type}_${day}.png` + }, + color: 0x00ff00 + }], + files: [{ + attachment: buffer, + name: `${type}_${day}.png` + }] + }); + }); + }).catch((err) => { + interaction.editReply({ content: "Failed to get outlook", ephemeral: true }); + }); + break; } - break; case Discord.InteractionType.MessageComponent: if (interaction.customId) { const product_id = interaction.customId; @@ -1182,6 +1286,7 @@ discord.on("interactionCreate", async (interaction) => { break; } + }); discord.on("guildCreate", (guild) => {