From 5ed26bd488d943e00528065d9c7c23279463fde8 Mon Sep 17 00:00:00 2001 From: Crylia Date: Fri, 13 Sep 2024 21:03:14 +0200 Subject: [PATCH] finish up current features --- package.json | 4 ++- src/database/birthdaydb.js | 23 ++++++-------- src/database/blacklistdb.js | 56 ++++++++++++++++----------------- src/database/database.js | 29 ++++++++++------- src/database/eventdb.js | 20 +++++++----- src/database/staticdb.js | 38 +++++++++++----------- src/discord/discordClient.js | 6 ++-- src/features/reactionPerRole.js | 4 +-- src/index.js | 11 +++++-- src/tasks/eventReminder.js | 41 ++++++++++++------------ 10 files changed, 124 insertions(+), 108 deletions(-) diff --git a/package.json b/package.json index 1b3ffda..2bfdcac 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,10 @@ "dependencies": { "discord.js": "^14.15.3", "dotenv": "^16.4.5", + "jest": "^29.7.0", "node-cron": "^3.0.3", - "pg": "^8.12.0" + "pg": "^8.12.0", + "sequelize": "^6.37.3" }, "scripts": { "test": "jest" diff --git a/src/database/birthdaydb.js b/src/database/birthdaydb.js index 1e47bd8..9abb1cc 100644 --- a/src/database/birthdaydb.js +++ b/src/database/birthdaydb.js @@ -1,17 +1,8 @@ -const { client } = require('./database') +const { getClient } = require('./database') const CreateBirthday = async (user, birthday) => { try { - const alreadyReportedResult = await client.query(` - SELECT discorduser FROM birthday - WHERE discorduser = $1;`, - [user] - ) - - if (alreadyReportedResult.rows.length === 1) { - return alreadyReportedResult.rows[0] - } - + const client = getClient() const userResult = await client.query(` SELECT * FROM discorduser WHERE name = $1;`, @@ -26,13 +17,13 @@ const CreateBirthday = async (user, birthday) => { ) } - await client.query(` + const res = await client.query(` INSERT INTO birthday (date, discorduser) VALUES ($1, $2);`, [new Date(birthday.split('.').reverse().join('-')).toISOString().slice(0, 10), user] ) - return true + return res.rowCount > 0 } catch (error) { console.error('Error creating birthday entry:', error) return false @@ -41,6 +32,8 @@ const CreateBirthday = async (user, birthday) => { const ReadBirthday = async (user) => { try { + const client = getClient() + if (user) { const res = await client.query(` SELECT * FROM birthday @@ -62,6 +55,8 @@ const ReadBirthday = async (user) => { const UpdateBirthday = async (user, birthday) => { try { + const client = getClient() + if (!birthday) return false await client.query(` @@ -80,6 +75,8 @@ const UpdateBirthday = async (user, birthday) => { const DeleteBirthday = async (user) => { try { + const client = getClient() + if (!user) return false await client.query(` diff --git a/src/database/blacklistdb.js b/src/database/blacklistdb.js index d782ef6..1a886c2 100644 --- a/src/database/blacklistdb.js +++ b/src/database/blacklistdb.js @@ -1,34 +1,30 @@ -const { client } = require('./database') +const { getClient } = require('./database') const CreateBlacklist = async (reportedUser, reason, reportedByUser) => { try { - const alreadyReportedResult = await client.query(` - SELECT name FROM blacklist - WHERE name = $1`, + const client = getClient() + + const alreadyReportedResult = await client.query( + "SELECT name FROM blacklist WHERE name = $1", [reportedUser] ) - if (alreadyReportedResult.rows.length === 1) { + if (alreadyReportedResult.rows.length === 1) return alreadyReportedResult.rows[0] - } - const userResult = await client.query(` - SELECT * FROM discorduser - WHERE name = $1;`, + const userResult = await client.query( + "SELECT * FROM discorduser WHERE name = $1", [reportedByUser] ) - if (userResult.rows.length === 0) { - await client.query(` - INSERT INTO discorduser (name) - VALUES ($1);`, + if (userResult.rows.length === 0) + await client.query( + "INSERT INTO discorduser (name) VALUES ($1)", [reportedByUser] ) - } - await client.query(` - INSERT INTO blacklist (name, reason, reportedby) - VALUES ($1, $2, $3);`, + await client.query( + "INSERT INTO blacklist (name, reason, reportedby) VALUES ($1, $2, $3)", [reportedUser, reason, reportedByUser] ) @@ -41,16 +37,17 @@ const CreateBlacklist = async (reportedUser, reason, reportedByUser) => { const ReadBlacklist = async (user) => { try { + const client = getClient() + if (user) { - const res = await client.query(` - SELECT * FROM blacklist - WHERE name=$1`, + const res = await client.query( + "SELECT * FROM blacklist WHERE name=$1", [user] ) return res.rows[0] || false } else { - const res = await client.query(` - SELECT * FROM blacklist` + const res = await client.query( + "SELECT * FROM blacklist" ) return res.rows } @@ -62,12 +59,12 @@ const ReadBlacklist = async (user) => { const UpdateBlacklist = async (reportedUser, reason) => { try { + const client = getClient() + if (!reportedUser) return false - await client.query(` - UPDATE blacklist - SET reason = $2 - WHERE name = $1;`, + await client.query( + "UPDATE blacklist SET reason = $2 WHERE name = $1", [reportedUser, reason] ) return true @@ -79,11 +76,12 @@ const UpdateBlacklist = async (reportedUser, reason) => { const DeleteBlacklist = async (user) => { try { + const client = getClient() + if (!user) return false - await client.query(` - DELETE FROM blacklist - WHERE name = $1;`, + await client.query( + "DELETE FROM blacklist WHERE name = $1", [user] ) return true diff --git a/src/database/database.js b/src/database/database.js index abd1d88..073237a 100644 --- a/src/database/database.js +++ b/src/database/database.js @@ -1,25 +1,32 @@ const { Client } = require('pg') -require('dotenv').config() -const DB_USER = process.env.DB_USER -const DB_HOST = process.env.DB_HOST -const DB_NAME = process.env.DB_NAME -const DB_PASS = process.env.DB_PASS -const client = new Client({ - connectionString: `postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_NAME}` -}) +let client = null -const connectDatabase = async () => { +const createClient = (config) => { + client = new Client(config); + return client; +}; + +const connectDatabase = async (client) => { try { await client.connect() console.log('Database connected') } catch (error) { - console.error('Database connection error:', err) + console.error('Database connection error:', error) + throw new Error('Connection failed'); } } +const getClient = () => { + if (!client) { + throw new Error('Client has not been initialized. Call createClient first.'); + } + return client; +}; + module.exports = { - client, + createClient, connectDatabase, + getClient, } diff --git a/src/database/eventdb.js b/src/database/eventdb.js index a03203a..80c1af0 100644 --- a/src/database/eventdb.js +++ b/src/database/eventdb.js @@ -1,9 +1,11 @@ -const { client } = require('./database') +const { getClient } = require('./database') const ReadEvents = async () => { try { - const res = await client.query(` - SELECT * FROM event_times;` + const client = getClient() + + const res = await client.query( + "SELECT * FROM event_times" ) return res.rows } catch (error) { @@ -14,8 +16,10 @@ const ReadEvents = async () => { const GetEventRole = async () => { try { - const res = await client.query(` - SELECT * FROM event_role_view;` + const client = getClient() + + const res = await client.query( + "SELECT * FROM event_role_view" ) const rolesEventMap = new Map() res.rows.forEach(row => rolesEventMap.set(row.event_name, row.role)) @@ -29,8 +33,10 @@ const GetEventRole = async () => { const GetIconRole = async () => { try { - const res = await client.query(` - SELECT role, icon_name FROM event_roles;` + const client = getClient() + + const res = await client.query( + "SELECT role, icon_name FROM event_roles" ) const rolesEventMap = new Map() res.rows.forEach(row => rolesEventMap.set(row.icon_name, row.role)) diff --git a/src/database/staticdb.js b/src/database/staticdb.js index b4593a1..fd25752 100644 --- a/src/database/staticdb.js +++ b/src/database/staticdb.js @@ -1,22 +1,22 @@ -const { client } = require('./database') +const { getClient } = require('./database') const CreateStatic = async (name, creator, members, size) => { try { - await client.query(` - INSERT INTO static (name, creator, size) - VALUES ($1, $2, $3) - RETURNING id;`, + const client = getClient() + + const result = await client.query( + "INSERT INTO static (name, creator, size) VALUES ($1, $2, $3) RETURNING id", [name, creator, size] ) - const staticId = result.rows[0].id; + const staticId = result.rows[0].id - const memberValues = members.map(member => `(${staticId}, '${member}')`).join(',') - - await client.query(` - INSERT INTO static_members (static_id, member) - VALUES ${memberValues};` - ) + for (const member of members) { + await client.query( + "INSERT INTO static_members (static_id, member) VALUES ($1, $2)", + [staticId, member] + ) + } return true } catch (error) { @@ -27,9 +27,10 @@ const CreateStatic = async (name, creator, members, size) => { const ReadStatic = async (name) => { try { - const res = await client.query(` - SELECT * FROM static - WHERE name = $1;`, + const client = getClient() + + const res = await client.query( + "SELECT * FROM static WHERE name = $1", [name] ) return res.rows @@ -41,9 +42,10 @@ const ReadStatic = async (name) => { const DeleteStatic = async (name) => { try { - await client.query(` - DELETE FROM static - WHERE name = $1;`, + const client = getClient() + + await client.query( + "DELETE FROM static WHERE name = $1", [name] ) } catch (error) { diff --git a/src/discord/discordClient.js b/src/discord/discordClient.js index dd8fe3d..da64304 100644 --- a/src/discord/discordClient.js +++ b/src/discord/discordClient.js @@ -1,4 +1,5 @@ const { Client, GatewayIntentBits, Partials, Routes } = require('discord.js') +require('dotenv').config() const { REST } = require('@discordjs/rest') const { SlashCommandBuilder } = require('@discordjs/builders') const { @@ -24,6 +25,8 @@ const { const { startBirthdayCheckCron } = require('../tasks/checkBirthday') const { startEventCheckCron } = require('../tasks/eventReminder') +const rest = new REST({ version: '10' }).setToken(process.env.BOT_TOKEN) + const client = new Client({ intents: [ GatewayIntentBits.Guilds, @@ -135,9 +138,6 @@ client.on('messageReactionRemove', async (reaction, user) => { messageReactionRemove(user, reaction) }) - -const rest = new REST({ version: '10' }).setToken(process.env.BOT_TOKEN) - client.once('ready', async () => { console.log(`Logged in as ${client.user.tag} `) startBirthdayCheckCron(client) diff --git a/src/features/reactionPerRole.js b/src/features/reactionPerRole.js index 1694154..fcc4839 100644 --- a/src/features/reactionPerRole.js +++ b/src/features/reactionPerRole.js @@ -60,7 +60,7 @@ const editReactionMessage = async (client) => { rolesMap.forEach((roleName, iconName) => { const emoji = emojis.find(e => e.name === iconName) if (emoji) - updatedContent += `${emoji}: \`${roleName}\`\n` + updatedContent += `${emoji}: \`${roleName}\`\n\n` else console.log(`Couldn't find emoji ${iconName}`) }) @@ -118,7 +118,7 @@ const createReactionMessage = async (client) => { for (const [iconName, roleName] of rolesMap) { const emoji = emojis.find(e => e.name === iconName) if (emoji) - message += `<:${emoji.name}:${emoji.id}> : \`${roleName}\`\n` + message += `<:${emoji.name}:${emoji.id}> : \`${roleName}\`\n\n` else console.log(`Emoji for ${iconName} not found`) } diff --git a/src/index.js b/src/index.js index 58bfc8b..2c2a076 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,15 @@ const { connectDiscord } = require('./discord/discordClient') -const { connectDatabase } = require('./database/database'); +const { connectDatabase, createClient } = require('./database/database'); +require('dotenv').config(); (async () => { try { - await connectDatabase() - await connectDiscord() + const client = createClient({ + connectionString: `postgresql://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}/${process.env.DB_NAME}` + }) + connectDatabase(client).then(() => { + connectDiscord() + }) } catch (error) { console.log(error) } diff --git a/src/tasks/eventReminder.js b/src/tasks/eventReminder.js index 0c8b7dc..059efd3 100644 --- a/src/tasks/eventReminder.js +++ b/src/tasks/eventReminder.js @@ -36,45 +36,44 @@ const getDayOfWeek = () => new Date(Date.UTC(new Date().getUTCFullYear(), new Da const startEventCheckCron = async (client) => { cron.schedule('45 * * * *', async () => { - console.log('Checking for events...') - if (!eventCache.length) { - await FetchEvents(); - } + await FetchEvents() - const rolesEventMap = await GetEventRole() - - for (const [guildId, oauthGuild] of await client.guilds.fetch()) { + for (const [_, oauthGuild] of await client.guilds.fetch()) { const guild = await oauthGuild.fetch() const channel = (await guild.channels.fetch()).find(ch => ch.name === 'reminder') if (!channel) continue - eventCache.forEach(event => { - let { schedule_id, event_name, start_time, end_time, day_of_week } = event; - console.log(!((!day_of_week || day_of_week === getDayOfWeek()) && isReminderTime(convertToUTC(start_time)))) - // Abbort if its not time to send a reminder - if (!((!day_of_week || day_of_week === getDayOfWeek()) && isReminderTime(convertToUTC(start_time)))) return; + eventCache.forEach(async (event) => { + let { schedule_id, event_name, start_time, end_time, day_of_week } = event + if (!((!day_of_week || day_of_week === getDayOfWeek()) && isReminderTime(convertToUTC(start_time)))) return - const timeComparisonLink = `https://www.timeanddate.com/worldclock/fixedtime.html?iso=${convertToISO(start_time, new Date().toISOString().split('T')[0])}&msg=${encodeURIComponent(event_name)}`; + const rolesEventMap = await GetEventRole() + const role = guild.roles.cache.find(r => r.name === rolesEventMap.get(event_name)) + const roleId = role ? role.id : null - console.log("Sending event...") - console.log(rolesEventMap.get(event_name)) const embed = new EmbedBuilder() .setTitle(event_name) - .setDescription(`${event_name} starts at **${start_time} CEST** and ends at **${end_time} CEST**. \n<@${rolesEventMap.get(event_name)}>\n`) + .setDescription(`${event_name} starts at **${start_time} CEST** and ends at **${end_time} CEST**. \n ${roleId ? `<@&${roleId}>` : 'No role assigned'} \n`) .addFields( { name: 'Day of Week', value: day_of_week ? day_of_week : 'Daily', inline: true }, - { name: 'Compare Time', value: `[Click here to compare event time to your local time](${timeComparisonLink})`, inline: true } + { + name: 'Compare Time', + value: `[Click here to compare event time to your local time](https://www.timeanddate.com/worldclock/fixedtime.html?iso=${convertToISO(start_time, new Date().toISOString().split('T')[0])}&msg=${encodeURIComponent(event_name)})`, + inline: true + } ) .setFooter({ text: `Schedule ID: ${schedule_id}` }) - .setColor('#00FF00'); + .setColor('#00FF00') - channel.send({ embeds: [embed] }).catch(console.error); - }); + await channel.send({ embeds: [embed] }).catch(console.error) + }) } - }); + }) } + + module.exports = { startEventCheckCron, }