diff --git a/config/config.js b/config/config.js index 2caa826..4c31809 100644 --- a/config/config.js +++ b/config/config.js @@ -2,7 +2,7 @@ require('dotenv').config(); module.exports = { Dev: "PROD.", - Version: "13.1.5", // (major).(feature).(revision/bug/refactoring) + Version: "13.1.6", // (major).(feature).(revision/bug/refactoring) Admins: ["362791661274660874", "329371697570381824"], // Admins of the bot DefaultPrefix: "?", ServerID: "955668596745461830", diff --git a/package-lock.json b/package-lock.json index e220ddf..bfc46fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "discord-bitfield-calculator": "^1.0.0", "discord.js": "^14.3.0", "dotenv": "^16.0.2", + "fs": "^0.0.1-security", "mongodb": "^4.7.0", "mongoose": "^6.4.2", "winston": "^3.8.1" @@ -454,6 +455,11 @@ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -1502,6 +1508,11 @@ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", diff --git a/package.json b/package.json index 4e34e0d..f723542 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "discord-bitfield-calculator": "^1.0.0", "discord.js": "^14.3.0", "dotenv": "^16.0.2", + "fs": "^0.0.1-security", "mongodb": "^4.7.0", "mongoose": "^6.4.2", "winston": "^3.8.1" diff --git a/structures/QuarksBot.js b/structures/QuarksBot.js index a2dd455..a915c67 100644 --- a/structures/QuarksBot.js +++ b/structures/QuarksBot.js @@ -25,6 +25,7 @@ class QuarksBot extends Client { this.db; this.dbo; this.connectMongo(this.config.mongoURI, this.config.dbo); + this.databaseConnected = false; this.LoadCommandsAndInteractionHandlers(); this.LoadEvents(); @@ -52,6 +53,15 @@ class QuarksBot extends Client { } }); }; + + if (!this.databaseConnected) { + let dbFailedEmbed = new EmbedBuilder() + .setDescription(`**Internal Error:**\nUh Oh D: Its not you, its me.\nThe bot has failed to connect to the database 5 times!\nContact the Developers\nhttps://discord.gg/YCXhvy9uZw`) + .setColor(this.config.Colors.Red) + + return interaction.send({ embeds: [dbFailedEmbed] }); + } + let cmd = client.commands.get(command); try { cmd.SlashCommand.run(this, interaction, args, { GuildDB }, start); // start is only used in ping / stats command @@ -65,16 +75,43 @@ class QuarksBot extends Client { } async connectMongo(mongoURI, dbo) { + let failed = false; + + let dbLogDir = path.join(__dirname, '..', 'logs', 'database-logs.json'); + let databaselogs; try { - // Connect to MongoDB database. - this.db = await MongoClient.connect(mongoURI, {connectTimeoutMS: 5000}); + databaselogs = JSON.parse(fs.readFileSync(dbLogDir)); + } catch (err) { + databaselogs = { + attempts: 0, + connected: false, + }; + } + + if (databaselogs.attempts >= 5) { + this.error('Failed to connect to mongodb after multiple attempts'); + return; // prevent further attempts + } + + try { + // Connect to Mongo database. + this.db = await MongoClient.connect(mongoURI, {connectTimeoutMS: 1000}); this.dbo = this.db.db(dbo); mongoose.connect(`${mongoURI}/${dbo}`); this.log('Successfully connected to mongoDB'); + databaselogs.connected = true; + databaselogs.attempts = 0; // reset attempts + this.databaseConnected = true; } catch (err) { - this.error('Failed to connect to mongodb'); - process.exit(-1); + databaselogs.attempts++; + this.error(`Failed to connect to mongodb: attempt ${databaselogs.attempts}`); + failed = true; } + + // write JSON string to a file + await fs.writeFileSync(dbLogDir, JSON.stringify(databaselogs)); + + if (failed) process.exit(-1); } exists(n) {return null != n && undefined != n && "" != n} @@ -155,7 +192,8 @@ class QuarksBot extends Client { } async GetGuild(GuildId) { - let guild = await this.dbo.collection("guilds").findOne({"server.serverID":GuildId}).then(guild => guild); + let guild = undefined; + if (this.databaseConnected) guild = await this.dbo.collection("guilds").findOne({"server.serverID":GuildId}).then(guild => guild); // If guild not found, generate guild default if (!guild) { @@ -178,9 +216,11 @@ class QuarksBot extends Client { canIgnoreInvoices: true, } } - this.dbo.collection("guilds").insertOne(guild, function(err, res) { - if (err) throw err; - }); + if (this.databaseConnected) { + this.dbo.collection("guilds").insertOne(guild, function(err, res) { + if (err) throw err; + }); + } } let guildData = {