Bugfixes in notifications and update to relay

This commit is contained in:
Skylar Grant 2023-02-20 14:07:38 -05:00
parent ebc31b5a0c
commit 56be24b5cd
3 changed files with 173 additions and 60 deletions

View File

@ -28,9 +28,9 @@ const dbfn = require('./modules/dbfn.js');
const isDev = process.env.DEBUG; const isDev = process.env.DEBUG;
client.once('ready', async () => { client.once('ready', async () => {
await fn.collectionBuilders.slashCommands(client); fn.collectionBuilders.slashCommands(client);
await fn.collectionBuilders.guildInfos(client); await fn.collectionBuilders.guildInfos(client);
await fn.setupCollectors(client); await fn.collectionBuilders.messageCollectors(client);
console.log('Ready!'); console.log('Ready!');
client.user.setActivity({ name: strings.activity.name, type: ActivityType.Watching }); client.user.setActivity({ name: strings.activity.name, type: ActivityType.Watching });
if (isDev == 'false') { if (isDev == 'false') {
@ -85,6 +85,11 @@ client.on('interactionCreate', async interaction => {
} }
}); });
client.on('messageUpdate', (oldMessage, newMessage) => {
if (process.env.DEBUG) console.log(`Message updated`);
});
process.on('unhandledRejection', error => { process.on('unhandledRejection', error => {
console.error('Unhandled promise rejection:', error); console.error('Unhandled promise rejection:', error);
}); });

View File

@ -43,6 +43,17 @@ const functions = {
client.guildInfos.set(guildInfo.guildId, guildInfo); client.guildInfos.set(guildInfo.guildId, guildInfo);
} }
return 'guildInfos Collection Built'; return 'guildInfos Collection Built';
},
async messageCollectors(client) {
// Create an empty collection for MessageCollectors
if (!client.messageCollectors) client.messageCollectors = new Discord.Collection();
client.messageCollectors.clear();
// Get all of the guild infos from the client
const { guildInfos, messageCollectors } = client;
// Iterate over each guild info
await guildInfos.forEach(async guildInfo => {
await functions.collectors.create(client, guildInfo);
});
} }
}, },
builders: { builders: {
@ -528,6 +539,59 @@ const functions = {
await member.roles.remove(role).catch(err => console.error("Error taking the role: " + err + "\n" + JSON.stringify(role))); await member.roles.remove(role).catch(err => console.error("Error taking the role: " + err + "\n" + JSON.stringify(role)));
} }
}, },
collectors: {
async create(client, guildInfo) {
// If a collector is already setup
if (client.messageCollectors.has(guildInfo.guildId)) {
// Close the collector
await this.end(client, guildInfo);
}
// Make sure guildInfo is what we expect, the watch channel isnt blank, and notifications are enabled
if (guildInfo instanceof GuildInfo && guildInfo.watchChannelId != "" && guildInfo.notificationsEnabled) {
// Fetch the Guild
const guild = await client.guilds.fetch(guildInfo.guildId);
// Fetch the Channel
const channel = await guild.channels.fetch(guildInfo.watchChannelId);
// Create the filter function
const filter = message => {
// Discard any messages sent by Silvanus
return message.author.id != process.env.BOTID;
}
// Create the collector
const collector = channel.createMessageCollector({ filter });
// Add the collector to the messageCollectors Collection
client.messageCollectors.set(guildInfo.guildId, collector);
collector.on('collect', message => {
// Check for manual relay use with "water ping" and "fruit ping"
if (message.content.toLowerCase().includes("water ping")) {
functions.sendWaterReminder(guildInfo, guildInfo.waterMessage, guildInfo.reminderChannelId, guild);
return;
} else if (message.content.toLowerCase().includes("fruit ping")) {
functions.sendFruitReminder(guildInfo, guildInfo.fruitMessage, guildInfo.reminderChannelId, guild);
return;
}
// If the message doesn't contain an embed, we can ignore it
if (message.embeds == undefined) return;
if (message.embeds.length == 0) return;
// Check the description field of the embed to determine if it matches Grow A Tree's notification texts
if (message.embeds[0].data.description.includes(strings.notifications.water)) {
functions.sendWaterReminder(guildInfo, guildInfo.waterMessage, guildInfo.reminderChannelId, guild);
} else if (message.embeds[0].data.description.includes(strings.notifications.fruit)) {
functions.sendFruitReminder(guildInfo, guildInfo.fruitMessage, guildInfo.reminderChannelId, guild);
}
});
}
},
async end(client, guildInfo) {
if (!client.messageCollectors) throw "No Message Collectors";
if (!client.messageCollectors.has(guildInfo.guildId)) throw "Guild doesn't have a Message Collector";
const collector = client.messageCollectors.get(guildInfo.guildId);
// Close the collector
await collector.stop();
// Remove the collector from the messageCollectors Collection
client.messageCollectors.delete(guildInfo.guildId);
}
},
async refresh(interaction) { async refresh(interaction) {
// const getGuildInfoResponse = await dbfn.getGuildInfo(interaction.guildId); // const getGuildInfoResponse = await dbfn.getGuildInfo(interaction.guildId);
// let guildInfo = getGuildInfoResponse.data; // let guildInfo = getGuildInfoResponse.data;
@ -642,9 +706,9 @@ const functions = {
}, },
async setupCollectors(client) { async setupCollectors(client) {
let guildInfos = client.guildInfos; let guildInfos = client.guildInfos;
guildInfos.set("collectors", []); let collectorsArray = [];
await guildInfos.forEach(async guildInfo => { await guildInfos.forEach(async guildInfo => {
if ( guildInfo instanceof GuildInfo && guildInfo.watchChannelId != "" && guildInfo.notificationsEnabled) { if (guildInfo instanceof GuildInfo && guildInfo.watchChannelId != "" && guildInfo.notificationsEnabled) {
const guild = await client.guilds.fetch(guildInfo.guildId); const guild = await client.guilds.fetch(guildInfo.guildId);
// console.log(guildInfo instanceof GuildInfo); // console.log(guildInfo instanceof GuildInfo);
const channel = await guild.channels.fetch(guildInfo.watchChannelId); const channel = await guild.channels.fetch(guildInfo.watchChannelId);
@ -671,12 +735,17 @@ const functions = {
}); });
} }
}); });
guildInfos.set("collectors", collectorsArray);
}, },
async setupCollector(channel, guildInfo) { async setupCollector(channel, interaction) {
if (interaction.client.guildInfos.has(interaction.guildId)) {
let collectors = interaction.client.guildInfos.get('collectors');
let guildInfo = interaction.client.guildInfos.get(interaction.guildId);
const filter = message => { const filter = message => {
return message.author.id != process.env.BOTID; return message.author.id != process.env.BOTID;
} }
const collector = channel.createMessageCollector({ filter }); const collector = channel.createMessageCollector({ filter });
collectors.push(collector);
collector.on('collect', message => { collector.on('collect', message => {
if (message.content.toLowerCase().includes("water ping")) { if (message.content.toLowerCase().includes("water ping")) {
this.sendWaterReminder(guildInfo, guildInfo.waterMessage, guildInfo.reminderChannelId, guild); this.sendWaterReminder(guildInfo, guildInfo.waterMessage, guildInfo.reminderChannelId, guild);
@ -687,13 +756,15 @@ const functions = {
} }
if (message.embeds == undefined) return; if (message.embeds == undefined) return;
if (message.embeds.length == 0) return; if (message.embeds.length == 0) return;
guildInfo = client.guildInfos.get(guild.id);
if (message.embeds[0].data.description.includes(strings.notifications.water)) { if (message.embeds[0].data.description.includes(strings.notifications.water)) {
this.sendWaterReminder(guildInfo, guildInfo.waterMessage, guildInfo.reminderChannelId, guild); this.sendWaterReminder(guildInfo, guildInfo.waterMessage, guildInfo.reminderChannelId, guild);
} else if (message.embeds[0].data.description.includes(strings.notifications.fruit)) { } else if (message.embeds[0].data.description.includes(strings.notifications.fruit)) {
this.sendFruitReminder(guildInfo, guildInfo.fruitMessage, guildInfo.reminderChannelId, guild); this.sendFruitReminder(guildInfo, guildInfo.fruitMessage, guildInfo.reminderChannelId, guild);
} }
}); });
} else {
throw "Guild doesn't exist in database!";
}
} }
}; };

View File

@ -6,7 +6,7 @@ const strings = require('../data/strings.json');
module.exports = { module.exports = {
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName('notifications') .setName('relay')
.setDescription('A notification relay for improved water and fruit notifications') .setDescription('A notification relay for improved water and fruit notifications')
.addSubcommand(sc => .addSubcommand(sc =>
sc.setName('set') sc.setName('set')
@ -67,78 +67,115 @@ module.exports = {
const subcommand = interaction.options.getSubcommand(); const subcommand = interaction.options.getSubcommand();
// if (process.env.DEBUG) console.log(`${typeof subcommand}: ${subcommand}`); // if (process.env.DEBUG) console.log(`${typeof subcommand}: ${subcommand}`);
switch (subcommand) { switch (subcommand) {
// Set all components for the first time
case "set": case "set":
// If there is already a guildInfo object for this server
if (interaction.client.guildInfos.has(interaction.guildId)) { if (interaction.client.guildInfos.has(interaction.guildId)) {
const watchChannel = interaction.options.getChannel('watchchannel');
const waterMessage = interaction.options.getString('watermessage');
const fruitMessage = interaction.options.getString('fruitmessage') ? interaction.options.getString('fruitmessage') : interaction.options.getString('watermessage');
const reminderChannel = interaction.options.getChannel('pingchannel');
let guildInfo = interaction.client.guildInfos.get(interaction.guildId); let guildInfo = interaction.client.guildInfos.get(interaction.guildId);
guildInfo.setReminders(waterMessage, fruitMessage, reminderChannel.id, watchChannel.id, true); // Get options from the interaction
let query = guildInfo.queryBuilder("setReminders");
await dbfn.setGuildInfo(query);
const replyParts = [
`I'll watch <#${watchChannel.id}> for Grow A Tree Notifications and relay them to <#${reminderChannel.id}>.`,
`Water Message: ${waterMessage}`
];
if (fruitMessage != "") replyParts.push(`Fruit Message: ${fruitMessage}`);
await interaction.editReply(replyParts.join("\n")).catch(e => console.error(e));
fn.collectionBuilders.guildInfos(interaction.client);
fn.setupCollector(interaction.channel, guildInfo);
} else {
const watchChannel = interaction.options.getChannel('watchchannel'); const watchChannel = interaction.options.getChannel('watchchannel');
const waterMessage = interaction.options.getString('watermessage'); const waterMessage = interaction.options.getString('watermessage');
// If the fruit message is set, use it, otherwise default to the water message.
const fruitMessage = interaction.options.getString('fruitmessage') ? interaction.options.getString('fruitmessage') : interaction.options.getString('watermessage'); const fruitMessage = interaction.options.getString('fruitmessage') ? interaction.options.getString('fruitmessage') : interaction.options.getString('watermessage');
const reminderChannel = interaction.options.getChannel('pingchannel'); const reminderChannel = interaction.options.getChannel('pingchannel');
// Set the reminder configuration in the GuildInfo object
guildInfo.setReminders(waterMessage, fruitMessage, reminderChannel.id, watchChannel.id, true);
// Update the guildInfos Collection
interaction.client.guildInfos.set(interaction.guildId, guildInfo);
// Build a query to update the database
let query = guildInfo.queryBuilder("setReminders");
// Run the query
await dbfn.setGuildInfo(query);
// Set up a collector on the watch channel
fn.collectors.create(interaction.client, guildInfo);
// Compose a reply
const reply = [
`I'll watch <#${watchChannel.id}> for Grow A Tree Notifications and relay them to <#${reminderChannel.id}>.`,
`Water Message: ${waterMessage}`,
`Fruit Message: ${fruitMessage}`
].join("\n");
// Send the reply
await interaction.editReply(fn.builders.embed(reply)).catch(e => console.error(e));
} else {
// Get options from the interaction
const watchChannel = interaction.options.getChannel('watchchannel');
const waterMessage = interaction.options.getString('watermessage');
// If the fruit message is set, use it. Otherwise default to the water message
const fruitMessage = interaction.options.getString('fruitmessage') ? interaction.options.getString('fruitmessage') : interaction.options.getString('watermessage');
const reminderChannel = interaction.options.getChannel('pingchannel');
// Create a new GuildInfo object
let guildInfo = new GuildInfo() let guildInfo = new GuildInfo()
.setId(interaction.guildId) .setId(interaction.guildId)
// Set the reminder configuration
.setReminders(waterMessage, fruitMessage, reminderChannel.id, watchChannel.id, true); .setReminders(waterMessage, fruitMessage, reminderChannel.id, watchChannel.id, true);
// Update the guildInfos Collection
interaction.client.guildInfos.set(interaction.guildId, guildInfo);
// Build a query to update the database
let query = guildInfo.queryBuilder("setReminders"); let query = guildInfo.queryBuilder("setReminders");
// Run the query
await dbfn.setGuildInfo(query); await dbfn.setGuildInfo(query);
const replyParts = [ // Create a messageCollector on the watch channel
fn.collectors.create(interaction.client, guildInfo);
// Compose a reply
const reply = [
`I'll watch <#${watchChannel.id}> for Grow A Tree Notifications and relay them to <#${reminderChannel.id}>.`, `I'll watch <#${watchChannel.id}> for Grow A Tree Notifications and relay them to <#${reminderChannel.id}>.`,
`Water Message: ${waterMessage}` `Water Message: ${waterMessage}`,
]; `Fruit Message: ${fruitMessage}`
if (fruitMessage != "") replyParts.push(`Fruit Message: ${fruitMessage}`); ].join("\n");
await interaction.editReply(replyParts.join("\n")).catch(e => console.error(e)); // Send the reply
fn.collectionBuilders.guildInfos(interaction.client); await interaction.editReply(reply).catch(e => console.error(e));
fn.setupCollector(watchChannel, guildInfo);
} }
break; break;
case "update": case "update": // Update the relay configuration piecemeal
if (interaction.client.guildInfos.has(interaction.guildId)) { if (interaction.client.guildInfos.has(interaction.guildId)) {
let guildInfo = interaction.client.guildInfos.get(interaction.guildId); let guildInfo = interaction.client.guildInfos.get(interaction.guildId);
// Get all possible options from the interaction
const inWatchChannel = interaction.options.getChannel('watchchannel'); const inWatchChannel = interaction.options.getChannel('watchchannel');
const inWaterMessage = interaction.options.getString('watermessage'); const inWaterMessage = interaction.options.getString('watermessage');
const inFruitMessage = interaction.options.getString('fruitmessage'); const inFruitMessage = interaction.options.getString('fruitmessage');
const inReminderChannel = interaction.options.getChannel('pingchannel'); const inReminderChannel = interaction.options.getChannel('pingchannel');
// Check if each option is set, if it is, use it. Otherwise use what was already set
const outWatchChannelId = inWatchChannel ? inWatchChannel.id : guildInfo.watchChannelId; const outWatchChannelId = inWatchChannel ? inWatchChannel.id : guildInfo.watchChannelId;
const outWaterMessage = inWaterMessage ? inWaterMessage : guildInfo.waterMessage; const outWaterMessage = inWaterMessage ? inWaterMessage : guildInfo.waterMessage;
const outFruitMessage = inFruitMessage ? inFruitMessage : guildInfo.fruitMessage; const outFruitMessage = inFruitMessage ? inFruitMessage : guildInfo.fruitMessage;
const outReminderChannelId = inReminderChannel ? inReminderChannel.id : guildInfo.reminderChannelId; const outReminderChannelId = inReminderChannel ? inReminderChannel.id : guildInfo.reminderChannelId;
// Update the relay configuration
guildInfo.setReminders(outWaterMessage, outFruitMessage, outReminderChannelId, outWatchChannelId, true); guildInfo.setReminders(outWaterMessage, outFruitMessage, outReminderChannelId, outWatchChannelId, true);
// Update the guildInfos Collection
interaction.client.guildInfos.set(interaction.guildId, guildInfo);
// Build a query to update the database
let query = guildInfo.queryBuilder("setReminders"); let query = guildInfo.queryBuilder("setReminders");
// Run the query
await dbfn.setGuildInfo(query); await dbfn.setGuildInfo(query);
const replyParts = [ // Create a messageCollector on the watch channel
fn.collectors.create(interaction.client, guildInfo);
// Compose a reply
const reply = [
`I'll watch <#${outWatchChannelId}> for Grow A Tree Notifications and relay them to <#${outReminderChannelId}>.`, `I'll watch <#${outWatchChannelId}> for Grow A Tree Notifications and relay them to <#${outReminderChannelId}>.`,
`Water Message: ${outWaterMessage}` `Water Message: ${outWaterMessage}`,
]; `Fruit Message: ${outFruitMessage}`
if (outFruitMessage != "") replyParts.push(`Fruit Message: ${outFruitMessage}`); ].join("\n");
await interaction.editReply(replyParts.join("\n")).catch(e => console.error(e)); // Send the reply
fn.collectionBuilders.guildInfos(interaction.client); await interaction.editReply(reply).catch(e => console.error(e));
fn.setupCollector(inWatchChannel, guildInfo);
} else { } else {
await interaction.editReply(fn.builders.errorEmbed("There is no existing notification relay to update!")).catch(e => console.error(e)); await interaction.editReply(fn.builders.errorEmbed("There is no existing notification relay to update!")).catch(e => console.error(e));
} }
break; break;
case 'disable': case 'disable': // Disable the relay
if (interaction.client.guildInfos.has(interaction.guildId)) { if (interaction.client.guildInfos.has(interaction.guildId)) {
let guildInfo = interaction.client.guildInfos.get(interaction.guildId); let guildInfo = interaction.client.guildInfos.get(interaction.guildId);
// Update the relay config with all undefined except for `enabled` which is false
guildInfo.setReminders(undefined, undefined, undefined, undefined, false); guildInfo.setReminders(undefined, undefined, undefined, undefined, false);
// Update the guildInfos Collection
interaction.client.guildInfos.set(interaction.guildId, guildInfo);
// Update the database
await dbfn.setGuildInfo(guildInfo.queryBuilder("setReminders")).catch(e => console.error(e)); await dbfn.setGuildInfo(guildInfo.queryBuilder("setReminders")).catch(e => console.error(e));
await fn.collectionBuilders.guildInfos(interaction.client); // Close the collector
await fn.collectors.end(interaction.client, guildInfo).catch(e => console.error(e));
// Reply confirming disabling of relay
await interaction.editReply(fn.builders.embed(strings.status.optout)).catch(e => console.error(e)); await interaction.editReply(fn.builders.embed(strings.status.optout)).catch(e => console.error(e));
} else { } else {
await interaction.editReply(fn.builders.errorEmbed("A notification relay has not been set up yet!")).catch(e => console.error(e)); await interaction.editReply(fn.builders.errorEmbed("A notification relay has not been set up yet!")).catch(e => console.error(e));