Done some stuff
This commit is contained in:
parent
fe5ac6073a
commit
94d5930cf4
269
index.js
269
index.js
|
@ -28,14 +28,59 @@ app.ws('/iem', (ws, req) => {
|
||||||
"uuid": curUUID,
|
"uuid": curUUID,
|
||||||
"host": hostname
|
"host": hostname
|
||||||
}));
|
}));
|
||||||
wsConnections.push(ws);
|
sock = wsConnections.push({ ws, req, subs: [] });
|
||||||
ws.on('close', () => {
|
ws.on('close', () => {
|
||||||
console.log(`disconnected from ${req.ip}`);
|
console.log(`disconnected from ${req.ip}`);
|
||||||
wsConnections = wsConnections.filter((conn) => conn !== ws);
|
wsConnections = wsConnections.filter((conn) => conn.ws !== ws);
|
||||||
});
|
});
|
||||||
ws.on('message', (msg) => {
|
ws.on('message', (msg) => {
|
||||||
if (msg === "ping") {
|
const data = JSON.parse(msg);
|
||||||
ws.send("pong")
|
if (!data.type) return;
|
||||||
|
switch (data.type) {
|
||||||
|
case "subscribe":
|
||||||
|
if (data.channel) {
|
||||||
|
if (!wsConnections[sock - 1].subs.includes(data.channel)) {
|
||||||
|
wsConnections[sock - 1].subs.push(data.channel);
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
"type": "internal-response",
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"message": `Subscribed to ${data.channel}`
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
"type": "internal-response",
|
||||||
|
"code": 409,
|
||||||
|
"data": {
|
||||||
|
"error": "Already subscribed to this channel."
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "unsubscribe":
|
||||||
|
if (data.channel) {
|
||||||
|
if (wsConnections[sock - 1].subs.includes(data.channel)) {
|
||||||
|
wsConnections[sock - 1].subs = wsConnections[sock - 1].subs.filter((sub) => sub !== data.channel);
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
"type": "internal-response",
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"message": `Unsubscribed from ${data.channel}`
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
"type": "internal-response",
|
||||||
|
"code": 404,
|
||||||
|
"data": {
|
||||||
|
"error": "Not subscribed to this channel."
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -228,13 +273,6 @@ xmpp.on("stanza", (stanza) => {
|
||||||
}
|
}
|
||||||
// Get new messages and log them, ignore old messages
|
// Get new messages and log them, ignore old messages
|
||||||
if (stanza.is("message") && stanza.attrs.type === "groupchat") {
|
if (stanza.is("message") && stanza.attrs.type === "groupchat") {
|
||||||
clearTimeout(restartTimer)
|
|
||||||
restartTimer = setTimeout(() => {
|
|
||||||
console.log(`${colors.yellow("[WARN]")} Restarting XMPP connection...`);
|
|
||||||
xmpp.disconnect().then(() => {
|
|
||||||
xmpp.start();
|
|
||||||
});
|
|
||||||
}, 10000)
|
|
||||||
// Stops spam from getting old messages
|
// Stops spam from getting old messages
|
||||||
if (startup) return;
|
if (startup) return;
|
||||||
// Get channel name
|
// Get channel name
|
||||||
|
@ -254,7 +292,6 @@ xmpp.on("stanza", (stanza) => {
|
||||||
if (!evt) {
|
if (!evt) {
|
||||||
evt = { name: "Unknown", priority: 3 }
|
evt = { name: "Unknown", priority: 3 }
|
||||||
console.log(`${colors.red("[ERROR]")} Unknown event type: ${product_id.pil.substring(0, 3)}. Fix me`);
|
console.log(`${colors.red("[ERROR]")} Unknown event type: ${product_id.pil.substring(0, 3)}. Fix me`);
|
||||||
console.log(`${colors.magenta("[DEBUG]")} ${bodyData.string}`)
|
|
||||||
const logChannel = discord.guilds.cache.get(config.discord.mainGuild).channels.cache.get(config.discord.logChannel);
|
const logChannel = discord.guilds.cache.get(config.discord.mainGuild).channels.cache.get(config.discord.logChannel);
|
||||||
logChannel.send({
|
logChannel.send({
|
||||||
embeds: [
|
embeds: [
|
||||||
|
@ -276,174 +313,11 @@ xmpp.on("stanza", (stanza) => {
|
||||||
console.log(`${colors.cyan("[INFO]")} ${getWFOByRoom(fromChannel).location} - ${evt.text} - ${product_id.timestamp}`);
|
console.log(`${colors.cyan("[INFO]")} ${getWFOByRoom(fromChannel).location} - ${evt.text} - ${product_id.timestamp}`);
|
||||||
messages++;
|
messages++;
|
||||||
|
|
||||||
|
|
||||||
// // Handle NTFY
|
|
||||||
// if (config.ntfy.enabled) {
|
|
||||||
// //if (config.debug >= 1) console.log(`${colors.magenta("[DEBUG]")} Sending NTFY for ${config.ntfy.prefix}${fromChannel}`)
|
|
||||||
// ntfyBody = {
|
|
||||||
// "topic": `${config.ntfy.prefix}${fromChannel}`,
|
|
||||||
// "message": bodyData.string,
|
|
||||||
// "tags": [`Timestamp: ${product_id.timestamp}`, `Station: ${product_id.station}`, `WMO: ${product_id.wmo}`, `PIL: ${product_id.pil}`, `Channel: ${fromChannel}`],
|
|
||||||
// "priority": evt.priority,
|
|
||||||
// "actions": [{ "action": "view", "label": "Product", "url": bodyData.url }, { "action": "view", "label": "Product Text", "url": `https://mesonet.agron.iastate.edu/api/1/nwstext/${product_id_raw}` }]
|
|
||||||
// }
|
|
||||||
// if (stanza.getChild("x").attrs.twitter_media) {
|
|
||||||
// ntfyBody.attach = stanza.getChild("x").attrs.twitter_media;
|
|
||||||
// }
|
|
||||||
// fetch(config.ntfy.server, {
|
|
||||||
// method: 'POST',
|
|
||||||
// body: JSON.stringify(ntfyBody),
|
|
||||||
// headers: {
|
|
||||||
// 'Authorization': `Bearer ${config.ntfy.token}`
|
|
||||||
// }
|
|
||||||
// }).then((res) => {
|
|
||||||
// //if (config.debug >= 1) console.log(`${colors.magenta("[DEBUG]")} NTFY sent for ${config.ntfy.prefix}${fromChannel} with status ${res.status} ${res.statusText}`);
|
|
||||||
// if (res.status !== 200) console.log(`${colors.red("[ERROR]")} NTFY failed for ${config.ntfy.prefix}${fromChannel} with status ${res.status} ${res.statusText}`);
|
|
||||||
|
|
||||||
|
|
||||||
// }).catch((err) => {
|
|
||||||
// console.error(err)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Send discord msg
|
|
||||||
// let embed = {
|
|
||||||
// description: `<t:${product_id.timestamp / 1000}:T> <t:${product_id.timestamp / 1000}:R> ${bodyData.string}`,
|
|
||||||
// color: parseInt(config.priorityColors[evt.priority].replace("#", ""), 16) || 0x000000,
|
|
||||||
// timestamp: product_id.timestamp,
|
|
||||||
// footer: {
|
|
||||||
// text: `Station: ${product_id.station} PID: ${product_id_raw} Channel: ${fromChannel}`
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (stanza.getChild("x").attrs.twitter_media) {
|
|
||||||
// embed.image = {
|
|
||||||
// url: stanza.getChild("x").attrs.twitter_media
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let discordMsg = {
|
|
||||||
// embeds: [embed],
|
|
||||||
// components: [
|
|
||||||
// {
|
|
||||||
// type: 1,
|
|
||||||
// components: [
|
|
||||||
// {
|
|
||||||
// type: 2,
|
|
||||||
// label: "Product",
|
|
||||||
// style: 5,
|
|
||||||
// url: bodyData.url
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// type: 2,
|
|
||||||
// style: 1,
|
|
||||||
// custom_id: `product|${product_id_raw}`,
|
|
||||||
// label: "Product Text",
|
|
||||||
// emoji: {
|
|
||||||
// name: "📄"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// // Discord Channel Handling
|
|
||||||
// db.all(`SELECT * FROM channels WHERE iemchannel = ?`, [fromChannel], (err, rows) => {
|
|
||||||
// if (err) {
|
|
||||||
// console.log(`${colors.red("[ERROR]")} ${err.message}`);
|
|
||||||
// }
|
|
||||||
// if (!rows) return; // No channels to alert
|
|
||||||
// rows.forEach(async (row) => {
|
|
||||||
// // Get Filters as arrays
|
|
||||||
// if (!row.filterEvt) row.filterEvt = "";
|
|
||||||
// if (!row.filter) row.filter = "";
|
|
||||||
// let filterEvt = row.filterEvt.toLowerCase().split(",");
|
|
||||||
// let filters = row.filter.toLowerCase().split(",");
|
|
||||||
// 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.toLowerCase()) && !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
|
|
||||||
// trySend = () => {
|
|
||||||
// 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.toLowerCase().includes(filter)) && !filters.some((filter) => text.toLowerCase().includes(filter))) return;
|
|
||||||
// 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();
|
|
||||||
// }).catch((err) => {
|
|
||||||
// console.log(`${colors.yellow("[WARN]")} Failed to send message to ${channel.guild.name}/${channel.name} (${channel.guild.id}/${channel.id})`);
|
|
||||||
// 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})
|
|
||||||
// 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`);
|
|
||||||
// });
|
|
||||||
// })
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }).catch((err) => {
|
|
||||||
// setTimeout(() => {
|
|
||||||
// console.log(`${colors.red("[ERROR]")} Failed to fetch product text, retrying... ${err}`)
|
|
||||||
// trySend();
|
|
||||||
// })
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// trySend();
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
// Handle WebSocket
|
// Handle WebSocket
|
||||||
if (wsConnections.length > 0) {
|
if (wsConnections.length > 0) {
|
||||||
wsConnections.forEach((ws) => {
|
wsConnections.forEach((connection) => {
|
||||||
ws.send(JSON.stringify({
|
if (connection.subs.includes(fromChannel) || connection.subs.includes("*")) {
|
||||||
|
connection.ws.send(JSON.stringify({
|
||||||
"type": "iem-message",
|
"type": "iem-message",
|
||||||
"data": {
|
"data": {
|
||||||
"channel": getWFOByRoom(fromChannel),
|
"channel": getWFOByRoom(fromChannel),
|
||||||
|
@ -458,11 +332,49 @@ xmpp.on("stanza", (stanza) => {
|
||||||
"image": stanza.getChild("x").attrs.twitter_media || null
|
"image": stanza.getChild("x").attrs.twitter_media || null
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
xmpp.on("status", (status) => {
|
||||||
|
console.log(`${colors.cyan("[INFO]")} XMPP Status: ${status}`);
|
||||||
|
// Broadcast a message to all connected WebSocket clients
|
||||||
|
wsConnections.forEach((connection) => {
|
||||||
|
if (connection.ws.readyState === 1) { // Ensure the socket is open
|
||||||
|
connection.ws.send(JSON.stringify({
|
||||||
|
"type": "xmpp-status",
|
||||||
|
"status": status
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
xmpp.reconnect.on("reconnecting", () => {
|
||||||
|
console.log(`${colors.yellow("[WARN]")} XMPP Reconnecting...`);
|
||||||
|
wsConnections.forEach((connection) => {
|
||||||
|
if (connection.ws.readyState === 1) { // Ensure the socket is open
|
||||||
|
connection.ws.send(JSON.stringify({
|
||||||
|
"type": "xmpp-reconnect",
|
||||||
|
"status": "reconnecting"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
xmpp.reconnect.on("reconnected", () => {
|
||||||
|
console.log(`${colors.green("[INFO]")} XMPP Reconnected`);
|
||||||
|
wsConnections.forEach((connection) => {
|
||||||
|
if (connection.ws.readyState === 1) { // Ensure the socket is open
|
||||||
|
connection.ws.send(JSON.stringify({
|
||||||
|
"type": "xmpp-reconnect",
|
||||||
|
"status": "reconnected"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
const createDiscordEmbed = (data) => {
|
const createDiscordEmbed = (data) => {
|
||||||
const embed = {
|
const embed = {
|
||||||
description: `<t:${Math.floor(data.timestamp / 1000)}:T> <t:${Math.floor(data.timestamp / 1000)}:R> ${data.body}`,
|
description: `<t:${Math.floor(data.timestamp / 1000)}:T> <t:${Math.floor(data.timestamp / 1000)}:R> ${data.body}`,
|
||||||
|
@ -541,7 +453,6 @@ xmpp.on("close", () => {
|
||||||
const start = () => {
|
const start = () => {
|
||||||
startup = true;
|
startup = true;
|
||||||
xmpp.start().catch((err) => {
|
xmpp.start().catch((err) => {
|
||||||
console.log("BWUH")
|
|
||||||
console.log(`${colors.red("[ERROR]")} XMPP failed to start: ${err}.`);
|
console.log(`${colors.red("[ERROR]")} XMPP failed to start: ${err}.`);
|
||||||
setTimeout(start, 5000);
|
setTimeout(start, 5000);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Document</title>
|
<title>Document</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="stuff"></div>
|
<div id="stuff"></div>
|
||||||
<script>
|
<script>
|
||||||
|
@ -23,13 +25,28 @@
|
||||||
};
|
};
|
||||||
socket.onmessage = (event) => {
|
socket.onmessage = (event) => {
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
|
if (!data.type) return;
|
||||||
|
switch (data.type) {
|
||||||
|
case "iem-message":
|
||||||
const explanation = `Event: ${JSON.stringify(data.event)}, Channel: ${JSON.stringify(data.channel)}, Station: ${data.station}`;
|
const explanation = `Event: ${JSON.stringify(data.event)}, Channel: ${JSON.stringify(data.channel)}, Station: ${data.station}`;
|
||||||
console.log(explanation);
|
console.log(explanation);
|
||||||
const newDiv = document.createElement('div');
|
const newDiv = document.createElement('div');
|
||||||
newDiv.innerText = explanation;
|
newDiv.innerText = explanation;
|
||||||
document.getElementById('stuff').prepend(newDiv);
|
document.getElementById('stuff').prepend(newDiv);
|
||||||
|
break;
|
||||||
|
case "internal-response":
|
||||||
|
const messageBox = document.createElement('textarea');
|
||||||
|
messageBox.value = data.data.message;
|
||||||
|
messageBox.style.width = "100%";
|
||||||
|
messageBox.style.height = "100px";
|
||||||
|
document.getElementById('stuff').prepend(messageBox);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
socket.send(JSON.stringify({ type: "subscribe", channel: "*" }));
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
Loading…
Reference in a new issue