Merge pull request 'Add NWRplay command' (#16) from Testing into main

Reviewed-on: ChrisChrome/weather-bot#16
This commit is contained in:
MoSiren 2024-06-18 00:53:53 -06:00
commit 4b8d0515f9
2 changed files with 77 additions and 17 deletions

12
data/nwrstreams.json Normal file
View file

@ -0,0 +1,12 @@
{
"callsigns": {
"WXL46": "https://icecast.sirenarchive.xyz/NWR/WXL46",
"KZZ30": "https://icecast.sirenarchive.xyz/NWR/KZZ30",
"KZZ57": "https://wxradio.org/IL-Rockford-KZZ57",
"KXI41": "https://wxradio.org/IL-CrystalLake-KXI41",
"KHB34": "https://wxradio.org/FL-Miami-KHB34",
"WNG663": "https://wxradio.org/FL-Princeton-WNG663",
"KEC80": "https://wxradio.org/GA-Atlanta-KEC80",
"KGRX_NOT_NWR": "https://icecast.sirenarchive.xyz/AAC/KGRX"
}
}

View file

@ -6,6 +6,7 @@ const blacklist = require("./data/blacklist.json");
const events = require("./data/events.json"); const events = require("./data/events.json");
const outlookURLs = require("./data/outlook.json"); const outlookURLs = require("./data/outlook.json");
const sattelites = require("./data/sattelites.json"); const sattelites = require("./data/sattelites.json");
const nwrstreams = require("./data/nwrstreams.json")
const Jimp = require("jimp"); const Jimp = require("jimp");
const { client, xml } = require("@xmpp/client"); const { client, xml } = require("@xmpp/client");
const fetch = require("node-fetch"); const fetch = require("node-fetch");
@ -30,6 +31,7 @@ const rest = new REST({
version: '10' version: '10'
}).setToken(config.discord.token); }).setToken(config.discord.token);
// Setup SQlite DB // Setup SQlite DB
const db = new sqlite3.Database("channels.db", (err) => { const db = new sqlite3.Database("channels.db", (err) => {
if (err) { if (err) {
@ -630,6 +632,7 @@ discord.on('ready', async () => {
}, },
{ {
"name": "play", "name": "play",
"type": 1,
"description": "Play a stream", "description": "Play a stream",
"options": [ "options": [
{ {
@ -658,10 +661,33 @@ discord.on('ready', async () => {
] ]
} }
) )
nwrplayCommand = {
"name": "nwrplay",
"description": "Nwr stream",
"type": 1,
"options": [
{
"name": "callsign",
"description": "The URL of the stream to play",
"type": 3,
"required": true,
"choices": []
}
]
}
for (const key in nwrstreams.callsigns) {
nwrplayCommand.options[0].choices.push({
"name": key,
"value": key
});
}
commands.push(nwrplayCommand);
} }
await (async () => { await (async () => {
try { try {
//Global //Global
if(config.debug >= 1) console.log(`${colors.magenta("[DEBUG]")} Registering global commands: ${JSON.stringify(commands, null, 2)}`);
await rest.put(Routes.applicationCommands(discord.user.id), { body: commands }) await rest.put(Routes.applicationCommands(discord.user.id), { body: commands })
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -869,7 +895,7 @@ discord.on("interactionCreate", async (interaction) => {
const embed = { const embed = {
title: "About Me!", title: "About Me!",
thumbnail: { thumbnail: {
url: discord.user.avatarURL() url: discord.user?.avatarURL()
}, },
description: `I listen to all the weather.im rooms and send them to discord channels.\nI am open source, you can find my code [here!](https://github.com/ChrisChrome/iembot-2.0)\n\nThis bot is not affiliated with NOAA, the National Weather Service, or the IEM project.`, description: `I listen to all the weather.im rooms and send them to discord channels.\nI am open source, you can find my code [here!](https://github.com/ChrisChrome/iembot-2.0)\n\nThis bot is not affiliated with NOAA, the National Weather Service, or the IEM project.`,
fields: [ fields: [
@ -900,7 +926,7 @@ discord.on("interactionCreate", async (interaction) => {
color: 0x00ff00, color: 0x00ff00,
footer: { footer: {
text: "Made by @chrischrome with <3", text: "Made by @chrischrome with <3",
icon_url: discord.users.cache.get("289884287765839882").avatarURL() icon_url: "https://cdn.discordapp.com/avatars/289884287765839882/2b00063a92adfe08f325353eee29e348.webp?size=1024&format=webp&width=0&height=256"
} }
} }
interaction.reply({ embeds: [embed] }); interaction.reply({ embeds: [embed] });
@ -1000,7 +1026,7 @@ discord.on("interactionCreate", async (interaction) => {
break; break;
case "playbcfy": // Play broadcastify stream case "playbcfy": // Play broadcastify stream
if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true }); if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true });
if (!config.broadcastify.enabled) return interaction.reply({ content: "Broadcastify is not enabled", ephemeral: true }); if (!config.broadcastify.enabled) return interaction.reply({ content: "Broadcastify is not enabled", ephemeral: true });
streamID = interaction.options.getString("id"); streamID = interaction.options.getString("id");
// Check if the stream ID is valid (up to 10 digit alphanumeric) // Check if the stream ID is valid (up to 10 digit alphanumeric)
@ -1008,7 +1034,7 @@ discord.on("interactionCreate", async (interaction) => {
// Get the stream URL // Get the stream URL
url = `https://${config.broadcastify.username}:${config.broadcastify.password}@audio.broadcastify.com/${streamID}.mp3`; url = `https://${config.broadcastify.username}:${config.broadcastify.password}@audio.broadcastify.com/${streamID}.mp3`;
// Get the channel // Get the channel
channel = interaction.member.voice.channel; channel = interaction.member.voice?.channel;
if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true }); if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true });
// Join the channel and play the stream // Join the channel and play the stream
res = JoinChannel(channel, url, .1, interaction) res = JoinChannel(channel, url, .1, interaction)
@ -1020,16 +1046,16 @@ discord.on("interactionCreate", async (interaction) => {
break; break;
case "play": // Play generic stream case "play": // Play generic stream
if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true }); if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true });
// Get the URL // Use local variables & Get the URL
url = interaction.options.getString("url"); interactionUrl = interaction.options.getString("url");
// Sanity check URL for funny stuff
if (!url.match(/https?:\/\/[^\s]+/)) return interaction.reply({ content: "Invalid URL", ephemeral: true });
// Get the channel // Get the channel
channel = interaction.member.voice.channel; channel = interaction.member.voice?.channel;
// Check if in channel
if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true }); if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true });
// Join the channel and play the stream // Join the channel and play the stream
st = JoinChannel(channel, url, .1, interaction) st = JoinChannel(channel, interactionUrl, .1, interaction);
if (st) { if (st) {
interaction.reply({ content: "Joined, trying to start playing.", ephemeral: true }); interaction.reply({ content: "Joined, trying to start playing.", ephemeral: true });
} else { } else {
@ -1037,7 +1063,29 @@ discord.on("interactionCreate", async (interaction) => {
} }
break; break;
case "leave": // Leaves Channel case "nwrplay": // Play NWR stream
if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true });
// Get the callsign
const callsign = interaction.options.getString("callsign");
// Get the URL associated with the callsign
const url = nwrstreams.callsigns[callsign];
// Get the voice channel
channel = interaction.member.voice?.channel; // Use a unique variable name
if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true });
// Join the channel and play the stream
const streamStatus = JoinChannel(channel, url, .1, interaction); // Use a unique variable name
if (streamStatus) {
interaction.reply({ content: "Joined, trying to start playing.", ephemeral: true });
} else {
interaction.reply({ content: `Failed to play stream`, ephemeral: true });
}
break;
case "leave": // Leave Channel
if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true }); if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true });
channel = interaction.member.voice.channel; channel = interaction.member.voice.channel;
if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true }); if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true });
@ -1050,7 +1098,7 @@ discord.on("interactionCreate", async (interaction) => {
break; break;
case "pause": // Pause/unpause stream case "pause": // Pause/unpause stream
if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true }); if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true });
channel = interaction.member.voice.channel; channel = interaction.member.voice.channel;
if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true }); if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true });
res = toggleVoicePause(channel) res = toggleVoicePause(channel)
@ -1061,7 +1109,7 @@ discord.on("interactionCreate", async (interaction) => {
} }
break; break;
case "volume": // Set volume case "volume": // Set volume
if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true }); if (!interaction.inGuild()) return interaction.reply({ content: "This command can only be used in a guild", ephemeral: true });
channel = interaction.member.voice.channel; channel = interaction.member.voice.channel;
if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true }); if (!channel) return interaction.reply({ content: "You need to be in a voice channel", ephemeral: true });
volume = interaction.options.getInteger("volume") / 100; volume = interaction.options.getInteger("volume") / 100;
@ -1158,9 +1206,9 @@ discord.on("interactionCreate", async (interaction) => {
}); });
break; break;
case "alertmap": case "alertmap":
url = "https://forecast.weather.gov/wwamap/png/US.png" const alertmapurl = "https://forecast.weather.gov/wwamap/png/US.png"
await interaction.deferReply(); await interaction.deferReply();
fetch(url).then((res) => { fetch(alertmapurl).then((res) => {
if (res.status !== 200) { if (res.status !== 200) {
interaction.editReply({ content: "Failed to get alert map", ephemeral: true }); interaction.editReply({ content: "Failed to get alert map", ephemeral: true });
return; return;
@ -1170,7 +1218,7 @@ discord.on("interactionCreate", async (interaction) => {
embeds: [{ embeds: [{
title: `Alert Map`, title: `Alert Map`,
image: { image: {
url: `attachment://alerts.png` alertmapurl: `attachment://alerts.png`
}, },
color: 0x00ff00 color: 0x00ff00
}], }],