Browse Source

Switch to postgres

Markus-Rost 4 years ago
parent
commit
5727f4e8b7
10 changed files with 592 additions and 712 deletions
  1. 39 21
      cmds/eval.js
  2. 178 206
      cmds/patreon.js
  3. 100 141
      cmds/rcscript.js
  4. 61 82
      cmds/settings.js
  5. 34 49
      cmds/verification.js
  6. 1 1
      cmds/voice.js
  7. 47 57
      dashboard/rcscript.js
  8. 94 106
      dashboard/settings.js
  9. 37 48
      dashboard/verification.js
  10. 1 1
      database.js

+ 39 - 21
cmds/eval.js

@@ -169,14 +169,14 @@ function removePatreons(guild, msg) {
 	if ( !( typeof guild === 'string' || msg instanceof Discord.Message ) ) {
 		return 'removePatreons(guild, msg) – No guild or message provided!';
 	}
-	var messages = [];
-	db.connect().then( client => {
-		client.query( 'SELECT lang, inline FROM discord WHERE guild = $1 AND channel IS NULL', [guild] ).then( ({rows:[row]}) => {
+	return db.connect().then( client => {
+		var messages = [];
+		return client.query( 'SELECT lang, role, inline FROM discord WHERE guild = $1 AND channel IS NULL', [guild] ).then( ({rows:[row]}) => {
 			if ( !row ) {
 				messages.push('The guild doesn\'t exist!');
 				return Promise.reject();
 			}
-			return client.query( 'UPDATE discord SET lang = $1, inline = $2, prefix = $3, patreon = NULL WHERE guild = $4', [row.lang, row.inline, process.env.prefix, guild] ).then( ({rowCount}) => {
+			return client.query( 'UPDATE discord SET lang = $1, role = $2, inline = $3, prefix = $4, patreon = NULL WHERE guild = $5', [row.lang, row.role, row.inline, process.env.prefix, guild] ).then( ({rowCount}) => {
 				if ( rowCount ) {
 					console.log( '- Guild successfully updated.' );
 					messages.push('Guild successfully updated.');
@@ -243,18 +243,21 @@ function removePatreons(guild, msg) {
 				messages.push('Error while updating the RcGcDw: ' + dberror);
 			} );
 		} ).then( () => {
+			if ( !messages.length ) messages.push('No settings found that had to be removed.');
 			return messages;
 		}, error => {
 			if ( error ) {
 				console.log( '- Error while removing the patreon features: ' + error );
 				messages.push('Error while removing the patreon features: ' + error);
 			}
+			if ( !messages.length ) messages.push('No settings found that had to be removed.');
 			return messages;
 		} ).finally( () => {
 			client.release();
 		} );
 	}, dberror => {
 		console.log( '- Error while connecting to the database client: ' + dberror );
+		return 'Error while connecting to the database client: ' + dberror;
 	} );
 }
 
@@ -264,8 +267,9 @@ function removePatreons(guild, msg) {
  */
 function removeSettings(msg) {
 	if ( !( msg instanceof Discord.Message ) ) return 'removeSettings(msg) – No message provided!';
-	try {
-		msg.client.shard.broadcastEval( `[
+	return db.connect().then( client => {
+		var messages = [];
+		return msg.client.shard.broadcastEval( `[
 			[...this.guilds.cache.keys()],
 			this.channels.cache.filter( channel => {
 				return ( channel.isGuild() || ( channel.type === 'category' && global.patreons.hasOwnProperty(channel.guild.id) ) );
@@ -275,8 +279,8 @@ function removeSettings(msg) {
 			var all_channels = results.map( result => result[1] ).reduce( (acc, val) => acc.concat(val), [] );
 			var guilds = [];
 			var channels = [];
-			db.query( 'SELECT guild, channel FROM discord' ).then( ({rows}) => {
-				rows.forEach( row => {
+			return client.query( 'SELECT guild, channel FROM discord' ).then( ({rows}) => {
+				return rows.forEach( row => {
 					if ( !all_guilds.includes(row.guild) ) {
 						if ( !row.channel ) {
 							if ( patreons.hasOwnProperty(row.guild) || voice.hasOwnProperty(row.guild) ) {
@@ -290,33 +294,47 @@ function removeSettings(msg) {
 						return channels.push(row.channel);
 					}
 				} );
+			}, dberror => {
+				console.log( '- Error while getting the settings: ' + dberror );
+				messages.push('Error while getting the settings: ' + dberror);
+			} ).then( () => {
 				if ( guilds.length ) {
-					db.query( 'DELETE FROM discord WHERE main IN (' + guilds.map( (guild, i) => '$' + ( i + 1 ) ).join(', ') + ')', guilds ).then( ({rowCount}) => {
+					return client.query( 'DELETE FROM discord WHERE main IN (' + guilds.map( (guild, i) => '$' + ( i + 1 ) ).join(', ') + ')', guilds ).then( ({rowCount}) => {
 						console.log( '- Guilds successfully removed: ' + rowCount );
+						messages.push('Guilds successfully removed: ' + rowCount);
 					}, dberror => {
 						console.log( '- Error while removing the guilds: ' + dberror );
-						msg.replyMsg( 'I got an error while removing the guilds!', {}, true );
+						messages.push('Error while removing the guilds: ' + dberror);
 					} );
 				}
+			} ).then( () => {
 				if ( channels.length ) {
-					db.query( 'DELETE FROM discord WHERE channel IN (' + channels.map( (channel, i) => '$' + ( i + 1 ) ).join(', ') + ')', channels ).then( ({rowCount}) => {
+					return client.query( 'DELETE FROM discord WHERE channel IN (' + channels.map( (channel, i) => '$' + ( i + 1 ) ).join(', ') + ')', channels ).then( ({rowCount}) => {
 						console.log( '- Channels successfully removed: ' + rowCount );
+						messages.push('Channels successfully removed: ' + rowCount);
 					}, dberror => {
 						console.log( '- Error while removing the channels: ' + dberror );
-						msg.replyMsg( 'I got an error while removing the channels!', {}, true );
+						messages.push('Error while removing the channels: ' + dberror);
 					} );
 				}
-				if ( !guilds.length && !channels.length ) console.log( '- Settings successfully removed.' );
-			}, dberror => {
-				console.log( '- Error while getting the settings: ' + dberror );
-				msg.replyMsg( 'I got an error while getting the settings!', {}, true );
 			} );
+		} ).then( () => {
+			if ( !messages.length ) messages.push('No settings found that had to be removed.');
+			return messages;
+		}, error => {
+			if ( error ) {
+				console.log( '- Error while removing the settings: ' + error );
+				messages.push('Error while removing the settings: ' + error);
+			}
+			if ( !messages.length ) messages.push('No settings found that had to be removed.');
+			return messages;
+		} ).finally( () => {
+			client.release();
 		} );
-	}
-	catch ( tryerror ) {
-		console.log( '- Error while removing the settings: ' + tryerror );
-		return 'removeSettings(msg) – Error while removing the settings: ' + tryerror;
-	}
+	}, dberror => {
+		console.log( '- Error while connecting to the database client: ' + dberror );
+		return 'Error while connecting to the database client: ' + dberror;
+	} );
 }
 
 module.exports = {

+ 178 - 206
cmds/patreon.js

@@ -24,271 +24,243 @@ function cmd_patreon(lang, msg, args, line, wiki) {
 			msg.replyMsg( 'I\'m not on a server with the id `' + args[1] + '`.\n<' + invite + '%20applications.commands' + '>', {}, true )
 		}, log_error );
 		if ( patreons[args[1]] ) return msg.replyMsg( '"' + guild + '" has the patreon features already enabled.', {}, true );
-		db.get( 'SELECT count, COUNT(guild) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = ? GROUP BY patreons.patreon', [msg.author.id], (dberror, row) => {
-			if ( dberror ) {
-				console.log( '- Error while getting the patreon: ' + dberror );
-				msg.replyMsg( 'I got an error while searching for you, please try again later.', {}, true );
-				return dberror;
-			}
-			if ( !row ) return msg.replyMsg( 'you can\'t have any server.', {}, true );
+		db.query( 'SELECT count, COUNT(guild) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = $1 GROUP BY patreons.patreon', [msg.author.id] ).then( ({rows:[row]}) => {
+			if ( !row ) return msg.replyMsg( 'you can\'t have any servers.', {}, true );
 			if ( row.count <= row.guilds ) return msg.replyMsg( 'you already reached your maximal server count.', {}, true );
 			if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
-			db.run( 'UPDATE discord SET patreon = ? WHERE guild = ? AND channel IS NULL', [msg.author.id, args[1]], function (error) {
-				if ( error ) {
-					console.log( '- Error while updating the guild: ' + error );
-					msg.replyMsg( 'I got an error while updating the server, please try again later.', {}, true );
-					return error;
-				}
-				if ( !this.changes ) return db.run( 'INSERT INTO discord(main, guild, patreon) VALUES(?, ?, ?)', [args[1], args[1], msg.author.id], function (inserror) {
-					if ( inserror ) {
-						console.log( '- Error while adding the guild: ' + inserror );
-						msg.replyMsg( 'I got an error while updating the server, please try again later.', {}, true );
-						return inserror;
-					}
+			db.query( 'UPDATE discord SET patreon = $1 WHERE guild = $2 AND channel IS NULL', [msg.author.id, args[1]] ).then( ({rowCount}) => {
+				if ( !rowCount ) return db.query( 'INSERT INTO discord(main, guild, patreon) VALUES($1, $1, $2)', [args[1], msg.author.id] ).then( () => {
 					console.log( '- Guild successfully added.' );
 					msg.client.shard.broadcastEval( `global.patreons['${args[1]}'] = '${process.env.prefix}'` );
 					msg.replyMsg( 'the patreon features are now enabled on "' + guild + '".', {}, true );
+				}, dberror => {
+					console.log( '- Error while adding the guild: ' + dberror );
+					msg.replyMsg( 'I got an error while updating the server, please try again later.', {}, true );
 				} );
 				console.log( '- Guild successfully updated.' );
 				msg.client.shard.broadcastEval( `global.patreons['${args[1]}'] = '${process.env.prefix}'` );
 				msg.replyMsg( 'the patreon features are now enabled on "' + guild + '".', {}, true );
+			}, dberror => {
+				console.log( '- Error while updating the guild: ' + dberror );
+				msg.replyMsg( 'I got an error while updating the server, please try again later.', {}, true );
 			} );
+		}, dberror => {
+			console.log( '- Error while getting the patreon: ' + dberror );
+			msg.replyMsg( 'I got an error while searching for you, please try again later.', {}, true );
 		} );
 	} );
 	
 	if ( args[0] === 'disable' && /^\d+$/.test(args.slice(1).join(' ')) ) return msg.client.shard.broadcastEval( `this.guilds.cache.get('${args[1]}')?.name`, shardIDForGuildID(args[1], msg.client.shard.count) ).then( guild => {
 		if ( !guild ) return msg.replyMsg( 'I\'m not on a server with the id `' + args[1] + '`.', {}, true );
 		if ( !patreons[args[1]] ) return msg.replyMsg( '"' + guild + '" doesn\'t have the patreon features enabled.', {}, true );
-		db.get( 'SELECT lang, inline FROM discord WHERE guild = ? AND patreon = ?', [args[1], msg.author.id], (dberror, row) => {
-			if ( dberror ) {
-				console.log( '- Error while getting the guild: ' + dberror );
-				msg.replyMsg( 'I got an error while searching for the server, please try again later.', {}, true );
-				return dberror;
-			}
-			if ( !row ) return msg.replyMsg( 'you didn\'t enable the patreon features for "' + guild + '"!', {}, true );
-			if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
-			db.run( 'UPDATE discord SET lang = ?, inline = ?, prefix = ?, patreon = NULL WHERE guild = ?', [row.lang, row.inline, process.env.prefix, args[1]], function (error) {
-				if ( error ) {
-					console.log( '- Error while updating the guild: ' + error );
+		return db.connect().then( client => {
+			return client.query( 'SELECT lang, role, inline FROM discord WHERE guild = $1 AND patreon = $2', [args[1], msg.author.id] ).then( ({rows:[row]}) => {
+				if ( !row ) return msg.replyMsg( 'you didn\'t enable the patreon features for "' + guild + '"!', {}, true );
+				if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
+				return client.query( 'UPDATE discord SET lang = $1, role = $2, inline = $3, prefix = $4, patreon = NULL WHERE guild = $5', [row.lang, row.role, row.inline, process.env.prefix, args[1]] ).then( () => {
+					console.log( '- Guild successfully updated.' );
+					msg.client.shard.broadcastEval( `delete global.patreons['${args[1]}']` );
+					msg.replyMsg( 'the patreon features are now disabled on "' + guild + '".', {}, true );
+				} ).then( () => {
+					return client.query( 'DELETE FROM discord WHERE guild = $1 AND channel LIKE $2', [args[1], '#%'] ).then( ({rowCount}) => {
+						if ( dberror ) {
+							console.log( '- Error while deleting the channel categories: ' + dberror );
+							return dberror;
+						}
+						if ( rowCount ) console.log( '- Channel categories successfully deleted.' );
+					} );
+				} ).then( () => {
+					return client.query( 'SELECT configid FROM verification WHERE guild = $1 ORDER BY configid ASC OFFSET $2', [args[1], verificationLimit.default] ).then( ({rows}) => {
+						if ( rows.length ) {
+							return client.query( 'DELETE FROM verification WHERE guild = $1 AND configid IN (' + rows.map( (row, i) => '$' + ( i + 2 ) ).join(', ') + ')', [args[1], ...rows.map( row => row.configid )] ).then( () => {
+								console.log( '- Verifications successfully deleted.' );
+							}, dberror => {
+								console.log( '- Error while deleting the verifications: ' + dberror );
+							} );
+						}
+					}, dberror => {
+						console.log( '- Error while getting the verifications: ' + dberror );
+					} );
+				} ).then( () => {
+					return client.query( 'SELECT webhook FROM rcgcdw WHERE guild = $1 ORDER BY configid ASC OFFSET $2', [args[1], rcgcdwLimit.default] ).then( ({rows}) => {
+						if ( rows.length ) {
+							return client.query( 'DELETE FROM rcgcdw WHERE webhook IN (' + rows.map( (row, i) => '$' + ( i + 1 ) ).join(', ') + ')', rows.map( row => row.webhook ) ).then( () => {
+								console.log( '- RcGcDw successfully deleted.' );
+								rows.forEach( row => msg.client.fetchWebhook(...row.webhook.split('/')).then( webhook => {
+									webhook.delete('Removed extra recent changes webhook').catch(log_error);
+								}, log_error ) );
+							}, dberror => {
+								console.log( '- Error while deleting the RcGcDw: ' + dberror );
+							} );
+						}
+					}, dberror => {
+						console.log( '- Error while getting the RcGcDw: ' + dberror );
+					} );
+				} ).then( () => {
+					return client.query( 'UPDATE rcgcdw SET display = $1 WHERE guild = $2 AND display > $1', [rcgcdwLimit.display, args[1]] ).then( () => {
+						console.log( '- RcGcDw successfully updated.' );
+					}, dberror => {
+						console.log( '- Error while updating the RcGcDw: ' + dberror );
+					} );
+				}, dberror => {
+					console.log( '- Error while updating the guild: ' + dberror );
 					msg.replyMsg( 'I got an error while updating the server, please try again later.', {}, true );
-					return error;
-				}
-				console.log( '- Guild successfully updated.' );
-				msg.client.shard.broadcastEval( `delete global.patreons['${args[1]}']` );
-				msg.replyMsg( 'the patreon features are now disabled on "' + guild + '".', {}, true );
-			} );
-			db.run( 'DELETE FROM discord WHERE guild = ? AND channel LIKE ?', [args[1], '#%'], function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while deleting the channel categories: ' + dberror );
-					return dberror;
-				}
-				if ( this.changes ) console.log( '- Channel categories successfully deleted.' );
-			} );
-			db.all( 'SELECT configid FROM verification WHERE guild = ? ORDER BY configid ASC', [args[1]], (dberror, rows) => {
-				if ( dberror ) {
-					console.log( '- Error while getting the verifications: ' + dberror );
-					return dberror;
-				}
-				var ids = rows.slice(verificationLimit.default).map( row => row.configid );
-				if ( ids.length ) db.run( 'DELETE FROM verification WHERE guild = ? AND configid IN (' + ids.map( configid => '?' ).join(', ') + ')', [args[1], ...ids], function (error) {
-					if ( error ) {
-						console.log( '- Error while deleting the verifications: ' + error );
-						return error;
-					}
-					console.log( '- Verifications successfully deleted.' );
-				} );
-			} );
-			db.all( 'SELECT webhook FROM rcgcdw WHERE guild = ? ORDER BY configid ASC', [args[1]], (dberror, rows) => {
-				if ( dberror ) {
-					console.log( '- Error while getting the RcGcDw: ' + dberror );
-					return dberror;
-				}
-				var webhooks = rows.slice(rcgcdwLimit.default).map( row => row.webhook );
-				if ( webhooks.length ) db.run( 'DELETE FROM rcgcdw WHERE webhook IN (' + webhooks.map( webhook => '?' ).join(', ') + ')', webhooks, function (error) {
-					if ( error ) {
-						console.log( '- Error while deleting the RcGcDw: ' + error );
-						return error;
-					}
-					console.log( '- RcGcDw successfully deleted.' );
-					webhooks.forEach( hook => msg.client.fetchWebhook(...hook.split('/')).then( webhook => {
-						webhook.delete('Removed extra recent changes webhook').catch(log_error);
-					}, log_error ) );
 				} );
+			}, dberror => {
+				console.log( '- Error while getting the guild: ' + dberror );
+				msg.replyMsg( 'I got an error while searching for the server, please try again later.', {}, true );
+			} ).finally( () => {
+				client.release();
 			} );
-			db.run( 'UPDATE rcgcdw SET display = ? WHERE guild = ? AND display > ?', [rcgcdwLimit.display, args[1], rcgcdwLimit.display], function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while updating the RcGcDw: ' + dberror );
-					return dberror;
-				}
-				console.log( '- RcGcDw successfully updated.' );
-			} );
+		}, dberror => {
+			console.log( '- Error while connecting to the database client: ' + dberror );
+			msg.replyMsg( 'I got an error while searching for the server, please try again later.', {}, true );
 		} );
 	} );
 	
 	if ( args[1] ) args[1] = args[1].replace( /^\\?<@!?(\d+)>$/, '$1' );
 	
 	if ( args[0] === 'check' ) {
-		if ( !args.slice(1).join('') ) return db.get( 'SELECT count, GROUP_CONCAT(guild) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = ? GROUP BY patreons.patreon', [msg.author.id], (dberror, row) => {
-			if ( dberror ) {
-				console.log( '- Error while getting the patreon: ' + dberror );
-				msg.replyMsg( 'I got an error while searching for you, please try again later.', {}, true );
-				return dberror;
-			}
-			if ( !row ) return msg.replyMsg( 'you can\'t have any server.', {}, true );
-			var text = 'you can have up to ' + row.count + ' server.\n\n';
-			if ( row.guilds ) {
-				msg.client.shard.broadcastEval( `'${row.guilds}'.split(',').map( guild => this.guilds.cache.get(guild)?.name )` ).then( results => {
-					var guilds = row.guilds.split(',').map( (guild, i) => '`' + guild + '` ' + ( results.find( result => result[i] !== null )?.[i] || '' ) );
-					text += 'Currently you have ' + guilds.length + ' server:\n' + guilds.join('\n');
+		if ( !args.slice(1).join('') ) return db.query( 'SELECT count, ARRAY_REMOVE(ARRAY_AGG(guild), NULL) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = $1 GROUP BY patreons.patreon', [msg.author.id] ).then( ({rows:[row]}) => {
+			if ( !row ) return msg.replyMsg( 'you can\'t have any servers.', {}, true );
+			var text = 'you can have up to ' + row.count + ' servers.\n\n';
+			if ( row.guilds.length ) {
+				msg.client.shard.broadcastEval( `${JSON.stringify(row.guilds)}.map( guild => this.guilds.cache.get(guild)?.name )` ).then( results => {
+					var guilds = row.guilds.map( (guild, i) => '`' + guild + '` ' + ( results.find( result => result[i] !== null )?.[i] || '' ) );
+					text += 'Currently you have ' + guilds.length + ' servers:\n' + guilds.join('\n');
+					if ( row.count < guilds.length ) text += '\n\n**You are above your server limit!**';
 					msg.replyMsg( text, {}, true );
 				} );
 			}
 			else {
-				text += '*You don\'t have any server yet.*';
+				text += '*You don\'t have any servers yet.*';
 				msg.replyMsg( text, {}, true );
 			}
+		}, dberror => {
+			console.log( '- Error while getting the patreon: ' + dberror );
+			msg.replyMsg( 'I got an error while searching for you, please try again later.', {}, true );
 		} );
-		if ( msg.isOwner() && /^\d+$/.test(args.slice(1).join(' ')) ) return db.get( 'SELECT count, GROUP_CONCAT(guild) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = ? GROUP BY patreons.patreon', [args[1]], (dberror, row) => {
-			if ( dberror ) {
-				console.log( '- Error while getting the patreon: ' + dberror );
-				msg.replyMsg( 'I got an error while searching for <@' + args[1] + '>, please try again later.', {}, true );
-				return dberror;
-			}
-			if ( !row ) return msg.replyMsg( '<@' + args[1] + '> can\'t have any server.', {}, true );
-			var text = '<@' + args[1] + '> can have up to ' + row.count + ' server.\n\n';
-			if ( row.guilds ) {
-				msg.client.shard.broadcastEval( `'${row.guilds}'.split(',').map( guild => this.guilds.cache.get(guild)?.name )` ).then( results => {
-					var guilds = row.guilds.split(',').map( (guild, i) => '`' + guild + '` ' + ( results.find( result => result[i] !== null )?.[i] || '' ) );
-					text += 'Currently they have ' + guilds.length + ' server:\n' + guilds.join('\n');
+		if ( msg.isOwner() && /^\d+$/.test(args.slice(1).join(' ')) ) return db.query( 'SELECT count, ARRAY_REMOVE(ARRAY_AGG(guild), NULL) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = $1 GROUP BY patreons.patreon', [args[1]] ).then( ({rows:[row]}) => {
+			if ( !row ) return msg.replyMsg( '<@' + args[1] + '> can\'t have any servers.', {}, true );
+			var text = '<@' + args[1] + '> can have up to ' + row.count + ' servers.\n\n';
+			if ( row.guilds.length ) {
+				msg.client.shard.broadcastEval( `${JSON.stringify(row.guilds)}.map( guild => this.guilds.cache.get(guild)?.name )` ).then( results => {
+					var guilds = row.guilds.map( (guild, i) => '`' + guild + '` ' + ( results.find( result => result[i] !== null )?.[i] || '' ) );
+					text += 'Currently they have ' + guilds.length + ' servers:\n' + guilds.join('\n');
+					if ( row.count < guilds.length ) text += '\n\n**They are above their server limit!**';
 					msg.replyMsg( text, {}, true );
 				} );
 			}
 			else {
-				text += '*They don\'t have any server yet.*';
+				text += '*They don\'t have any servers yet.*';
 				msg.replyMsg( text, {}, true );
 			}
+		}, dberror => {
+			console.log( '- Error while getting the patreon: ' + dberror );
+			msg.replyMsg( 'I got an error while searching for <@' + args[1] + '>, please try again later.', {}, true );
 		} );
 	}
 	
-	if ( args[0] === 'edit' && msg.isOwner() && /^\d+ [\+\-]?\d+$/.test(args.slice(1).join(' ')) ) return db.get( 'SELECT count, GROUP_CONCAT(guild) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = ? GROUP BY patreons.patreon', [args[1]], (dberror, row) => {
-		if ( dberror ) {
-			console.log( '- Error while getting the patreon: ' + dberror );
-			msg.replyMsg( 'I got an error while searching for <@' + args[1] + '>, please try again later.', {}, true );
-			return dberror;
-		}
+	if ( args[0] === 'edit' && msg.isOwner() && /^\d+ [\+\-]?\d+$/.test(args.slice(1).join(' ')) ) return db.query( 'SELECT count, ARRAY_REMOVE(ARRAY_AGG(guild), NULL) guilds FROM patreons LEFT JOIN discord ON discord.patreon = patreons.patreon WHERE patreons.patreon = $1 GROUP BY patreons.patreon', [args[1]] ).then( ({rows:[row]}) => {
 		var value = parseInt(args[2], 10);
 		var count = ( row ? row.count : 0 );
-		var guilds = ( row && row.guilds ? row.guilds.split(',') : [] );
+		var guilds = ( row ? row.guilds : [] );
 		if ( args[2].startsWith( '+' ) || args[2].startsWith( '-' ) ) count += value;
 		else count = value;
 		if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
-		if ( count <= 0 ) return db.run( 'DELETE FROM patreons WHERE patreon = ?', [args[1]], function (error) {
-			if ( error ) {
-				console.log( '- Error while deleting the patreon: ' + error );
+		if ( count <= 0 ) return db.connect().then( client => {
+			return client.query( 'DELETE FROM patreons WHERE patreon = $1', [args[1]] ).then( () => {
+				console.log( '- Patreon successfully deleted.' );
+				msg.replyMsg( '<@' + args[1] + '> is no longer a patreon.', {}, true );
+				if ( !guilds.length ) return Promise.reject();
+				msg.client.shard.broadcastEval( `${JSON.stringify(row.guilds)}.forEach( guild => delete global.patreons[guild] )` );
+			}, dberror => {
+				console.log( '- Error while deleting the patreon: ' + dberror );
 				msg.replyMsg( 'I got an error while deleting <@' + args[1] + '>, please try again later.', {}, true );
-				return error;
-			}
-			console.log( '- Patreon successfully deleted.' );
-			if ( !guilds.length ) return msg.replyMsg( '<@' + args[1] + '> is no longer a patreon.', {}, true );
-			db.each( 'SELECT guild, lang, inline FROM discord WHERE guild IN (' + guilds.map( guild => '?' ).join(', ') + ') AND channel IS NULL', guilds, (eacherror, eachrow) => {
-				if ( eacherror ) {
-					console.log( '- Error while getting the guild: ' + eacherror );
-					msg.replyMsg( 'I couldn\'t disable the patreon features.', {}, true );
-					return eacherror;
-				}
-				db.run( 'UPDATE discord SET lang = ?, inline = ?, prefix = ?, patreon = NULL WHERE guild = ?', [eachrow.lang, eachrow.inline, process.env.prefix, eachrow.guild], function (uperror) {
-					if ( uperror ) {
-						console.log( '- Error while updating the guild: ' + uperror );
-						msg.replyMsg( 'I couldn\'t disable the patreon features for `' + eachrow.guild + '`.', {}, true );
-						return uperror;
-					}
-					console.log( '- Guild successfully updated.' );
-					msg.client.shard.broadcastEval( `delete global.patreons['${eachrow.guild}']` );
+				return Promise.reject();
+			} ).then( () => {
+				return client.query( 'SELECT guild, lang, role, inline FROM discord WHERE guild IN (' + guilds.map( (guild, i) => '$' + ( i + 1 ) ).join(', ') + ') AND channel IS NULL', guilds ).then( ({rows}) => {
+					return Promise.all(rows.map( row => {
+						return client.query( 'UPDATE discord SET lang = $1, role = $2, inline = $3, prefix = $4, patreon = NULL WHERE guild = $5', [row.lang, row.role, row.inline, process.env.prefix, row.guild] ).then( () => {
+							console.log( '- Guild successfully updated.' );
+						}, dberror => {
+							console.log( '- Error while updating the guild: ' + dberror );
+						} );
+					} ));
+				}, dberror => {
+					console.log( '- Error while getting the guilds: ' + dberror );
 				} );
-			}, (eacherror) => {
-				if ( eacherror ) {
-					console.log( '- Error while getting the guilds: ' + eacherror );
-					msg.replyMsg( 'I couldn\'t disable the patreon features for `' + guilds.join('`, `') + '`.', {}, true );
-					return eacherror;
-				}
-				msg.replyMsg( '<@' + args[1] + '> is no longer a patreon.', {}, true );
-			} );
-			db.run( 'DELETE FROM discord WHERE guild IN (' + guilds.map( guild => '?' ).join(', ') + ') AND channel LIKE ?', [...guilds, '#%'], function (uperror) {
-				if ( uperror ) {
-					console.log( '- Error while deleting the channel categories: ' + uperror );
-					return uperror;
-				}
-				if ( this.changes ) console.log( '- Channel categories successfully deleted.' );
-			} );
-			db.each( 'SELECT a.guild, GROUP_CONCAT(DISTINCT a.configid) configids FROM verification a LEFT JOIN verification b ON a.guild = b.guild WHERE a.guild IN (' + guilds.map( guild => '?' ).join(', ') + ') GROUP BY a.guild', guilds, (eacherror, eachrow) => {
-				if ( eacherror ) {
-					console.log( '- Error while getting the verifications: ' + eacherror );
-					return eacherror;
-				}
-				var ids = eachrow.configids.split(',').slice(verificationLimit.default);
-				if ( ids.length ) db.run( 'DELETE FROM verification WHERE guild = ? AND configid IN (' + ids.map( configid => '?' ).join(', ') + ')', [eachrow.guild, ...ids], function (uperror) {
-					if ( uperror ) {
-						console.log( '- Error while deleting the verifications: ' + uperror );
-						return uperror;
-					}
-					console.log( '- Verifications successfully deleted.' );
+			} ).then( () => {
+				return client.query( 'DELETE FROM discord WHERE guild IN (' + guilds.map( (guild, i) => '$' + ( i + 2 ) ).join(', ') + ') AND channel LIKE $1', ['#%', ...guilds] ).then( ({rowCount}) => {
+					if ( rowCount ) console.log( '- Channel categories successfully deleted.' );
+				}, dberror => {
+					console.log( '- Error while deleting the channel categories: ' + dberror );
 				} );
-			}, (eacherror) => {
-				if ( eacherror ) {
-					console.log( '- Error while getting the verifications: ' + eacherror );
-					return eacherror;
-				}
-			} );
-			db.each( 'SELECT GROUP_CONCAT(DISTINCT a.webhook) webhooks FROM rcgcdw a LEFT JOIN verification b ON a.guild = b.guild WHERE a.guild IN (' + guilds.map( guild => '?' ).join(', ') + ') GROUP BY a.guild', guilds, (eacherror, eachrow) => {
-				if ( eacherror ) {
-					console.log( '- Error while getting the RcGcDw: ' + eacherror );
-					return eacherror;
-				}
-				var webhooks = eachrow.webhooks.split(',').slice(rcgcdwLimit.default);
-				if ( webhooks.length ) db.run( 'DELETE FROM rcgcdw WHERE webhook IN (' + webhooks.map( webhook => '?' ).join(', ') + ')', webhooks, function (uperror) {
-					if ( uperror ) {
-						console.log( '- Error while deleting the RcGcDw: ' + uperror );
-						return uperror;
+			} ).then( () => {
+				return client.query( 'SELECT guild, (ARRAY_AGG(configid ORDER BY configid))[' + ( verificationLimit.default + 1 ) + ':] configids FROM verification WHERE guild IN (' + guilds.map( (guild, i) => '$' + ( i + 1 ) ).join(', ') + ') GROUP BY guild', guilds ).then( ({rows}) => {
+					if ( !rows.length ) return;
+					rows = rows.filter( row => row.configids.length );
+					if ( rows.length ) return Promise.all(rows.map( row => {
+						return client.query( 'DELETE FROM verification WHERE guild = $1 AND configid IN (' + row.configids.map( (configid, i) => '$' + ( i + 2 ) ).join(', ') + ')', [row.guild, ...row.configids] ).then( () => {
+							console.log( '- Verifications successfully deleted.' );
+						}, dberror => {
+							console.log( '- Error while deleting the verifications: ' + dberror );
+						} );
+					} ));
+				}, dberror => {
+					console.log( '- Error while getting the verifications: ' + dberror );
+				} );
+			} ).then( () => {
+				return client.query( 'SELECT (ARRAY_AGG(webhook ORDER BY configid))[' + ( rcgcdwLimit.default + 1 ) + ':] webhooks FROM rcgcdw WHERE guild IN (' + guilds.map( (guild, i) => '$' + ( i + 1 ) ).join(', ') + ') GROUP BY guild', guilds ).then( ({rows}) => {
+					if ( !rows.length ) return;
+					var webhooks = [].concat(...rows.map( row => row.webhooks ));
+					if ( webhooks.length ) {
+						return client.query( 'DELETE FROM rcgcdw WHERE webhook IN (' + webhooks.map( (webhook, i) => '$' + ( i + 1 ) ).join(', ') + ')', webhooks ).then( () => {
+							console.log( '- RcGcDw successfully deleted.' );
+							webhooks.forEach( hook => msg.client.fetchWebhook(...hook.split('/')).then( webhook => {
+								webhook.delete('Removed extra recent changes webhook').catch(log_error);
+							}, log_error ) );
+						}, dberror => {
+							console.log( '- Error while deleting the RcGcDw: ' + dberror );
+						} );
 					}
-					console.log( '- RcGcDw successfully deleted.' );
-					webhooks.forEach( hook => msg.client.fetchWebhook(...hook.split('/')).then( webhook => {
-						webhook.delete('Removed extra recent changes webhook').catch(log_error);
-					}, log_error ) );
+				}, dberror => {
+					console.log( '- Error while getting the RcGcDw: ' + dberror );
 				} );
-			}, (eacherror) => {
-				if ( eacherror ) {
-					console.log( '- Error while getting the RcGcDw: ' + eacherror );
-					return eacherror;
-				}
-			} );
-			db.run( 'UPDATE rcgcdw SET display = ? WHERE guild IN (' + guilds.map( guild => '?' ).join(', ') + ') AND display > ?', [rcgcdwLimit.display, ...guilds, rcgcdwLimit.display], function (uperror) {
-				if ( uperror ) {
-					console.log( '- Error while updating the RcGcDw: ' + uperror );
-					return uperror;
-				}
-				console.log( '- RcGcDw successfully updated.' );
+			} ).then( () => {
+				return client.query( 'UPDATE rcgcdw SET display = $1 WHERE guild IN (' + guilds.map( (guild, i) => '$' + ( i + 2 ) ).join(', ') + ') AND display > $1', [rcgcdwLimit.display, ...guilds] ).then( () => {
+					console.log( '- RcGcDw successfully updated.' );
+				}, dberror => {
+					console.log( '- Error while updating the RcGcDw: ' + dberror );
+				} );
+			} ).catch( error => {
+				if ( error ) console.log( '- Error while removing the patreon features: ' + error );
+			} ).finally( () => {
+				client.release();
 			} );
+		}, dberror => {
+			console.log( '- Error while connecting to the database client: ' + dberror );
+			msg.replyMsg( 'I got an error while updating <@' + args[1] + '>, please try again later.', {}, true );
 		} );
-		if ( !row ) return db.run( 'INSERT INTO patreons(patreon, count) VALUES(?, ?)', [args[1], count], function (error) {
-			if ( error ) {
-				console.log( '- Error while adding the patreon: ' + error );
-				msg.replyMsg( 'I got an error while adding <@' + args[1] + '>, please try again later.', {}, true );
-				return error;
-			}
+		if ( !row ) return db.query( 'INSERT INTO patreons(patreon, count) VALUES($1, $2)', [args[1], count] ).then( () => {
 			console.log( '- Patreon successfully added.' );
-			msg.replyMsg( '<@' + args[1] + '> can now have up to ' + count + ' server.', {}, true );
+			msg.replyMsg( '<@' + args[1] + '> can now have up to ' + count + ' servers.', {}, true );
+		}, dberror => {
+			console.log( '- Error while adding the patreon: ' + dberror );
+			msg.replyMsg( 'I got an error while adding <@' + args[1] + '>, please try again later.', {}, true );
 		} );
-		db.run( 'UPDATE patreons SET count = ? WHERE patreon = ?', [count, args[1]], function (error) {
-			if ( error ) {
-				console.log( '- Error while updating the patreon: ' + error );
-				msg.replyMsg( 'I got an error while updating <@' + args[1] + '>, please try again later.', {}, true );
-				return error;
-			}
+		db.query( 'UPDATE patreons SET count = $1 WHERE patreon = $2', [count, args[1]] ).then( () => {
 			console.log( '- Patreon successfully updated.' );
-			var text = '<@' + args[1] + '> can now have up to ' + count + ' server.';
+			var text = '<@' + args[1] + '> can now have up to ' + count + ' servers.';
 			if ( count < guilds.length ) text += '\n\n**They are now above their server limit!**';
 			msg.replyMsg( text, {}, true );
+		}, dberror => {
+			console.log( '- Error while updating the patreon: ' + dberror );
+			msg.replyMsg( 'I got an error while updating <@' + args[1] + '>, please try again later.', {}, true );
 		} );
+	}, dberror => {
+		console.log( '- Error while getting the patreon: ' + dberror );
+		msg.replyMsg( 'I got an error while searching for <@' + args[1] + '>, please try again later.', {}, true );
 	} );
 	
 	if ( !msg.channel.isGuild() || !pause[msg.guild.id] ) this.LINK(lang, msg, line, wiki);

+ 100 - 141
cmds/rcscript.js

@@ -29,13 +29,7 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 	if ( !msg.isAdmin() ) return msg.reactEmoji('❌');
 	if ( msg.defaultSettings ) return help_setup(lang, msg);
 	
-	db.all( 'SELECT configid, webhook, wiki, lang, display, rcid, postid FROM rcgcdw WHERE guild = ? ORDER BY configid ASC', [msg.guild.id], (dberror, rows) => {
-		if ( dberror || !rows ) {
-			console.log( '- Error while getting the RcGcDw: ' + dberror );
-			msg.reactEmoji('error', true);
-			return dberror;
-		}
-
+	db.query( 'SELECT configid, webhook, wiki, lang, display, rcid, postid FROM rcgcdw WHERE guild = $1 ORDER BY configid ASC', [msg.guild.id] ).then( ({rows}) => {
 		var prefix = process.env.prefix;
 		var limit = rcgcdwLimit.default;
 		var display = display_types.slice(0, rcgcdwLimit.display + 1);
@@ -99,13 +93,7 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 					if ( reaction ) reaction.removeEmoji();
 					return msg.replyMsg( lang.get('rcscript.sysmessage', 'MediaWiki:Custom-RcGcDw', msg.guild.id) + '\n<' + wikinew.toLink('MediaWiki:Custom-RcGcDw', 'action=edit') + '>', {}, true );
 				}
-				return db.get( 'SELECT reason FROM blocklist WHERE wiki = ?', [wikinew.href], (blerror, block) => {
-					if ( blerror ) {
-						console.log( '- Error while getting the blocklist: ' + blerror );
-						if ( reaction ) reaction.removeEmoji();
-						msg.reactEmoji('error', true);
-						return blerror;
-					}
+				return db.query( 'SELECT reason FROM blocklist WHERE wiki = $1', [wikinew.href] ).then( ({rows:[block]}) => {
 					if ( block ) {
 						console.log( '- This wiki is blocked: ' + block.reason );
 						if ( reaction ) reaction.removeEmoji();
@@ -145,16 +133,14 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 								if ( new_configid === i ) new_configid++;
 								else break;
 							}
-							db.run( 'INSERT INTO rcgcdw(guild, configid, webhook, wiki, lang, display, postid) VALUES(?, ?, ?, ?, ?, ?, ?)', [msg.guild.id, new_configid, webhook.id + '/' + webhook.token, wikinew.href, webhook_lang.lang, ( msg.showEmbed() ? 1 : 0 ), ( enableFeeds ? null : '-1' )], function (error) {
-								if ( error ) {
-									console.log( '- Error while adding the RcGcDw: ' + error );
-									if ( reaction ) reaction.removeEmoji();
-									msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-									return error;
-								}
+							db.query( 'INSERT INTO rcgcdw(guild, configid, webhook, wiki, lang, display, postid) VALUES($1, $2, $3, $4, $5, $6, $7)', [msg.guild.id, new_configid, webhook.id + '/' + webhook.token, wikinew.href, webhook_lang.lang, ( msg.showEmbed() ? 1 : 0 ), ( enableFeeds ? null : '-1' )] ).then( () => {
 								console.log( '- RcGcDw successfully added.' );
 								if ( reaction ) reaction.removeEmoji();
 								msg.replyMsg( lang.get('rcscript.added') + ' <' + wikinew + '>\n`' + prefix + 'rcscript' + ( rows.length ? ' ' + new_configid : '' ) + '`', {}, true );
+							}, dberror => {
+								console.log( '- Error while adding the RcGcDw: ' + dberror );
+								if ( reaction ) reaction.removeEmoji();
+								msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 							} );
 						}, error => {
 							console.log( '- Error while creating the webhook: ' + error );
@@ -162,6 +148,10 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 							msg.replyMsg( lang.get('rcscript.webhook_failed'), {}, true );
 						} );
 					}
+				}, dberror => {
+					console.log( '- Error while getting the blocklist: ' + dberror );
+					if ( reaction ) reaction.removeEmoji();
+					msg.reactEmoji('error', true);
 				} );
 			}, error => {
 				if ( reaction ) reaction.removeEmoji();
@@ -200,31 +190,27 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 					if ( !channel || !channel.permissionsFor(msg.member).has('MANAGE_WEBHOOKS') ) {
 						return msg.replyMsg( lang.get('rcscript.noadmin') );
 					}
-					db.run( 'DELETE FROM rcgcdw WHERE webhook = ?', [selected_row.webhook], function (delerror) {
-						if ( delerror ) {
-							console.log( '- Error while removing the RcGcDw: ' + delerror );
-							msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-							return delerror;
-						}
+					db.query( 'DELETE FROM rcgcdw WHERE webhook = $1', [selected_row.webhook] ).then( () => {
 						console.log( '- RcGcDw successfully removed.' );
 						webhook.send( webhook_lang.get('deleted') ).catch(log_error).finally( () => {
 							webhook.delete(lang.get('rcscript.audit_reason_delete')).catch(log_error);
 						} );
 						msg.replyMsg( lang.get('rcscript.deleted'), {}, true );
+					}, dberror => {
+						console.log( '- Error while removing the RcGcDw: ' + dberror );
+						msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 					} );
 				}, error => {
 					log_error(error);
 					if ( error.name === 'DiscordAPIError' && ['Unknown Webhook', 'Invalid Webhook Token'].includes( error.message ) ) {
 						return msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 					}
-					db.run( 'DELETE FROM rcgcdw WHERE webhook = ?', [selected_row.webhook], function (delerror) {
-						if ( delerror ) {
-							console.log( '- Error while removing the RcGcDw: ' + delerror );
-							msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-							return delerror;
-						}
+					db.query( 'DELETE FROM rcgcdw WHERE webhook = $1', [selected_row.webhook] ).then( () => {
 						console.log( '- RcGcDw successfully removed.' );
 						msg.replyMsg( lang.get('rcscript.deleted'), {}, true );
+					}, dberror => {
+						console.log( '- Error while removing the RcGcDw: ' + dberror );
+						msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 					} );
 				} );
 			}
@@ -274,13 +260,7 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 						if ( reaction ) reaction.removeEmoji();
 						return msg.replyMsg( lang.get('rcscript.sysmessage', 'MediaWiki:Custom-RcGcDw', msg.guild.id) + '\n<' + wikinew.toLink('MediaWiki:Custom-RcGcDw', 'action=edit') + '>', {}, true );
 					}
-					return db.get( 'SELECT reason FROM blocklist WHERE wiki = ?', [wikinew.href], (blerror, block) => {
-						if ( blerror ) {
-							console.log( '- Error while getting the blocklist: ' + blerror );
-							if ( reaction ) reaction.removeEmoji();
-							msg.reactEmoji('error', true);
-							return blerror;
-						}
+					return db.query( 'SELECT reason FROM blocklist WHERE wiki = $1', [wikinew.href] ).then( ({rows:[block]}) => {
 						if ( block ) {
 							console.log( '- This wiki is blocked: ' + block.reason );
 							if ( reaction ) reaction.removeEmoji();
@@ -311,18 +291,20 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 							msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 								webhook.send( webhook_lang.get('updated_wiki', body.query.general.sitename) + '\n<' + wikinew.toLink(body.query.pages['-1'].title) + ( enableFeeds ? '>\n<' + wikinew + 'f' : '' ) + '>' ).catch(log_error);
 							}, log_error );
-							db.run( 'UPDATE rcgcdw SET wiki = ?, rcid = ?, postid = ? WHERE webhook = ?', [wikinew.href, null, ( enableFeeds ? null : '-1' ), selected_row.webhook], function (error) {
-								if ( error ) {
-									console.log( '- Error while updating the RcGcDw: ' + error );
-									if ( reaction ) reaction.removeEmoji();
-									msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-									return error;
-								}
+							db.query( 'UPDATE rcgcdw SET wiki = $1, rcid = $2, postid = $3 WHERE webhook = $4', [wikinew.href, null, ( enableFeeds ? null : '-1' ), selected_row.webhook] ).then( () => {
 								console.log( '- RcGcDw successfully updated.' );
 								if ( reaction ) reaction.removeEmoji();
 								msg.replyMsg( lang.get('rcscript.updated_wiki') + ' <' + wikinew + '>\n`' + cmd + '`', {}, true );
+							}, dberror => {
+								console.log( '- Error while updating the RcGcDw: ' + dberror );
+								if ( reaction ) reaction.removeEmoji();
+								msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 							} );
 						}
+					}, dberror => {
+						console.log( '- Error while getting the blocklist: ' + dberror );
+						if ( reaction ) reaction.removeEmoji();
+						msg.reactEmoji('error', true);
 					} );
 				}, error => {
 					if ( reaction ) reaction.removeEmoji();
@@ -350,14 +332,12 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 				msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 					webhook.send( new Lang(allLangs.map[args[1]], 'rcscript.webhook').get('updated_lang', allLangs.names[allLangs.map[args[1]]]), {files:[`./RcGcDb/locale/widgets/${allLangs.map[args[1]]}.png`]} ).catch(log_error);
 				}, log_error );
-				return db.run( 'UPDATE rcgcdw SET lang = ? WHERE webhook = ?', [allLangs.map[args[1]], selected_row.webhook], function (error) {
-					if ( error ) {
-						console.log( '- Error while updating the RcGcDw: ' + error );
-						msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-						return error;
-					}
+				return db.query( 'UPDATE rcgcdw SET lang = $1 WHERE webhook = $2', [allLangs.map[args[1]], selected_row.webhook] ).then( () => {
 					console.log( '- RcGcDw successfully updated.' );
 					msg.replyMsg( lang.get('rcscript.updated_lang') + ' `' + allLangs.names[allLangs.map[args[1]]] + '`\n`' + cmd + '`', {files:( msg.uploadFiles() ? [`./RcGcDb/locale/widgets/${allLangs.map[args[1]]}.png`] : [] )}, true );
+				}, dberror => {
+					console.log( '- Error while updating the RcGcDw: ' + dberror );
+					msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 				} );
 			}
 			if ( args[0] === 'display' ) {
@@ -372,14 +352,12 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 				msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 					webhook.send( webhook_lang.get('updated_display_' + args[1]) ).catch(log_error);
 				}, log_error );
-				return db.run( 'UPDATE rcgcdw SET display = ? WHERE webhook = ?', [display_types.indexOf(args[1]), selected_row.webhook], function (error) {
-					if ( error ) {
-						console.log( '- Error while updating the RcGcDw: ' + error );
-						msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-						return error;
-					}
+				return db.query( 'UPDATE rcgcdw SET display = $1 WHERE webhook = $2', [display_types.indexOf(args[1]), selected_row.webhook] ).then( () => {
 					console.log( '- RcGcDw successfully updated.' );
 					msg.replyMsg( lang.get('rcscript.updated_display') + ' `' + args[1] + '`\n`' + cmd + '`', {}, true );
+				}, dberror => {
+					console.log( '- Error while updating the RcGcDw: ' + dberror );
+					msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 				} );
 			}
 			if ( new Wiki(selected_row.wiki).isFandom(false) && args[0] === 'feeds' ) {
@@ -389,14 +367,12 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 						msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 							webhook.send( webhook_lang.get('enabled_rc') ).catch(log_error);
 						}, log_error );
-						return db.run( 'UPDATE rcgcdw SET rcid = ? WHERE webhook = ?', [null, selected_row.webhook], function (error) {
-							if ( error ) {
-								console.log( '- Error while updating the RcGcDw: ' + error );
-								msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-								return error;
-							}
+						return db.query( 'UPDATE rcgcdw SET rcid = $1 WHERE webhook = $2', [null, selected_row.webhook] ).then( () => {
 							console.log( '- RcGcDw successfully updated.' );
 							msg.replyMsg( lang.get('rcscript.enabled_rc') + '\n`' + cmd + '`', {}, true );
+						}, dberror => {
+							console.log( '- Error while updating the RcGcDw: ' + dberror );
+							msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 						} );
 					}
 
@@ -406,14 +382,12 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 					msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 						webhook.send( webhook_lang.get('disabled_rc') ).catch(log_error);
 					}, log_error );
-					return db.run( 'UPDATE rcgcdw SET rcid = ? WHERE webhook = ?', [-1, selected_row.webhook], function (error) {
-						if ( error ) {
-							console.log( '- Error while updating the RcGcDw: ' + error );
-							msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-							return error;
-						}
+					return db.query( 'UPDATE rcgcdw SET rcid = $1 WHERE webhook = $2', [-1, selected_row.webhook] ).then( () => {
 						console.log( '- RcGcDw successfully updated.' );
 						msg.replyMsg( lang.get('rcscript.disabled_rc') + '\n`' + cmd + '`', {}, true );
+					}, dberror => {
+						console.log( '- Error while updating the RcGcDw: ' + dberror );
+						msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 					} );
 				}
 
@@ -424,14 +398,12 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 					msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 						webhook.send( webhook_lang.get('disabled_feeds') ).catch(log_error);
 					}, log_error );
-					return db.run( 'UPDATE rcgcdw SET postid = ? WHERE webhook = ?', ['-1', selected_row.webhook], function (error) {
-						if ( error ) {
-							console.log( '- Error while updating the RcGcDw: ' + error );
-							msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-							return error;
-						}
+					return db.query( 'UPDATE rcgcdw SET postid = $1 WHERE webhook = $2', ['-1', selected_row.webhook] ).then( () => {
 						console.log( '- RcGcDw successfully updated.' );
 						msg.replyMsg( lang.get('rcscript.disabled_feeds') + '\n`' + cmd + '`', {}, true );
+					}, dberror => {
+						console.log( '- Error while updating the RcGcDw: ' + dberror );
+						msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 					} );
 				}
 
@@ -449,16 +421,14 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 					msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 						webhook.send( webhook_lang.get('enabled_feeds') + '\n<' + selected_row.wiki + 'f>' ).catch(log_error);
 					}, log_error );
-					db.run( 'UPDATE rcgcdw SET postid = ? WHERE webhook = ?', [null, selected_row.webhook], function (error) {
-						if ( error ) {
-							console.log( '- Error while updating the RcGcDw: ' + error );
-							if ( reaction ) reaction.removeEmoji();
-							msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-							return error;
-						}
+					db.query( 'UPDATE rcgcdw SET postid = $1 WHERE webhook = $2', [null, selected_row.webhook] ).then( () => {
 						console.log( '- RcGcDw successfully updated.' );
 						if ( reaction ) reaction.removeEmoji();
 						msg.replyMsg( lang.get('rcscript.enabled_feeds') + '\n`' + cmd + '`', {}, true );
+					}, dberror => {
+						console.log( '- Error while updating the RcGcDw: ' + dberror );
+						if ( reaction ) reaction.removeEmoji();
+						msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 					} );
 				}, error => {
 					console.log( '- Error while checking for discussions: ' + error );
@@ -472,14 +442,12 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 			}, error => {
 				log_error(error);
 				if ( error.name === 'DiscordAPIError' && ['Unknown Webhook', 'Invalid Webhook Token'].includes( error.message ) ) {
-					db.run( 'DELETE FROM rcgcdw WHERE webhook = ?', [selected_row.webhook], function (delerror) {
-						if ( delerror ) {
-							console.log( '- Error while removing the RcGcDw: ' + delerror );
-							return delerror;
-						}
+					db.query( 'DELETE FROM rcgcdw WHERE webhook = $1', [selected_row.webhook] ).then( () => {
 						console.log( '- RcGcDw successfully removed.' );
+					}, dberror => {
+						console.log( '- Error while removing the RcGcDw: ' + dberror );
 					} );
-					Promise.reject();
+					return Promise.reject();
 				}
 				return;
 			} ).then( channel => {
@@ -510,12 +478,10 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 		}, error => {
 			log_error(error);
 			if ( error.name === 'DiscordAPIError' && ['Unknown Webhook', 'Invalid Webhook Token'].includes( error.message ) ) {
-				db.run( 'DELETE FROM rcgcdw WHERE webhook = ?', [row.webhook], function (delerror) {
-					if ( delerror ) {
-						console.log( '- Error while removing the RcGcDw: ' + delerror );
-						return delerror;
-					}
+				db.query( 'DELETE FROM rcgcdw WHERE webhook = $1', [row.webhook] ).then( () => {
 					console.log( '- RcGcDw successfully removed.' );
+				}, dberror => {
+					console.log( '- Error while removing the RcGcDw: ' + dberror );
 				} );
 				return;
 			}
@@ -561,6 +527,9 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 			if ( rows.length < limit ) text += '\n\n' + lang.get('rcscript.add_more') + '\n`' + prefix + 'rcscript add ' + lang.get('rcscript.new_wiki') + '`';
 			msg.replyMsg( text, {split:true}, true );
 		} );
+	}, dberror => {
+		console.log( '- Error while getting the RcGcDw: ' + dberror );
+		msg.reactEmoji('error', true);
 	} );
 }
 
@@ -578,36 +547,29 @@ function blocklist(msg, args) {
 		let wiki = Wiki.fromInput(input);
 		if ( !wiki ) return msg.replyMsg( '`' + prefix + 'rcscript block add <wiki> [<reason>]`', {}, true );
 		let reason = ( args.slice(2).join(' ').trim() || null );
-		return db.run( 'INSERT INTO blocklist(wiki, reason) VALUES(?, ?)', [wiki.href, reason], function (error) {
-			if ( error ) {
-				if ( error.message === 'SQLITE_CONSTRAINT: UNIQUE constraint failed: blocklist.wiki' ) {
-					return msg.replyMsg( '`' + wiki + '` is already on the blocklist.\n`' + prefix + 'rcscript block <' + wiki + '>`', {}, true );
-				}
-				console.log( '- Error while adding to the blocklist: ' + error );
-				msg.replyMsg( 'I got an error while adding to the blocklist: ' + error, {}, true );
-				return error;
-			}
+		return db.query( 'INSERT INTO blocklist(wiki, reason) VALUES($1, $2)', [wiki.href, reason] ).then( () => {
 			console.log( '- Successfully added to the blocklist.' );
-			db.each( 'SELECT webhook, lang FROM rcgcdw WHERE wiki = ?', [wiki.href], (dberror, row) => {
-				if ( dberror ) return dberror;
-				msg.client.fetchWebhook(...row.webhook.split('/')).then( webhook => {
-					var lang = new Lang(row.lang, 'rcscript.webhook');
-					webhook.send( '**' + ( reason ? lang.get('blocked_reason', reason) : lang.get('blocked') ) + '**\n' + lang.get('blocked_help', `<${process.env.invite}>`) ).catch(log_error).finally( () => {
-						webhook.delete().catch(log_error);
-					} );
-				}, log_error );
-			}, (dberror, count) => {
-				if ( dberror ) console.log( '- Error while deleting the webhooks: ' + dberror );
-				db.run( 'DELETE FROM rcgcdw WHERE wiki = ?', [wiki.href], function (delerror) {
-					if ( delerror ) {
-						console.log( '- Error while removing the webhooks: ' + delerror );
-						msg.replyMsg( 'I added `' + wiki + '` to the blocklist for `' + reason + '` but got an error while removing the webhooks: ' + delerror, {}, true );
-						return delerror;
-					}
-					console.log( '- Successfully removed ' + count + ' webhooks.' );
-					msg.replyMsg( 'I added `' + wiki + '` to the blocklist for `' + reason + '` and removed ' + count + ' webhooks.', {}, true );
+			db.query( 'DELETE FROM rcgcdw WHERE wiki = $1 RETURNING webhook, lang', [wiki.href] ).then( ({rows}) => {
+				console.log( '- Successfully removed ' + rows.length + ' webhooks.' );
+				msg.replyMsg( 'I added `' + wiki + '` to the blocklist for `' + reason + '` and removed ' + rows.length + ' webhooks.', {}, true );
+				if ( rows.length ) rows.forEach( row => {
+					msg.client.fetchWebhook(...row.webhook.split('/')).then( webhook => {
+						var lang = new Lang(row.lang, 'rcscript.webhook');
+						webhook.send( '**' + ( reason ? lang.get('blocked_reason', reason) : lang.get('blocked') ) + '**\n' + lang.get('blocked_help', `<${process.env.invite}>`) ).catch(log_error).finally( () => {
+							webhook.delete().catch(log_error);
+						} );
+					}, log_error );
 				} );
+			}, dberror => {
+				console.log( '- Error while removing the webhooks: ' + dberror );
+				msg.replyMsg( 'I added `' + wiki + '` to the blocklist for `' + reason + '` but got an error while removing the webhooks: ' + dberror, {}, true );
 			} );
+		}, dberror => {
+			if ( dberror.message === 'duplicate key value violates unique constraint "blocklist_wiki_key"' ) {
+				return msg.replyMsg( '`' + wiki + '` is already on the blocklist.\n`' + prefix + 'rcscript block <' + wiki + '>`', {}, true );
+			}
+			console.log( '- Error while adding to the blocklist: ' + dberror );
+			msg.replyMsg( 'I got an error while adding to the blocklist: ' + dberror, {}, true );
 		} );
 	}
 	if ( args[0] === 'remove' ) {
@@ -615,38 +577,35 @@ function blocklist(msg, args) {
 		let wiki = Wiki.fromInput(input);
 		if ( !wiki ) return msg.replyMsg( '`' + prefix + 'rcscript block remove <wiki>`', {}, true );
 		if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
-		return db.run( 'DELETE FROM blocklist WHERE wiki = ?', [wiki.href], function (error) {
-			if ( error ) {
-				console.log( '- Error while removing from the blocklist: ' + error );
-				msg.replyMsg( 'I got an error while removing from the blocklist: ' + error, {}, true );
-				return error;
+		return db.query( 'DELETE FROM blocklist WHERE wiki = $1', [wiki.href] ).then( ({rowCount}) => {
+			if ( rowCount ) {
+				console.log( '- Successfully removed from the blocklist.' );
+				msg.replyMsg( 'I removed `' + wiki + '` from the blocklist.', {}, true );
 			}
-			console.log( '- Successfully removed from the blocklist.' );
-			msg.replyMsg( 'I removed `' + wiki + '` from the blocklist.', {}, true );
+			else msg.replyMsg( '`' + wiki + '` was not on the blocklist.', {}, true );
+		}, dberror => {
+			console.log( '- Error while removing from the blocklist: ' + dberror );
+			msg.replyMsg( 'I got an error while removing from the blocklist: ' + dberror, {}, true );
 		} );
 	}
 	if ( args.length ) {
 		let input = args.join(' ').toLowerCase().trim().replace( /^<\s*(.*?)\s*>$/, '$1' );
 		let wiki = Wiki.fromInput(input);
 		if ( !wiki ) return msg.replyMsg( '`' + prefix + 'rcscript block <wiki>`\n`' + prefix + 'rcscript block add <wiki> [<reason>]`\n`' + prefix + 'rcscript block remove <wiki>`', {}, true );
-		return db.get( 'SELECT reason FROM blocklist WHERE wiki = ?', [wiki.href], function (error, row) {
-			if ( error ) {
-				console.log( '- Error while checking the blocklist: ' + error );
-				msg.replyMsg( 'I got an error while checking the blocklist: ' + error, {}, true );
-				return error;
-			}
+		return db.query( 'SELECT reason FROM blocklist WHERE wiki = $1', [wiki.href] ).then( ({rows:[row]}) => {
 			if ( !row ) return msg.replyMsg( '`' + wiki + '` is currently not on the blocklist.\n`' + prefix + 'rcscript block add <' + wiki + '> [<reason>]`', {}, true );
 			msg.replyMsg( '`' + wiki + '` is currently on the blocklist ' + ( row.reason ? 'for `' + row.reason + '`' : 'with no reason provided' ) + '.\n`' + prefix + 'rcscript block remove <' + wiki + '>`', {}, true );
+		}, dberror => {
+			console.log( '- Error while checking the blocklist: ' + dberror );
+			msg.replyMsg( 'I got an error while checking the blocklist: ' + dberror, {}, true );
 		} );
 	}
-	db.all( 'SELECT wiki, reason FROM blocklist', [], function (error, rows) {
-		if ( error ) {
-			console.log( '- Error while checking the blocklist: ' + error );
-			msg.replyMsg( 'I got an error while checking the blocklist: ' + error, {}, true );
-			return error;
-		}
+	db.query( 'SELECT wiki, reason FROM blocklist' ).then( ({rows}) => {
 		if ( !rows.length ) return msg.replyMsg( 'there are currently no wikis on the blocklist.\n`' + prefix + 'rcscript block add <wiki> [<reason>]`', {}, true );
 		msg.replyMsg( 'there are currently ' + row.length + ' wikis the blocklist:\n' + rows.map( row => '`' + row.wiki + '` – ' + ( row.reason ? '`' + row.reason + '`' : 'No reason provided.' ) ).join('\n') + '\n`' + prefix + 'rcscript block remove <wiki>`', {split:true}, true );
+	}, dberror => {
+		console.log( '- Error while checking the blocklist: ' + dberror );
+		msg.replyMsg( 'I got an error while checking the blocklist: ' + dberror, {}, true );
 	} );
 }
 

+ 61 - 82
cmds/settings.js

@@ -17,12 +17,7 @@ var db = require('../util/database.js');
 function cmd_settings(lang, msg, args, line, wiki) {
 	if ( !msg.isAdmin() ) return msg.reactEmoji('❌');
 	
-	db.all( 'SELECT channel, wiki, lang, role, inline, prefix FROM discord WHERE guild = ? ORDER BY channel DESC', [msg.guild.id], (error, rows) => {
-		if ( error ) {
-			console.log( '- Error while getting the settings: ' + error );
-			msg.reactEmoji('error', true);
-			return error;
-		}
+	db.query( 'SELECT channel, wiki, lang, role, inline, prefix FROM discord WHERE guild = $1 ORDER BY channel DESC NULLS LAST', [msg.guild.id] ).then( ({rows}) => {
 		var guild = rows.find( row => !row.channel );
 		if ( !guild ) guild = Object.assign({
 			role: null, inline: null,
@@ -145,32 +140,25 @@ function cmd_settings(lang, msg, args, line, wiki) {
 							embed = new MessageEmbed().setAuthor( body.query.general.sitename ).setTitle( lang.get('test.notice') ).addFields( notice );
 						}
 					}
-					var sql = 'UPDATE discord SET wiki = ? WHERE guild = ? AND wiki = ?';
+					var sql = 'UPDATE discord SET wiki = $1 WHERE guild = $2 AND wiki = $3';
 					var sqlargs = [wikinew.href, msg.guild.id, guild.wiki];
 					if ( !rows.length ) {
-						sqlargs.pop();
-						sql = 'INSERT INTO discord(wiki, guild, main, lang) VALUES(?, ?, ?, ?)';
-						sqlargs.push(msg.guild.id, lang.lang);
+						sql = 'INSERT INTO discord(wiki, guild, main, lang) VALUES($1, $2, $2, $3)';
+						sqlargs[2] = lang.lang;
 					}
 					else if ( channel ) {
-						sql = 'UPDATE discord SET wiki = ? WHERE guild = ? AND channel = ?';
+						sql = 'UPDATE discord SET wiki = $1 WHERE guild = $2 AND channel = $3';
 						sqlargs[2] = msg.channel.id;
 						if ( !rows.includes( channel ) ) {
 							if ( channel.wiki === wikinew.href ) {
 								if ( reaction ) reaction.removeEmoji();
 								return msg.replyMsg( lang.get('settings.' + prelang + 'changed') + ' ' + channel.wiki + wikihelp, {embed}, true );
 							}
-							sql = 'INSERT INTO discord(wiki, guild, channel, lang, role, inline, prefix) VALUES(?, ?, ?, ?, ?, ?, ?)';
+							sql = 'INSERT INTO discord(wiki, guild, channel, lang, role, inline, prefix) VALUES($1, $2, $3, $4, $5, $6, $7)';
 							sqlargs.push(guild.lang, guild.role, guild.inline, guild.prefix);
 						}
 					}
-					return db.run( sql, sqlargs, function (dberror) {
-						if ( dberror ) {
-							console.log( '- Error while editing the settings: ' + dberror );
-							msg.replyMsg( lang.get('settings.save_failed'), {embed}, true );
-							if ( reaction ) reaction.removeEmoji();
-							return dberror;
-						}
+					return db.query( sql, sqlargs ).then( () => {
 						console.log( '- Settings successfully updated.' );
 						if ( channel ) channel.wiki = wikinew.href;
 						else {
@@ -183,13 +171,15 @@ function cmd_settings(lang, msg, args, line, wiki) {
 						if ( reaction ) reaction.removeEmoji();
 						msg.replyMsg( lang.get('settings.' + prelang + 'changed') + ' ' + wikinew + wikihelp, {embed}, true );
 						var channels = rows.filter( row => row.channel && row.lang === guild.lang && row.wiki === guild.wiki && row.prefix === guild.prefix && row.role === guild.role && row.inline === guild.inline ).map( row => row.channel );
-						if ( channels.length ) db.run( 'DELETE FROM discord WHERE channel IN (' + channels.map( row => '?' ).join(', ') + ')', channels, function (delerror) {
-							if ( delerror ) {
-								console.log( '- Error while removing the settings: ' + delerror );
-								return delerror;
-							}
+						if ( channels.length ) db.query( 'DELETE FROM discord WHERE channel IN (' + channels.map( (row, i) => '$' + ( i + 1 ) ).join(', ') + ')', channels ).then( () => {
 							console.log( '- Settings successfully removed.' );
+						}, dberror => {
+							console.log( '- Error while removing the settings: ' + dberror );
 						} );
+					}, dberror => {
+						console.log( '- Error while editing the settings: ' + dberror );
+						msg.replyMsg( lang.get('settings.save_failed'), {embed}, true );
+						if ( reaction ) reaction.removeEmoji();
 					} );
 				}, ferror => {
 					if ( reaction ) reaction.removeEmoji();
@@ -218,29 +208,24 @@ function cmd_settings(lang, msg, args, line, wiki) {
 			if ( !allLangs.map.hasOwnProperty(args[1]) ) {
 				return msg.replyMsg( lang.get('settings.langinvalid') + langhelp, {}, true );
 			}
-			var sql = 'UPDATE discord SET lang = ? WHERE guild = ? AND lang = ?';
+			var sql = 'UPDATE discord SET lang = $1 WHERE guild = $2 AND lang = $3';
 			var sqlargs = [allLangs.map[args[1]], msg.guild.id, guild.lang];
 			if ( !rows.length ) {
-				sql = 'INSERT INTO discord(lang, guild, main) VALUES(?, ?, ?)';
-				sqlargs[2] = msg.guild.id;
+				sql = 'INSERT INTO discord(lang, guild, main) VALUES($1, $2, $2)';
+				sqlargs.pop();
 			}
 			else if ( channel ) {
-				sql = 'UPDATE discord SET lang = ? WHERE guild = ? AND channel = ?';
+				sql = 'UPDATE discord SET lang = $1 WHERE guild = $2 AND channel = $3';
 				sqlargs[2] = msg.channel.id;
 				if ( !rows.includes( channel ) ) {
 					if ( channel.lang === allLangs.map[args[1]] ) {
 						return msg.replyMsg( lang.get('settings.' + prelang + 'changed') + ' `' + allLangs.names[channel.lang] + '`' + langhelp, {files:( msg.uploadFiles() ? [`./i18n/widgets/${channel.lang}.png`] : [] )}, true );
 					}
-					sql = 'INSERT INTO discord(lang, guild, channel, wiki, role, inline, prefix) VALUES(?, ?, ?, ?, ?, ?, ?)';
+					sql = 'INSERT INTO discord(lang, guild, channel, wiki, role, inline, prefix) VALUES($1, $2, $3, $4, $5, $6, $7)';
 					sqlargs.push(guild.wiki, guild.role, guild.inline, guild.prefix);
 				}
 			}
-			return db.run( sql, sqlargs, function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while editing the settings: ' + dberror );
-					msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-					return dberror;
-				}
+			return db.query( sql, sqlargs ).then( () => {
 				console.log( '- Settings successfully updated.' );
 				if ( channel ) channel.lang = allLangs.map[args[1]];
 				else {
@@ -253,13 +238,14 @@ function cmd_settings(lang, msg, args, line, wiki) {
 				if ( channel || !patreons[msg.guild.id] || !rows.some( row => row.channel === msg.channel.id ) ) lang = new Lang(allLangs.map[args[1]]);
 				msg.replyMsg( lang.get('settings.' + prelang + 'changed') + ' `' + allLangs.names[allLangs.map[args[1]]] + '`\n' + lang.get('settings.langhelp', prefix + 'settings ' + prelang) + ' `' + Object.values(allLangs.names).join('`, `') + '`', {files:( msg.uploadFiles() ? [`./i18n/widgets/${allLangs.map[args[1]]}.png`] : [] )}, true );
 				var channels = rows.filter( row => row.channel && row.lang === guild.lang && row.wiki === guild.wiki && row.prefix === guild.prefix && row.role === guild.role && row.inline === guild.inline ).map( row => row.channel );
-				if ( channels.length ) db.run( 'DELETE FROM discord WHERE channel IN (' + channels.map( row => '?' ).join(', ') + ')', channels, function (delerror) {
-					if ( delerror ) {
-						console.log( '- Error while removing the settings: ' + delerror );
-						return delerror;
-					}
+				if ( channels.length ) db.query( 'DELETE FROM discord WHERE channel IN (' + channels.map( (row, i) => '$' + ( i + 1 ) ).join(', ') + ')', channels ).then( () => {
 					console.log( '- Settings successfully removed.' );
+				}, dberror => {
+					console.log( '- Error while removing the settings: ' + dberror );
 				} );
+			}, dberror => {
+				console.log( '- Error while editing the settings: ' + dberror );
+				msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 			} );
 		}
 		
@@ -281,34 +267,29 @@ function cmd_settings(lang, msg, args, line, wiki) {
 				return msg.replyMsg( lang.get('settings.roleinvalid') + rolehelp, {}, true );
 			}
 			role = ( role.id === msg.guild.id ? null : role.id );
-			var sql = 'UPDATE discord SET role = ? WHERE guild = ?';
+			var sql = 'UPDATE discord SET role = $1 WHERE guild = $2';
 			var sqlargs = [role, msg.guild.id];
 			if ( !rows.length ) {
-				sql = 'INSERT INTO discord(role, guild, main, lang) VALUES(?, ?, ?, ?)';
-				sqlargs.push(msg.guild.id, lang.lang);
+				sql = 'INSERT INTO discord(role, guild, main, lang) VALUES($1, $2, $2, $3)';
+				sqlargs.push(lang.lang);
 			}
 			else if ( channel ) {
-				sql = 'UPDATE discord SET role = ? WHERE guild = ? AND channel = ?';
+				sql = 'UPDATE discord SET role = $1 WHERE guild = $2 AND channel = $3';
 				sqlargs.push(msg.channel.id);
 				if ( !rows.includes( channel ) ) {
 					if ( channel.role === role ) {
 						return msg.replyMsg( lang.get('settings.' + prelang + 'changed') + ' ' + ( channel.role ? `<@&${channel.role}>` : '@everyone' ) + rolehelp, {}, true );
 					}
-					sql = 'INSERT INTO discord(role, guild, channel, wiki, lang, inline, prefix) VALUES(?, ?, ?, ?, ?, ?, ?)';
+					sql = 'INSERT INTO discord(role, guild, channel, wiki, lang, inline, prefix) VALUES($1, $2, $3, $4, $5, $6, $7)';
 					sqlargs.push(guild.wiki, guild.lang, guild.inline, guild.prefix);
 				}
 			}
 			else if ( guild.role ) {
-				sql += ' AND role = ?';
+				sql += ' AND role = $3';
 				sqlargs.push(guild.role);
 			}
 			else sql += ' AND role IS NULL';
-			return db.run( sql, sqlargs, function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while editing the settings: ' + dberror );
-					msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-					return dberror;
-				}
+			return db.query( sql, sqlargs ).then( () => {
 				console.log( '- Settings successfully updated.' );
 				if ( channel ) channel.role = role;
 				else {
@@ -319,13 +300,14 @@ function cmd_settings(lang, msg, args, line, wiki) {
 				}
 				msg.replyMsg( lang.get('settings.' + prelang + 'changed') + ' ' + ( role ? `<@&${role}>` : '@everyone' ) + rolehelp, {}, true );
 				var channels = rows.filter( row => row.channel && row.lang === guild.lang && row.wiki === guild.wiki && row.prefix === guild.prefix && row.role === guild.role && row.inline === guild.inline ).map( row => row.channel );
-				if ( channels.length ) db.run( 'DELETE FROM discord WHERE channel IN (' + channels.map( row => '?' ).join(', ') + ')', channels, function (delerror) {
-					if ( delerror ) {
-						console.log( '- Error while removing the settings: ' + delerror );
-						return delerror;
-					}
+				if ( channels.length ) db.query( 'DELETE FROM discord WHERE channel IN (' + channels.map( (row, i) => '$' + ( i + 1 ) ).join(', ') + ')', channels ).then( () => {
 					console.log( '- Settings successfully removed.' );
+				}, dberror => {
+					console.log( '- Error while removing the settings: ' + dberror );
 				} );
+			}, dberror => {
+				console.log( '- Error while editing the settings: ' + dberror );
+				msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 			} );
 		}
 		
@@ -343,22 +325,20 @@ function cmd_settings(lang, msg, args, line, wiki) {
 				return msg.replyMsg( lang.get('settings.prefixinvalid') + prefixhelp, {}, true );
 			}
 			if ( args[1] === 'reset' || args[1] === 'default' ) args[1] = process.env.prefix;
-			var sql = 'UPDATE discord SET prefix = ? WHERE guild = ?';
+			var sql = 'UPDATE discord SET prefix = $1 WHERE guild = $2';
 			var sqlargs = [args[1], msg.guild.id];
 			if ( !rows.length ) {
-				sql = 'INSERT INTO discord(prefix, guild, main, lang) VALUES(?, ?, ?, ?)';
-				sqlargs.push(msg.guild.id, lang.lang);
+				sql = 'INSERT INTO discord(prefix, guild, main, lang) VALUES($1, $2, $2, $3)';
+				sqlargs.push(lang.lang);
 			}
-			return db.run( sql, sqlargs, function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while editing the settings: ' + dberror );
-					msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-					return dberror;
-				}
+			return db.query( sql, sqlargs ).then( () => {
 				console.log( '- Settings successfully updated.' );
 				guild.prefix = args[1];
 				msg.client.shard.broadcastEval( `global.patreons['${msg.guild.id}'] = '${args[1]}'` );
 				msg.replyMsg( lang.get('settings.prefixchanged') + ' `' + args[1] + '`\n' + lang.get('settings.prefixhelp', args[1] + 'settings prefix'), {}, true );
+			}, dberror => {
+				console.log( '- Error while editing the settings: ' + dberror );
+				msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 			} );
 		}
 		
@@ -372,26 +352,21 @@ function cmd_settings(lang, msg, args, line, wiki) {
 			}
 			if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
 			var value = ( ( channel || guild ).inline ? null : 1 );
-			var sql = 'UPDATE discord SET inline = ? WHERE guild = ?';
+			var sql = 'UPDATE discord SET inline = $1 WHERE guild = $2';
 			var sqlargs = [value, msg.guild.id];
 			if ( !rows.length ) {
-				sql = 'INSERT INTO discord(inline, guild, main, lang) VALUES(?, ?, ?, ?)';
-				sqlargs.push(msg.guild.id, lang.lang);
+				sql = 'INSERT INTO discord(inline, guild, main, lang) VALUES($1, $2, $2, $3)';
+				sqlargs.push(lang.lang);
 			}
 			else if ( channel ) {
-				sql = 'UPDATE discord SET inline = ? WHERE guild = ? AND channel = ?';
+				sql = 'UPDATE discord SET inline = $1 WHERE guild = $2 AND channel = $3';
 				sqlargs.push(msg.channel.id);
 				if ( !rows.includes( channel ) ) {
-					sql = 'INSERT INTO discord(inline, guild, channel, wiki, lang, role, prefix) VALUES(?, ?, ?, ?, ?, ?, ?)';
+					sql = 'INSERT INTO discord(inline, guild, channel, wiki, lang, role, prefix) VALUES($1, $2, $3, $4, $5, $6, $7)';
 					sqlargs.push(guild.wiki, guild.lang, guild.role, guild.prefix);
 				}
 			}
-			return db.run( sql, sqlargs, function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while editing the settings: ' + dberror );
-					msg.replyMsg( lang.get('settings.save_failed'), {}, true );
-					return dberror;
-				}
+			return db.query( sql, sqlargs ).then( () => {
 				console.log( '- Settings successfully updated.' );
 				if ( channel ) channel.inline = value;
 				else {
@@ -403,17 +378,21 @@ function cmd_settings(lang, msg, args, line, wiki) {
 				toggle = 'inline ' + ( ( channel || guild ).inline ? 'disabled' : 'enabled' );
 				msg.replyMsg( lang.get('settings.' + toggle + '.' + prelang + 'changed') + '\n' + lang.get('settings.' + toggle + '.help', prefix + 'settings ' + prelang + ' toggle', inlinepage), {}, true );
 				var channels = rows.filter( row => row.channel && row.lang === guild.lang && row.wiki === guild.wiki && row.prefix === guild.prefix && row.role === guild.role && row.inline === guild.inline ).map( row => row.channel );
-				if ( channels.length ) db.run( 'DELETE FROM discord WHERE channel IN (' + channels.map( row => '?' ).join(', ') + ')', channels, function (delerror) {
-					if ( delerror ) {
-						console.log( '- Error while removing the settings: ' + delerror );
-						return delerror;
-					}
+				if ( channels.length ) db.query( 'DELETE FROM discord WHERE channel IN (' + channels.map( (row, i) => '$' + ( i + 1 ) ).join(', ') + ')', channels ).then( () => {
 					console.log( '- Settings successfully removed.' );
+				}, dberror => {
+					console.log( '- Error while removing the settings: ' + dberror );
 				} );
+			}, dberror => {
+				console.log( '- Error while editing the settings: ' + dberror );
+				msg.replyMsg( lang.get('settings.save_failed'), {}, true );
 			} );
 		}
 		
 		return msg.replyMsg( text, {split:true}, true );
+	}, dberror => {
+		console.log( '- Error while getting the settings: ' + dberror );
+		msg.reactEmoji('error', true);
 	} );
 }
 

+ 34 - 49
cmds/verification.js

@@ -22,13 +22,7 @@ function cmd_verification(lang, msg, args, line, wiki) {
 		return msg.replyMsg( lang.get('general.missingperm') + ' `MANAGE_ROLES`' );
 	}
 	
-	db.all( 'SELECT configid, channel, role, editcount, postcount, usergroup, accountage, rename FROM verification WHERE guild = ? ORDER BY configid ASC', [msg.guild.id], (error, rows) => {
-		if ( error || !rows ) {
-			console.log( '- Error while getting the verifications: ' + error );
-			msg.reactEmoji('error', true);
-			return error;
-		}
-		
+	db.query( 'SELECT configid, channel, role, editcount, postcount, usergroup, accountage, rename FROM verification WHERE guild = $1 ORDER BY configid ASC', [msg.guild.id] ).then( ({rows}) => {
 		var prefix = ( patreons[msg.guild.id] || process.env.prefix );
 		if ( args[0] && args[0].toLowerCase() === 'add' ) {
 			var limit = verificationLimit[( patreons[msg.guild.id] ? 'patreon' : 'default' )];
@@ -52,14 +46,12 @@ function cmd_verification(lang, msg, args, line, wiki) {
 				if ( new_configid === i ) new_configid++;
 				else break;
 			}
-			return db.run( 'INSERT INTO verification(guild, configid, channel, role) VALUES(?, ?, ?, ?)', [msg.guild.id, new_configid, '|' + msg.channel.id + '|', roles], function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while adding the verification: ' + dberror );
-					msg.replyMsg( lang.get('verification.save_failed'), {}, true );
-					return dberror;
-				}
+			return db.query( 'INSERT INTO verification(guild, configid, channel, role) VALUES($1, $2, $3, $4)', [msg.guild.id, new_configid, '|' + msg.channel.id + '|', roles] ).then( () => {
 				console.log( '- Verification successfully added.' );
 				msg.replyMsg( lang.get('verification.added') + formatVerification(false, false, {configid: new_configid, role: roles}), {}, true );
+			}, dberror => {
+				console.log( '- Error while adding the verification: ' + dberror );
+				msg.replyMsg( lang.get('verification.save_failed'), {}, true );
 			} );
 		}
 		if ( !rows.some( row => row.configid.toString() === args[0] ) ) {
@@ -84,14 +76,12 @@ function cmd_verification(lang, msg, args, line, wiki) {
 		if ( args[1] ) args[1] = args[1].toLowerCase();
 		if ( args[1] === 'delete' && !args.slice(2).join('') ) {
 			if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
-			return db.run( 'DELETE FROM verification WHERE guild = ? AND configid = ?', [msg.guild.id, row.configid], function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while removing the verification: ' + dberror );
-					msg.replyMsg( lang.get('verification.save_failed'), {}, true );
-					return dberror;
-				}
+			return db.query( 'DELETE FROM verification WHERE guild = $1 AND configid = $2', [msg.guild.id, row.configid] ).then( () => {
 				console.log( '- Verification successfully removed.' );
 				msg.replyMsg( lang.get('verification.deleted'), {}, true );
+			}, dberror => {
+				console.log( '- Error while removing the verification: ' + dberror );
+				msg.replyMsg( lang.get('verification.save_failed'), {}, true );
 			} );
 		}
 		if ( args[1] === 'rename' && !args.slice(2).join('') ) {
@@ -100,15 +90,13 @@ function cmd_verification(lang, msg, args, line, wiki) {
 				return msg.replyMsg( lang.get('general.missingperm') + ' `MANAGE_NICKNAMES`' );
 			}
 			if ( process.env.READONLY ) return msg.replyMsg( lang.get('general.readonly') + '\n' + process.env.invite, {}, true );
-			return db.run( 'UPDATE verification SET rename = ? WHERE guild = ? AND configid = ?', [( row.rename ? 0 : 1 ), msg.guild.id, row.configid], function (dberror) {
-				if ( dberror ) {
-					console.log( '- Error while updating the verification: ' + dberror );
-					msg.replyMsg( lang.get('verification.save_failed'), {}, true );
-					return dberror;
-				}
+			return db.query( 'UPDATE verification SET rename = $1 WHERE guild = $2 AND configid = $3', [( row.rename ? 0 : 1 ), msg.guild.id, row.configid] ).then( () => {
 				console.log( '- Verification successfully updated.' );
 				row.rename = ( row.rename ? 0 : 1 );
 				msg.sendChannel( '<@' + msg.author.id + '>, ' + lang.get('verification.updated') + formatVerification(), {split:true}, true );
+			}, dberror => {
+				console.log( '- Error while updating the verification: ' + dberror );
+				msg.replyMsg( lang.get('verification.save_failed'), {}, true );
 			} );
 		}
 		if ( args[2] ) {
@@ -126,15 +114,13 @@ function cmd_verification(lang, msg, args, line, wiki) {
 				} );
 				if ( channels.some( channel => !channel ) ) return msg.replyMsg( lang.get('verification.channel_missing'), {}, true );
 				channels = channels.map( channel => channel.id ).join('|');
-				if ( channels.length ) return db.run( 'UPDATE verification SET channel = ? WHERE guild = ? AND configid = ?', ['|' + channels + '|', msg.guild.id, row.configid], function (dberror) {
-					if ( dberror ) {
-						console.log( '- Error while updating the verification: ' + dberror );
-						msg.replyMsg( lang.get('verification.save_failed'), {}, true );
-						return dberror;
-					}
+				if ( channels.length ) return db.query( 'UPDATE verification SET channel = $1 WHERE guild = $2 AND configid = $3', ['|' + channels + '|', msg.guild.id, row.configid] ).then( () => {
 					console.log( '- Verification successfully updated.' );
 					row.channel = '|' + channels + '|';
 					msg.sendChannel( '<@' + msg.author.id + '>, ' + lang.get('verification.updated') + formatVerification(), {split:true}, true );
+				}, dberror => {
+					console.log( '- Error while updating the verification: ' + dberror );
+					msg.replyMsg( lang.get('verification.save_failed'), {}, true );
 				} );
 			}
 			if ( args[1] === 'role' ) {
@@ -150,15 +136,13 @@ function cmd_verification(lang, msg, args, line, wiki) {
 				if ( roles.some( role => !role ) ) return msg.replyMsg( lang.get('verification.role_missing'), {}, true );
 				if ( roles.some( role => role.managed || role.id === msg.guild.id ) ) return msg.replyMsg( lang.get('verification.role_managed'), {}, true );
 				roles = roles.map( role => role.id ).join('|');
-				if ( roles.length ) return db.run( 'UPDATE verification SET role = ? WHERE guild = ? AND configid = ?', [roles, msg.guild.id, row.configid], function (dberror) {
-					if ( dberror ) {
-						console.log( '- Error while updating the verification: ' + dberror );
-						msg.replyMsg( lang.get('verification.save_failed'), {}, true );
-						return dberror;
-					}
+				if ( roles.length ) return db.query( 'UPDATE verification SET role = $1 WHERE guild = $2 AND configid = $3', [roles, msg.guild.id, row.configid] ).then( () => {
 					console.log( '- Verification successfully updated.' );
 					row.role = roles;
 					msg.sendChannel( '<@' + msg.author.id + '>, ' + lang.get('verification.updated') + formatVerification(), {split:true}, true );
+				}, dberror => {
+					console.log( '- Error while updating the verification: ' + dberror );
+					msg.replyMsg( lang.get('verification.save_failed'), {}, true );
 				} );
 			}
 			if ( ( ( args[1] === 'editcount' || args[1] === 'accountage' ) && /^\d+$/.test(args[2]) ) || ( args[1] === 'postcount' && /^(?:-?\d+|null)$/.test(args[2]) ) ) {
@@ -167,15 +151,13 @@ function cmd_verification(lang, msg, args, line, wiki) {
 				if ( args[2] > 1000000 || args[2] < -1000000 ) {
 					return msg.replyMsg( lang.get('verification.value_too_high'), {}, true );
 				}
-				return db.run( 'UPDATE verification SET ' + args[1] + ' = ? WHERE guild = ? AND configid = ?', [args[2], msg.guild.id, row.configid], function (dberror) {
-					if ( dberror ) {
-						console.log( '- Error while updating the verification: ' + dberror );
-						msg.replyMsg( lang.get('verification.save_failed'), {}, true );
-						return dberror;
-					}
+				return db.query( 'UPDATE verification SET ' + args[1] + ' = $1 WHERE guild = $2 AND configid = $3', [args[2], msg.guild.id, row.configid] ).then( () => {
 					console.log( '- Verification successfully updated.' );
 					row[args[1]] = args[2];
 					msg.sendChannel( '<@' + msg.author.id + '>, ' + lang.get('verification.updated') + formatVerification(), {split:true}, true );
+				}, dberror => {
+					console.log( '- Error while updating the verification: ' + dberror );
+					msg.replyMsg( lang.get('verification.save_failed'), {}, true );
 				} );
 			}
 			if ( args[1] === 'usergroup' ) {
@@ -219,16 +201,16 @@ function cmd_verification(lang, msg, args, line, wiki) {
 					console.log( '- Error while getting the usergroups: ' + error );
 				} ).finally( () => {
 					usergroups = usergroups.join('|');
-					db.run( 'UPDATE verification SET usergroup = ? WHERE guild = ? AND configid = ?', [and_or + usergroups, msg.guild.id, row.configid], function (dberror) {
-						if ( dberror ) {
-							console.log( '- Error while updating the verification: ' + dberror );
-							msg.replyMsg( lang.get('verification.save_failed'), {}, true );
-							return dberror;
-						}
+					db.query( 'UPDATE verification SET usergroup = $1 WHERE guild = $2 AND configid = $3', [and_or + usergroups, msg.guild.id, row.configid] ).then( () => {
 						console.log( '- Verification successfully updated.' );
 						row.usergroup = and_or + usergroups;
 						msg.sendChannel( '<@' + msg.author.id + '>, ' + lang.get('verification.updated') + formatVerification(), {split:true}, true );
 						
+						if ( reaction ) reaction.removeEmoji();
+					}, dberror => {
+						console.log( '- Error while updating the verification: ' + dberror );
+						msg.replyMsg( lang.get('verification.save_failed'), {}, true );
+						
 						if ( reaction ) reaction.removeEmoji();
 					} );
 				} ) );
@@ -283,6 +265,9 @@ function cmd_verification(lang, msg, args, line, wiki) {
 			}
 			return verification_text;
 		}
+	}, dberror => {
+		console.log( '- Error while getting the verifications: ' + dberror );
+		msg.reactEmoji('error', true);
 	} );
 }
 

+ 1 - 1
cmds/voice.js

@@ -25,7 +25,7 @@ function cmd_voice(lang, msg, args, line, wiki) {
 				console.log( '- Voice settings successfully updated.' );
 				if ( value ) {
 					voice[msg.guild.id] = lang.lang;
-					db.query( 'SELECT lang FROM discord WHERE guild = ? AND channel IS NULL', [msg.guild.id] ).then( ({rows:[row]}) => {
+					db.query( 'SELECT lang FROM discord WHERE guild = $1 AND channel IS NULL', [msg.guild.id] ).then( ({rows:[row]}) => {
 						console.log( '- Voice language successfully updated.' );
 						voice[msg.guild.id] = row.lang;
 					}, dberror => {

+ 47 - 57
dashboard/rcscript.js

@@ -178,18 +178,7 @@ function createForm($, header, dashboardLang, settings, guildChannels, allWikis)
  * @param {import('./i18n.js')} dashboardLang - The user language
  */
 function dashboard_rcscript(res, $, guild, args, dashboardLang) {
-	db.all( 'SELECT discord.wiki mainwiki, discord.lang mainlang, (SELECT GROUP_CONCAT(DISTINCT wiki) FROM discord WHERE guild = ?) allwikis, webhook, configid, rcgcdw.wiki, rcgcdw.lang, display, rcid, postid FROM discord LEFT JOIN rcgcdw ON discord.guild = rcgcdw.guild WHERE discord.guild = ? AND discord.channel IS NULL ORDER BY configid ASC', [guild.id, guild.id], function(dberror, rows) {
-		if ( dberror ) {
-			console.log( '- Dashboard: Error while getting the RcGcDw: ' + dberror );
-			createNotice($, 'error', dashboardLang);
-			$('#text .description').html(dashboardLang.get('rcscript.explanation'));
-			$('#text code#server-id').text(guild.id);
-			$('.channel#rcscript').addClass('selected');
-			let body = $.html();
-			res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
-			res.write( body );
-			return res.end();
-		}
+	db.query( 'SELECT discord.wiki mainwiki, discord.lang mainlang, (SELECT ARRAY_AGG(DISTINCT wiki ORDER BY wiki ASC) FROM discord WHERE guild = $1) allwikis, webhook, configid, rcgcdw.wiki, rcgcdw.lang, display, rcid, postid FROM discord LEFT JOIN rcgcdw ON discord.guild = rcgcdw.guild WHERE discord.guild = $1 AND discord.channel IS NULL ORDER BY configid ASC', [guild.id] ).then( ({rows}) => {
 		if ( rows.length === 0 ) {
 			createNotice($, 'nosettings', dashboardLang, [guild.id]);
 			$('#text .description').html(dashboardLang.get('rcscript.explanation'));
@@ -202,7 +191,7 @@ function dashboard_rcscript(res, $, guild, args, dashboardLang) {
 		}
 		var wiki = rows[0].mainwiki;
 		var lang = rows[0].mainlang;
-		var allwikis = rows[0].allwikis.split(',').sort();
+		var allwikis = rows[0].allwikis;
 		if ( rows.length === 1 && rows[0].configid === null ) rows.pop();
 		$('<p>').html(dashboardLang.get('rcscript.desc', true, $('<code>').text(guild.name))).appendTo('#text .description');
 		Promise.all(rows.map( row => {
@@ -257,6 +246,16 @@ function dashboard_rcscript(res, $, guild, args, dashboardLang) {
 			res.write( body );
 			return res.end();
 		} );
+	}, dberror => {
+		console.log( '- Dashboard: Error while getting the RcGcDw: ' + dberror );
+		createNotice($, 'error', dashboardLang);
+		$('#text .description').html(dashboardLang.get('rcscript.explanation'));
+		$('#text code#server-id').text(guild.id);
+		$('.channel#rcscript').addClass('selected');
+		let body = $.html();
+		res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
+		res.write( body );
+		return res.end();
 	} );
 }
 
@@ -319,14 +318,8 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 		if ( settings.display > rcgcdwLimit.display && !response.patreon ) {
 			settings.display = rcgcdwLimit.display;
 		}
-		return db.get( 'SELECT discord.lang, GROUP_CONCAT(configid) count FROM discord LEFT JOIN rcgcdw ON discord.guild = rcgcdw.guild WHERE discord.guild = ? AND discord.channel IS NULL', [guild], function(curerror, row) {
-			if ( curerror ) {
-				console.log( '- Dashboard: Error while checking for RcGcDw: ' + curerror );
-				return res(`/guild/${guild}/rcscript/new`, 'savefail');
-			}
+		return db.query( 'SELECT discord.lang, ARRAY_REMOVE(ARRAY_AGG(configid ORDER BY configid), NULL) count FROM discord LEFT JOIN rcgcdw ON discord.guild = rcgcdw.guild WHERE discord.guild = $1 AND discord.channel IS NULL GROUP BY discord.lang', [guild] ).then( ({rows:[row]}) => {
 			if ( !row ) return res(`/guild/${guild}/rcscript`, 'savefail');
-			if ( row.count === null ) row.count = [];
-			else row.count = row.count.split(',').map( configid => parseInt(configid, 10) );
 			if ( row.count.length >= rcgcdwLimit[( response.patreon ? 'patreon' : 'default' )] ) {
 				return res(`/guild/${guild}/rcscript`, 'savefail');
 			}
@@ -363,11 +356,7 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 				if ( body.query.allmessages[0]['*'] !== guild ) {
 					return res(`/guild/${guild}/rcscript/new`, 'sysmessage', guild, wiki.toLink('MediaWiki:Custom-RcGcDw', 'action=edit'));
 				}
-				return db.get( 'SELECT reason FROM blocklist WHERE wiki = ?', [wiki.href], (blerror, block) => {
-					if ( blerror ) {
-						console.log( '- Dashboard: Error while getting the blocklist: ' + blerror );
-						return res(`/guild/${guild}/rcscript/new`, 'savefail');
-					}
+				return db.query( 'SELECT reason FROM blocklist WHERE wiki = $1', [wiki.href] ).then( ({rows:[block]}) => {
 					if ( block ) {
 						console.log( `- Dashboard: ${wiki.href} is blocked: ${block.reason}` );
 						return res(`/guild/${guild}/rcscript/new`, 'wikiblocked', body.query.general.sitename, block.reason);
@@ -410,11 +399,7 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 								if ( configid === i ) configid++;
 								else break;
 							}
-							db.run( 'INSERT INTO rcgcdw(guild, configid, webhook, wiki, lang, display, rcid, postid) VALUES(?, ?, ?, ?, ?, ?, ?, ?)', [guild, configid, webhook, wiki.href, settings.lang, settings.display, ( enableFeeds && settings.feeds_only ? -1 : null ), ( enableFeeds ? null : '-1' )], function (dberror) {
-								if ( dberror ) {
-									console.log( '- Dashboard: Error while adding the RcGcDw: ' + dberror );
-									return res(`/guild/${guild}/rcscript/new`, 'savefail');
-								}
+							db.query( 'INSERT INTO rcgcdw(guild, configid, webhook, wiki, lang, display, rcid, postid) VALUES($1, $2, $3, $4, $5, $6, $7, $8)', [guild, configid, webhook, wiki.href, settings.lang, settings.display, ( enableFeeds && settings.feeds_only ? -1 : null ), ( enableFeeds ? null : '-1' )] ).then( () => {
 								console.log( `- Dashboard: RcGcDw successfully added: ${guild}#${configid}` );
 								res(`/guild/${guild}/rcscript/${configid}`, 'save');
 								var text = lang.get('rcscript.dashboard.added', `<@${userSettings.user.id}>`, configid);
@@ -431,12 +416,18 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 								} ).catch( error => {
 									console.log( '- Dashboard: Error while notifying the guild: ' + error );
 								} );
+							}, dberror => {
+								console.log( '- Dashboard: Error while adding the RcGcDw: ' + dberror );
+								return res(`/guild/${guild}/rcscript/new`, 'savefail');
 							} );
 						}, error => {
 							console.log( '- Dashboard: Error while creating the webhook: ' + error );
 							return res(`/guild/${guild}/rcscript/new`, 'savefail');
 						} );
 					}
+				}, dberror => {
+					console.log( '- Dashboard: Error while getting the blocklist: ' + dberror );
+					return res(`/guild/${guild}/rcscript/new`, 'savefail');
 				} );
 			}, error => {
 				if ( error.message?.startsWith( 'connect ECONNREFUSED ' ) || error.message?.startsWith( 'Hostname/IP does not match certificate\'s altnames: ' ) || error.message === 'certificate has expired' ) {
@@ -449,17 +440,16 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 				}
 				return res(`/guild/${guild}/rcscript/new`, 'savefail');
 			} );
+		}, dberror => {
+			console.log( '- Dashboard: Error while checking for RcGcDw: ' + dberror );
+			return res(`/guild/${guild}/rcscript/new`, 'savefail');
 		} );
 	}, error => {
 		console.log( '- Dashboard: Error while getting the member: ' + error );
 		return res(`/guild/${guild}/rcscript/new`, 'savefail');
 	} );
 	type = parseInt(type, 10);
-	return db.get( 'SELECT discord.lang mainlang, webhook, rcgcdw.wiki, rcgcdw.lang, display, rcid, postid FROM discord LEFT JOIN rcgcdw ON discord.guild = rcgcdw.guild AND configid = ? WHERE discord.guild = ? AND discord.channel IS NULL', [type, guild], function(curerror, row) {
-		if ( curerror ) {
-			console.log( '- Dashboard: Error while checking for RcGcDw: ' + curerror );
-			return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
-		}
+	return db.query( 'SELECT discord.lang mainlang, webhook, rcgcdw.wiki, rcgcdw.lang, display, rcid, postid FROM discord LEFT JOIN rcgcdw ON discord.guild = rcgcdw.guild AND configid = $1 WHERE discord.guild = $2 AND discord.channel IS NULL', [type, guild] ).then( ({rows:[row]}) => {
 		if ( !row?.webhook ) return res(`/guild/${guild}/rcscript`, 'savefail');
 		return got.get( 'https://discord.com/api/webhooks/' + row.webhook ).then( wresponse => {
 			if ( !wresponse.body?.channel_id ) {
@@ -497,11 +487,7 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 					if ( !hasPerm(response.userPermissions, 'VIEW_CHANNEL', 'MANAGE_WEBHOOKS') ) {
 						return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
 					}
-					return db.run( 'DELETE FROM rcgcdw WHERE webhook = ?', [row.webhook], function (delerror) {
-						if ( delerror ) {
-							console.log( '- Dashboard: Error while removing the RcGcDw: ' + delerror );
-							return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
-						}
+					return db.query( 'DELETE FROM rcgcdw WHERE webhook = $1', [row.webhook] ).then( () => {
 						console.log( `- Dashboard: RcGcDw successfully removed: ${guild}#${type}` );
 						res(`/guild/${guild}/rcscript`, 'save');
 						var lang = new Lang(row.mainlang);
@@ -545,6 +531,9 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 						} ).catch( error => {
 							console.log( '- Dashboard: Error while notifying the guild: ' + error );
 						} );
+					}, dberror => {
+						console.log( '- Dashboard: Error while removing the RcGcDw: ' + dberror );
+						return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
 					} );
 				}
 				if ( newChannel && ( !hasPerm(response.botPermissions, 'MANAGE_WEBHOOKS') 
@@ -594,11 +583,7 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 					if ( row.wiki !== wiki.href && body.query.allmessages[0]['*'] !== guild ) {
 						return res(`/guild/${guild}/rcscript/${type}`, 'sysmessage', guild, wiki.toLink('MediaWiki:Custom-RcGcDw', 'action=edit'));
 					}
-					return db.get( 'SELECT reason FROM blocklist WHERE wiki = ?', [wiki.href], (blerror, block) => {
-						if ( blerror ) {
-							console.log( '- Dashboard: Error while getting the blocklist: ' + blerror );
-							return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
-						}
+					return db.query( 'SELECT reason FROM blocklist WHERE wiki = $1', [wiki.href] ).then( ({rows:[block]}) => {
 						if ( block ) {
 							console.log( `- Dashboard: ${wiki.href} is blocked: ${block.reason}` );
 							return res(`/guild/${guild}/rcscript/${type}`, 'wikiblocked', body.query.general.sitename, block.reason);
@@ -625,35 +610,31 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 						 * @param {Boolean} enableFeeds - If feeds based changes should be enabled.
 						 */
 						function updateWebhook(enableFeeds = null) {
-							var sql = 'UPDATE rcgcdw SET wiki = ?, lang = ?, display = ?';
-							var sqlargs = [wiki.href, settings.lang, settings.display];
+							var sqlargs = [row.webhook, wiki.href, settings.lang, settings.display];
+							var sql = 'UPDATE rcgcdw SET wiki = $2, lang = $3, display = $4';
 							if ( row.wiki !== wiki.href ) {
-								sql += ', rcid = ?, postid = ?';
 								sqlargs.push(( enableFeeds && settings.feeds_only ? -1 : null ), ( enableFeeds ? null : '-1' ));
+								sql += ', rcid = $5, postid = $6';
 							}
 							else {
 								if ( enableFeeds && settings.feeds_only ) {
-									sql += ', rcid = ?';
 									sqlargs.push(-1);
+									sql += ', rcid = $' + sqlargs.length;
 								}
 								else if ( row.rcid === -1 ) {
-									sql += ', rcid = ?';
 									sqlargs.push(null);
+									sql += ', rcid = $' + sqlargs.length;
 								}
 								if ( !enableFeeds ) {
-									sql += ', postid = ?';
 									sqlargs.push('-1');
+									sql += ', postid = $' + sqlargs.length;
 								}
 								else if ( row.postid === '-1' ) {
-									sql += ', postid = ?';
 									sqlargs.push(null);
+									sql += ', postid = $' + sqlargs.length;
 								}
 							}
-							db.run( sql + ' WHERE webhook = ?', [...sqlargs, row.webhook], function (dberror) {
-								if ( dberror ) {
-									console.log( '- Dashboard: Error while updating the RcGcDw: ' + dberror );
-									return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
-								}
+							db.query( sql + ' WHERE webhook = $1', sqlargs ).then( () => {
 								console.log( `- Dashboard: RcGcDw successfully updated: ${guild}#${type}` );
 								var lang = new Lang(row.mainlang);
 								var webhook_lang = new Lang(settings.lang, 'rcscript.webhook');
@@ -755,8 +736,14 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 								} ).catch( error => {
 									console.log( '- Dashboard: Error while notifying the guild: ' + error );
 								} );
+							}, dberror => {
+								console.log( '- Dashboard: Error while updating the RcGcDw: ' + dberror );
+								return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
 							} );
 						}
+					}, dberror => {
+						console.log( '- Dashboard: Error while getting the blocklist: ' + dberror );
+						return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
 					} );
 				}, error => {
 					if ( error.message?.startsWith( 'connect ECONNREFUSED ' ) || error.message?.startsWith( 'Hostname/IP does not match certificate\'s altnames: ' ) || error.message === 'certificate has expired' ) {
@@ -777,6 +764,9 @@ function update_rcscript(res, userSettings, guild, type, settings) {
 			console.log( '- Dashboard: Error while getting the webhook: ' + error );
 			return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
 		} );
+	}, dberror => {
+		console.log( '- Dashboard: Error while checking for RcGcDw: ' + dberror );
+		return res(`/guild/${guild}/rcscript/${type}`, 'savefail');
 	} );
 }
 

+ 94 - 106
dashboard/settings.js

@@ -171,7 +171,7 @@ function createForm($, header, dashboardLang, settings, guildRoles, guildChannel
  * @param {import('./i18n.js')} dashboardLang - The user language
  */
 function dashboard_settings(res, $, guild, args, dashboardLang) {
-	db.query( 'SELECT channel, wiki, lang, role, inline, prefix, patreon FROM discord WHERE guild = $1 ORDER BY channel ASC', [guild.id] ).then( ({rows}) => {
+	db.query( 'SELECT channel, wiki, lang, role, inline, prefix, patreon FROM discord WHERE guild = $1 ORDER BY channel DESC NULLS LAST', [guild.id] ).then( ({rows}) => {
 		$('<p>').html(dashboardLang.get('settings.desc', true, $('<code>').text(guild.name))).appendTo('#text .description');
 		if ( !rows.length ) {
 			$('.channel#settings').addClass('selected');
@@ -316,28 +316,18 @@ function update_settings(res, userSettings, guild, type, settings) {
 		if ( type !== 'default' && !hasPerm(response.userPermissions, 'VIEW_CHANNEL', 'SEND_MESSAGES') ) {
 			return res(`/guild/${guild}/settings/${type}`, 'savefail');
 		}
-		if ( settings.delete_settings ) return db.get( 'SELECT GROUP_CONCAT(DISTINCT main.lang) guildlang, main.lang mainlang, main.wiki mainwiki, main.role mainrole, main.inline maininline, old.wiki, old.lang, old.role, old.inline FROM discord main LEFT JOIN discord old ON main.guild = old.guild AND old.channel = ? WHERE main.guild = ? AND ( main.channel = ? OR main.channel IS NULL ) ORDER BY main.channel DESC', [( response.isCategory ? '#' : '' ) + type, guild, '#' + response.parentID], function(dberror, row) {
-			db.run( 'DELETE FROM discord WHERE guild = ? AND channel = ?', [guild, ( response.isCategory ? '#' : '' ) + type], function (delerror) {
-				if ( delerror ) {
-					console.log( '- Dashboard: Error while removing the settings: ' + delerror );
-					return res(`/guild/${guild}/settings/${type}`, 'savefail');
-				}
-				console.log( `- Dashboard: Settings successfully removed: ${guild}#${type}` );
-				res(`/guild/${guild}/settings`, 'save');
-				if ( dberror ) {
-					console.log( '- Dashboard: Error while notifying the guild: ' + dberror );
-					return;
-				}
-				if ( !row || row.wiki === null ) return;
-				var lang = new Lang(( row.guildlang.split(',').find( guildlang => {
-					return ( guildlang !== row.mainlang );
-				} ) || row.mainlang ));
+		if ( settings.delete_settings ) return db.query( 'DELETE FROM discord WHERE guild = $1 AND channel = $2 RETURNING wiki, lang, role, inline', [guild, ( response.isCategory ? '#' : '' ) + type] ).then( ({rows:[channel]}) => {
+			console.log( `- Dashboard: Settings successfully removed: ${guild}#${type}` );
+			res(`/guild/${guild}/settings`, 'save');
+			if ( !channel ) return;
+			db.query( 'SELECT channel, wiki, lang, role, inline FROM discord WHERE guild = $1 AND ( channel = $2 OR channel IS NULL ) ORDER BY channel DESC NULLS LAST', [guild, '#' + response.parentID] ).then( ({rows:[row, {lang: guildlang} = {}]}) => {
+				var lang = new Lang(( guildlang || row.lang ));
 				var text = lang.get('settings.dashboard.removed', `<@${userSettings.user.id}>`, `<#${type}>`);
-				if ( row.wiki !== row.mainwiki ) text += `\n${lang.get('settings.currentwiki')} <${row.wiki}>`;
+				if ( channel.wiki !== row.wiki ) text += `\n${lang.get('settings.currentwiki')} <${channel.wiki}>`;
 				if ( response.patreon ) {
-					if ( row.lang !== row.mainlang ) text += `\n${lang.get('settings.currentlang')} \`${allLangs.names[row.lang]}\``;
-					if ( row.role !== row.mainrole ) text += `\n${lang.get('settings.currentrole')} ` + ( row.role ? `<@&${row.role}>` : '@everyone' );
-					if ( row.inline !== row.maininline ) text += `\n${lang.get('settings.currentinline')} ${( row.inline ? '~~' : '' )}\`[[${( lang.localNames.page || 'page' )}]]\`${( row.inline ? '~~' : '' )}`;
+					if ( channel.lang !== row.lang ) text += `\n${lang.get('settings.currentlang')} \`${allLangs.names[channel.lang]}\``;
+					if ( channel.role !== row.role ) text += `\n${lang.get('settings.currentrole')} ` + ( channel.role ? `<@&${channel.role}>` : '@everyone' );
+					if ( channel.inline !== row.inline ) text += `\n${lang.get('settings.currentinline')} ${( channel.inline ? '~~' : '' )}\`[[${( lang.localNames.page || 'page' )}]]\`${( channel.inline ? '~~' : '' )}`;
 				}
 				text += `\n<${new URL(`/guild/${guild}/settings`, process.env.dashboard).href}>`;
 				sendMsg( {
@@ -345,9 +335,15 @@ function update_settings(res, userSettings, guild, type, settings) {
 				} ).catch( error => {
 					console.log( '- Dashboard: Error while notifying the guild: ' + error );
 				} );
+			}, dberror => {
+				console.log( '- Dashboard: Error while notifying the guild: ' + dberror );
 			} );
+		}, dberror => {
+			console.log( '- Dashboard: Error while removing the settings: ' + dberror );
+			return res(`/guild/${guild}/settings/${type}`, 'savefail');
 		} );
 		var wiki = Wiki.fromInput(settings.wiki);
+		var embed;
 		return got.get( wiki + 'api.php?&action=query&meta=siteinfo&siprop=general|extensions&format=json', {
 			responseType: 'text'
 		} ).then( fresponse => {
@@ -365,24 +361,53 @@ function update_settings(res, userSettings, guild, type, settings) {
 			}
 			return fresponse;
 		} ).then( fresponse => {
-			return new Promise( function (resolve, reject) {
-				db.get( 'SELECT guild.lang guildlang, main.lang, main.wiki, main.role, main.inline, main.prefix FROM discord main LEFT JOIN discord guild ON main.guild = guild.guild AND guild.channel IS NULL WHERE main.guild = ? AND ( main.channel = ? OR main.channel IS NULL ) ORDER BY main.channel DESC', [guild, '#' + response.parentID], function(error, row) {
-					if ( error ) {
-						console.log( '- Dashboard: Error while getting the settings: ' + error );
-						return reject();
+			return db.query( 'SELECT channel, wiki, lang, role, inline, prefix FROM discord WHERE guild = $1 AND ( channel = $2 OR channel IS NULL ) ORDER BY channel DESC NULLS LAST', [guild, '#' + response.parentID] ).then( ({rows:[row, {lang: guildlang} = {}]}) => {
+				row.guildlang = ( guildlang || row.lang );
+				var body = fresponse.body;
+				if ( fresponse.statusCode !== 200 || body?.batchcomplete === undefined || !body?.query?.general || !body?.query?.extensions ) {
+					console.log( '- Dashboard: ' + fresponse.statusCode + ': Error while testing the wiki: ' + body?.error?.info );
+					if ( row.wiki === wiki.href ) return row;
+					if ( body?.error?.info === 'You need read permission to use this module.' ) {
+						return Promise.reject('private');
+					}
+					return Promise.reject();
+				}
+				wiki.updateWiki(body.query.general);
+				if ( !wiki.isFandom() ) {
+					let notice = [];
+					if ( body.query.general.generator.replace( /^MediaWiki 1\.(\d\d).*$/, '$1' ) <= 30 ) {
+						console.log( '- Dashboard: This wiki is using ' + body.query.general.generator + '.' );
+						notice.push({
+							name: 'MediaWiki',
+							value: lang.get('test.MediaWiki', '[MediaWiki 1.30](https://www.mediawiki.org/wiki/MediaWiki_1.30)', body.query.general.generator)
+						});
+					}
+					if ( !body.query.extensions.some( extension => extension.name === 'TextExtracts' ) ) {
+						console.log( '- Dashboard: This wiki is missing Extension:TextExtracts.' );
+						notice.push({
+							name: 'TextExtracts',
+							value: lang.get('test.TextExtracts', '[TextExtracts](https://www.mediawiki.org/wiki/Extension:TextExtracts)')
+						});
 					}
-					var body = fresponse.body;
-					if ( fresponse.statusCode !== 200 || body?.batchcomplete === undefined || !body?.query?.general || !body?.query?.extensions ) {
-						console.log( '- Dashboard: ' + fresponse.statusCode + ': Error while testing the wiki: ' + body?.error?.info );
-						if ( row?.wiki === wiki.href ) return resolve(row);
-						if ( body?.error?.info === 'You need read permission to use this module.' ) {
-							return reject('private');
+					if ( !body.query.extensions.some( extension => extension.name === 'PageImages' ) ) {
+						console.log( '- Dashboard: This wiki is missing Extension:PageImages.' );
+						notice.push({
+							name: 'PageImages',
+							value: lang.get('test.PageImages', '[PageImages](https://www.mediawiki.org/wiki/Extension:PageImages)')
+						});
+					}
+					if ( notice.length ) {
+						embed = {
+							author: {name: body.query.general.sitename},
+							title: lang.get('test.notice'),
+							fields: notice
 						}
-						return reject();
 					}
-					wiki.updateWiki(body.query.general);
-					return resolve(row, body.query);
-				} );
+				}
+				return row;
+			}, dberror => {
+				console.log( '- Dashboard: Error while getting the settings: ' + dberror );
+				return Promise.reject();
 			} );
 		}, error => {
 			if ( error.message?.startsWith( 'connect ECONNREFUSED ' ) || error.message?.startsWith( 'Hostname/IP does not match certificate\'s altnames: ' ) || error.message === 'certificate has expired' ) {
@@ -394,40 +419,8 @@ function update_settings(res, userSettings, guild, type, settings) {
 				return Promise.reject('timeout');
 			}
 			return Promise.reject();
-		} ).then( (row, query) => {
+		} ).then( row => {
 			var lang = new Lang(( type === 'default' && settings.lang || row.guildlang ));
-			var embed;
-			if ( !wiki.isFandom() && query ) {
-				let notice = [];
-				if ( query.general.generator.replace( /^MediaWiki 1\.(\d\d).*$/, '$1' ) <= 30 ) {
-					console.log( '- Dashboard: This wiki is using ' + query.general.generator + '.' );
-					notice.push({
-						name: 'MediaWiki',
-						value: lang.get('test.MediaWiki', '[MediaWiki 1.30](https://www.mediawiki.org/wiki/MediaWiki_1.30)', query.general.generator)
-					});
-				}
-				if ( !query.extensions.some( extension => extension.name === 'TextExtracts' ) ) {
-					console.log( '- Dashboard: This wiki is missing Extension:TextExtracts.' );
-					notice.push({
-						name: 'TextExtracts',
-						value: lang.get('test.TextExtracts', '[TextExtracts](https://www.mediawiki.org/wiki/Extension:TextExtracts)')
-					});
-				}
-				if ( !query.extensions.some( extension => extension.name === 'PageImages' ) ) {
-					console.log( '- Dashboard: This wiki is missing Extension:PageImages.' );
-					notice.push({
-						name: 'PageImages',
-						value: lang.get('test.PageImages', '[PageImages](https://www.mediawiki.org/wiki/Extension:PageImages)')
-					});
-				}
-				if ( notice.length ) {
-					embed = {
-						author: {name: query.general.sitename},
-						title: lang.get('test.notice'),
-						fields: notice
-					}
-				}
-			}
 			if ( type === 'default' ) {
 				if ( settings.channel || !settings.lang || ( !response.patreon !== !settings.prefix ) ) {
 					return res(`/guild/${guild}/settings`, 'savefail');
@@ -439,11 +432,7 @@ function update_settings(res, userSettings, guild, type, settings) {
 					settings.prefix = settings.prefix.trim().toLowerCase();
 					if ( settings.prefix_space ) settings.prefix += ' ';
 				}
-				if ( !row ) return db.run( 'INSERT INTO discord(wiki, lang, role, inline, prefix, guild, main) VALUES(?, ?, ?, ?, ?, ?, ?)', [wiki.href, settings.lang, ( settings.role || null ), ( settings.inline ? null : 1 ), ( settings.prefix || process.env.prefix ), guild, guild], function(dberror) {
-					if ( dberror ) {
-						console.log( '- Dashboard: Error while saving the settings: ' + dberror );
-						return res(`/guild/${guild}/settings`, 'savefail');
-					}
+				if ( !row ) return db.query( 'INSERT INTO discord(wiki, lang, role, inline, prefix, guild, main) VALUES($1, $2, $3, $4, $5, $6, $6)', [wiki.href, settings.lang, ( settings.role || null ), ( settings.inline ? null : 1 ), ( settings.prefix || process.env.prefix ), guild] ).then( () => {
 					console.log( '- Dashboard: Settings successfully saved: ' + guild );
 					res(`/guild/${guild}/settings`, 'save');
 					var text = lang.get('settings.dashboard.updated', `<@${userSettings.user.id}>`);
@@ -461,6 +450,9 @@ function update_settings(res, userSettings, guild, type, settings) {
 					} ).catch( error => {
 						console.log( '- Dashboard: Error while notifying the guild: ' + error );
 					} );
+				}, dberror => {
+					console.log( '- Dashboard: Error while saving the settings: ' + dberror );
+					return res(`/guild/${guild}/settings`, 'savefail');
 				} );
 				var diff = [];
 				var file = [];
@@ -492,34 +484,27 @@ function update_settings(res, userSettings, guild, type, settings) {
 					var dbupdate = [];
 					if ( response.patreon ) {
 						dbupdate.push([
-							'UPDATE discord SET wiki = ?, lang = ?, role = ?, inline = ?, prefix = ? WHERE guild = ? AND channel IS NULL',
+							'UPDATE discord SET wiki = $1, lang = $2, role = $3, inline = $4, prefix = $5 WHERE guild = $6 AND channel IS NULL',
 							[wiki.href, settings.lang, ( settings.role || null ), ( settings.inline ? null : 1 ), ( settings.prefix || process.env.prefix ), guild]
 						]);
 					}
 					else {
 						if ( updateGuild ) {
 							dbupdate.push([
-								'UPDATE discord SET wiki = ? WHERE guild = ? AND channel IS NULL',
+								'UPDATE discord SET wiki = $1 WHERE guild = $2 AND channel IS NULL',
 								[wiki.href, guild]
 							]);
 						}
 						if ( updateChannel ) {
 							dbupdate.push([
-								'UPDATE discord SET lang = ?, role = ?, inline = ?, prefix = ? WHERE guild = ?',
+								'UPDATE discord SET lang = $1, role =  $2, inline =  $3, prefix = $4 WHERE guild = $5',
 								[settings.lang, ( settings.role || null ), ( settings.inline ? null : 1 ), ( settings.prefix || process.env.prefix ), guild]
 							]);
 						}
 					}
-					return Promise.all([
-						...dbupdate.map( ([sql, sqlargs]) => {
-							return new Promise( function (resolve, reject) {
-								db.run( sql, sqlargs, function(error) {
-									if (error) reject(error);
-									else resolve(this);
-								} );
-							} );
-						} )
-					]).then( () => {
+					return Promise.all(dbupdate.map( ([sql, sqlargs]) => {
+						return db.query( sql, sqlargs );
+					} )).then( () => {
 						console.log( '- Dashboard: Settings successfully saved: ' + guild );
 						res(`/guild/${guild}/settings`, 'save');
 						var text = lang.get('settings.dashboard.updated', `<@${userSettings.user.id}>`);
@@ -532,8 +517,8 @@ function update_settings(res, userSettings, guild, type, settings) {
 						} ).catch( error => {
 							console.log( '- Dashboard: Error while notifying the guild: ' + error );
 						} );
-					}, error => {
-						console.log( '- Dashboard: Error while saving the settings: ' + error );
+					}, dberror => {
+						console.log( '- Dashboard: Error while saving the settings: ' + dberror );
 						return res(`/guild/${guild}/settings`, 'savefail');
 					} );
 				}
@@ -548,27 +533,28 @@ function update_settings(res, userSettings, guild, type, settings) {
 				if ( type === 'new' ) {
 					return res(`/guild/${guild}/settings/${type}`, 'nochange');
 				}
-				return db.run( 'DELETE FROM discord WHERE guild = ? AND channel = ?', [guild, ( response.isCategory ? '#' : '' ) + type], function (delerror) {
-					if ( delerror ) {
-						console.log( '- Dashboard: Error while removing the settings: ' + delerror );
-						return res(`/guild/${guild}/settings/${type}`, 'savefail');
-					}
+				return db.query( 'DELETE FROM discord WHERE guild = $1 AND channel = $2 RETURNING wiki, lang, role, inline', [guild, ( response.isCategory ? '#' : '' ) + type] ).then( ({rows:[channel]}) => {
 					console.log( `- Dashboard: Settings successfully removed: ${guild}#${type}` );
 					res(`/guild/${guild}/settings`, 'save');
 					var text = lang.get('settings.dashboard.removed', `<@${userSettings.user.id}>`, `<#${type}>`);
+					if ( channel.wiki !== row.wiki ) text += `\n${lang.get('settings.currentwiki')} <${channel.wiki}>`;
+					if ( response.patreon ) {
+						if ( channel.lang !== row.lang ) text += `\n${lang.get('settings.currentlang')} \`${allLangs.names[channel.lang]}\``;
+						if ( channel.role !== row.role ) text += `\n${lang.get('settings.currentrole')} ` + ( channel.role ? `<@&${channel.role}>` : '@everyone' );
+						if ( channel.inline !== row.inline ) text += `\n${lang.get('settings.currentinline')} ${( channel.inline ? '~~' : '' )}\`[[${( lang.localNames.page || 'page' )}]]\`${( channel.inline ? '~~' : '' )}`;
+					}
 					text += `\n<${new URL(`/guild/${guild}/settings`, process.env.dashboard).href}>`;
 					sendMsg( {
 						type: 'notifyGuild', guild, text
 					} ).catch( error => {
 						console.log( '- Dashboard: Error while notifying the guild: ' + error );
 					} );
+				}, dberror => {
+					console.log( '- Dashboard: Error while removing the settings: ' + dberror );
+					return res(`/guild/${guild}/settings/${type}`, 'savefail');
 				} );
 			}
-			return db.get( 'SELECT lang, wiki, role, inline FROM discord WHERE guild = ? AND channel = ?', [guild, ( response.isCategory ? '#' : '' ) + settings.channel], function(curerror, channel) {
-				if ( curerror ) {
-					console.log( '- Dashboard: Error while getting the channel settings: ' + curerror );
-					return res(`/guild/${guild}/settings/${type}`, 'savefail');
-				}
+			return db.query( 'SELECT lang, wiki, role, inline FROM discord WHERE guild = $1 AND channel = $2', [guild, ( response.isCategory ? '#' : '' ) + settings.channel] ).then( ({rows:[channel]}) => {
 				if ( !channel ) channel = row;
 				var diff = [];
 				var file = [];
@@ -591,17 +577,13 @@ function update_settings(res, userSettings, guild, type, settings) {
 				if ( !diff.length ) {
 					return res(`/guild/${guild}/settings/${settings.channel}`, 'save');
 				}
-				let sql = 'UPDATE discord SET wiki = ?, lang = ?, role = ?, inline = ? WHERE guild = ? AND channel = ?';
+				let sql = 'UPDATE discord SET wiki = $1, lang = $2, role = $3, inline = $4 WHERE guild = $5 AND channel = $6';
 				let sqlargs = [wiki.href, ( settings.lang || channel.lang ), ( response.patreon ? ( settings.role || null ) : channel.role ), ( response.patreon ? ( settings.inline ? null : 1 ) : channel.inline ), guild, ( response.isCategory ? '#' : '' ) + settings.channel];
 				if ( channel === row ) {
-					sql = 'INSERT INTO discord(wiki, lang, role, inline, guild, channel, prefix) VALUES(?, ?, ?, ?, ?, ?, ?)';
+					sql = 'INSERT INTO discord(wiki, lang, role, inline, guild, channel, prefix) VALUES($1, $2, $3, $4, $5, $6, $7)';
 					sqlargs.push(row.prefix);
 				}
-				return db.run( sql, sqlargs, function(dberror) {
-					if ( dberror ) {
-						console.log( '- Dashboard: Error while saving the settings: ' + dberror );
-						return res(`/guild/${guild}/settings/${type}`, 'savefail');
-					}
+				return db.query( sql, sqlargs ).then( () => {
 					console.log( `- Dashboard: Settings successfully saved: ${guild}#${settings.channel}` );
 					res(`/guild/${guild}/settings/${settings.channel}`, 'save');
 					var text = lang.get('settings.dashboard.channel', `<@${userSettings.user.id}>`, `<#${settings.channel}>`);
@@ -613,7 +595,13 @@ function update_settings(res, userSettings, guild, type, settings) {
 					} ).catch( error => {
 						console.log( '- Dashboard: Error while notifying the guild: ' + error );
 					} );
+				}, dberror => {
+					console.log( '- Dashboard: Error while saving the settings: ' + dberror );
+					return res(`/guild/${guild}/settings/${type}`, 'savefail');
 				} );
+			}, dberror => {
+				console.log( '- Dashboard: Error while getting the channel settings: ' + dberror );
+				return res(`/guild/${guild}/settings/${type}`, 'savefail');
 			} );
 		}, error => {
 			return res(`/guild/${guild}/settings/${type}`, 'savefail', error);

+ 37 - 48
dashboard/verification.js

@@ -224,18 +224,7 @@ function createForm($, header, dashboardLang, settings, guildChannels, guildRole
  * @param {import('./i18n.js')} dashboardLang - The user language
  */
 function dashboard_verification(res, $, guild, args, dashboardLang) {
-	db.all( 'SELECT wiki, discord.role defaultrole, prefix, configid, verification.channel, verification.role, editcount, postcount, usergroup, accountage, rename FROM discord LEFT JOIN verification ON discord.guild = verification.guild WHERE discord.guild = ? AND discord.channel IS NULL ORDER BY configid ASC', [guild.id], function(dberror, rows) {
-		if ( dberror ) {
-			console.log( '- Dashboard: Error while getting the verifications: ' + dberror );
-			createNotice($, 'error', dashboardLang);
-			$('#text .description').html(dashboardLang.get('verification.explanation'));
-			$('#text code.prefix').prepend(escapeText(process.env.prefix));
-			$('.channel#verification').addClass('selected');
-			let body = $.html();
-			res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
-			res.write( body );
-			return res.end();
-		}
+	db.query( 'SELECT wiki, discord.role defaultrole, prefix, configid, verification.channel, verification.role, editcount, postcount, usergroup, accountage, rename FROM discord LEFT JOIN verification ON discord.guild = verification.guild WHERE discord.guild = $1 AND discord.channel IS NULL ORDER BY configid ASC', [guild.id] ).then( ({rows}) => {
 		if ( rows.length === 0 ) {
 			createNotice($, 'nosettings', dashboardLang, [guild.id]);
 			$('#text .description').html(dashboardLang.get('verification.explanation'));
@@ -301,6 +290,16 @@ function dashboard_verification(res, $, guild, args, dashboardLang) {
 		res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
 		res.write( body );
 		return res.end();
+	}, dberror => {
+		console.log( '- Dashboard: Error while getting the verifications: ' + dberror );
+		createNotice($, 'error', dashboardLang);
+		$('#text .description').html(dashboardLang.get('verification.explanation'));
+		$('#text code.prefix').prepend(escapeText(process.env.prefix));
+		$('.channel#verification').addClass('selected');
+		let body = $.html();
+		res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
+		res.write( body );
+		return res.end();
 	} );
 }
 
@@ -406,20 +405,11 @@ function update_verification(res, userSettings, guild, type, settings) {
 			userSettings.guilds.isMember.delete(guild);
 			return res('/', 'savefail');
 		}
-		if ( settings.delete_settings ) return db.get( 'SELECT lang, verification.channel, verification.role, editcount, postcount, usergroup, accountage, rename FROM discord LEFT JOIN verification ON discord.guild = verification.guild AND configid = ? WHERE discord.guild = ? AND discord.channel IS NULL', [type, guild], function(dberror, row) {
-			if ( !dberror && !row?.channel ) return res(`/guild/${guild}/verification`, 'save');
-			db.run( 'DELETE FROM verification WHERE guild = ? AND configid = ?', [guild, type], function (delerror) {
-				if ( delerror ) {
-					console.log( '- Dashboard: Error while removing the verification: ' + delerror );
-					return res(`/guild/${guild}/verification/${type}`, 'savefail');
-				}
-				console.log( `- Dashboard: Verification successfully removed: ${guild}#${type}` );
-				res(`/guild/${guild}/verification`, 'save');
-				if ( dberror ) {
-					console.log( '- Dashboard: Error while notifying the guild: ' + dberror );
-					return;
-				}
-				var lang = new Lang(row.lang);
+		if ( settings.delete_settings ) return db.query( 'DELETE FROM verification WHERE guild = $1 AND configid = $2 RETURNING channel, role, editcount, postcount, usergroup, accountage, rename', [guild, type] ).then( ({rows:[row]}) => {
+			console.log( `- Dashboard: Verification successfully removed: ${guild}#${type}` );
+			res(`/guild/${guild}/verification`, 'save');
+			if ( row ) db.query( 'SELECT lang FROM discord WHERE guild = $1 AND channel IS NULL', [guild] ).then( ({rows:[channel]}) => {
+				var lang = new Lang(channel.lang);
 				var text = lang.get('verification.dashboard.removed', `<@${userSettings.user.id}>`, type);
 				if ( row ) {
 					text += '\n' + lang.get('verification.channel') + ' <#' + row.channel.split('|').filter( channel => channel.length ).join('>, <#') + '>';
@@ -442,19 +432,18 @@ function update_verification(res, userSettings, guild, type, settings) {
 				} ).catch( error => {
 					console.log( '- Dashboard: Error while notifying the guild: ' + error );
 				} );
+			}, dberror => {
+				console.log( '- Dashboard: Error while notifying the guild: ' + dberror );
 			} );
+		}, dberror => {
+			console.log( '- Dashboard: Error while removing the verification: ' + dberror );
+			return res(`/guild/${guild}/verification/${type}`, 'savefail');
 		} );
 		if ( !hasPerm(response.botPermissions, 'MANAGE_ROLES') ) {
 			return res(`/guild/${guild}/verification`, 'savefail');
 		}
-		if ( type === 'new' ) return db.get( 'SELECT wiki, lang, GROUP_CONCAT(configid) count FROM discord LEFT JOIN verification ON discord.guild = verification.guild WHERE discord.guild = ? AND discord.channel IS NULL', [guild], function(curerror, row) {
-			if ( curerror ) {
-				console.log( '- Dashboard: Error while checking for verifications: ' + curerror );
-				return res(`/guild/${guild}/verification/new`, 'savefail');
-			}
+		if ( type === 'new' ) return db.query( 'SELECT wiki, lang, ARRAY_REMOVE(ARRAY_AGG(configid ORDER BY configid), NULL) count FROM discord LEFT JOIN verification ON discord.guild = verification.guild WHERE discord.guild = $1 AND discord.channel IS NULL GROUP BY wiki, lang', [guild] ).then( ({rows:[row]}) => {
 			if ( !row ) return res(`/guild/${guild}/verification`, 'savefail');
-			if ( row.count === null ) row.count = [];
-			else row.count = row.count.split(',').map( configid => parseInt(configid, 10) );
 			if ( row.count.length >= verificationLimit[( response.patreon ? 'patreon' : 'default' )] ) {
 				return res(`/guild/${guild}/verification`, 'savefail');
 			}
@@ -493,11 +482,7 @@ function update_verification(res, userSettings, guild, type, settings) {
 					if ( configid === i ) configid++;
 					else break;
 				}
-				db.run( 'INSERT INTO verification(guild, configid, channel, role, editcount, postcount, usergroup, accountage, rename) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)', [guild, configid, '|' + settings.channel.join('|') + '|', settings.role.join('|'), settings.editcount, settings.postcount, settings.usergroup.join('|'), settings.accountage, ( settings.rename ? 1 : 0 )], function (dberror) {
-					if ( dberror ) {
-						console.log( '- Dashboard: Error while adding the verification: ' + dberror );
-						return res(`/guild/${guild}/verification/new`, 'savefail');
-					}
+				db.query( 'INSERT INTO verification(guild, configid, channel, role, editcount, postcount, usergroup, accountage, rename) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9)', [guild, configid, '|' + settings.channel.join('|') + '|', settings.role.join('|'), settings.editcount, settings.postcount, settings.usergroup.join('|'), settings.accountage, ( settings.rename ? 1 : 0 )] ).then( () => {
 					console.log( `- Dashboard: Verification successfully added: ${guild}#${configid}` );
 					res(`/guild/${guild}/verification/${configid}`, 'save');
 					var lang = new Lang(row.lang);
@@ -543,14 +528,16 @@ function update_verification(res, userSettings, guild, type, settings) {
 					} ).catch( error => {
 						console.log( '- Dashboard: Error while notifying the guild: ' + error );
 					} );
+				}, dberror => {
+					console.log( '- Dashboard: Error while adding the verification: ' + dberror );
+					return res(`/guild/${guild}/verification/new`, 'savefail');
 				} );
 			} );
+		}, dberror => {
+			console.log( '- Dashboard: Error while checking for verifications: ' + dberror );
+			return res(`/guild/${guild}/verification/new`, 'savefail');
 		} );
-		return db.get( 'SELECT wiki, lang, verification.channel, verification.role, editcount, postcount, usergroup, accountage, rename FROM discord LEFT JOIN verification ON discord.guild = verification.guild AND verification.configid = ? WHERE discord.guild = ? AND discord.channel IS NULL', [type, guild], function(curerror, row) {
-			if ( curerror ) {
-				console.log( '- Dashboard: Error while checking for verifications: ' + curerror );
-				return res(`/guild/${guild}/verification/${type}`, 'savefail');
-			}
+		return db.query( 'SELECT wiki, lang, verification.channel, verification.role, editcount, postcount, usergroup, accountage, rename FROM discord LEFT JOIN verification ON discord.guild = verification.guild AND verification.configid = $1 WHERE discord.guild = $2 AND discord.channel IS NULL', [type, guild] ).then( ({rows:[row]}) => {
 			if ( !row?.channel ) return res(`/guild/${guild}/verification`, 'savefail');
 			row.channel = row.channel.split('|').filter( channel => channel.length );
 			var newChannel = settings.channel.filter( channel => !row.channel.includes( channel ) );
@@ -648,11 +635,7 @@ function update_verification(res, userSettings, guild, type, settings) {
 					diff.push(lang.get('verification.rename') + ` ~~*\`${lang.get('verification.' + ( row.rename ? 'enabled' : 'disabled'))}\`*~~ → *\`${lang.get('verification.' + ( settings.rename ? 'enabled' : 'disabled'))}\`*`);
 				}
 				if ( !diff.length ) return res(`/guild/${guild}/verification/${type}`, 'save');
-				db.run( 'UPDATE verification SET channel = ?, role = ?, editcount = ?, postcount = ?, usergroup = ?, accountage = ?, rename = ? WHERE guild = ? AND configid = ?', ['|' + settings.channel.join('|') + '|', settings.role.join('|'), settings.editcount, settings.postcount, settings.usergroup.join('|'), settings.accountage, ( settings.rename ? 1 : 0 ), guild, type], function (dberror) {
-					if ( dberror ) {
-						console.log( '- Dashboard: Error while updating the verification: ' + dberror );
-						return res(`/guild/${guild}/verification/${type}`, 'savefail');
-					}
+				db.query( 'UPDATE verification SET channel = $1, role = $2, editcount = $3, postcount = $4, usergroup = $5, accountage = $6, rename = $7 WHERE guild = $8 AND configid = $9', ['|' + settings.channel.join('|') + '|', settings.role.join('|'), settings.editcount, settings.postcount, settings.usergroup.join('|'), settings.accountage, ( settings.rename ? 1 : 0 ), guild, type] ).then( () => {
 					console.log( `- Dashboard: Verification successfully updated: ${guild}#${type}` );
 					res(`/guild/${guild}/verification/${type}`, 'save');
 					var text = lang.get('verification.dashboard.updated', `<@${userSettings.user.id}>`, type);
@@ -685,8 +668,14 @@ function update_verification(res, userSettings, guild, type, settings) {
 					} ).catch( error => {
 						console.log( '- Dashboard: Error while notifying the guild: ' + error );
 					} );
+				}, dberror => {
+					console.log( '- Dashboard: Error while updating the verification: ' + dberror );
+					return res(`/guild/${guild}/verification/${type}`, 'savefail');
 				} );
 			} );
+		}, dberror => {
+			console.log( '- Dashboard: Error while checking for verifications: ' + dberror );
+			return res(`/guild/${guild}/verification/${type}`, 'savefail');
 		} );
 	}, error => {
 		console.log( '- Dashboard: Error while getting the member: ' + error );

+ 1 - 1
database.js

@@ -133,7 +133,7 @@ ALTER DATABASE "${process.env.PGDATABASE}" SET my.version TO 1;
 module.exports = db.connect().then( () => {
 	return db.query( 'SELECT CURRENT_SETTING($1) AS version', ['my.version'] ).then( ({rows:[row]}) => {
 		row.version = parseInt(row.version, 10);
-		if ( row.version > schema.length ) {
+		if ( isNaN(row.version) || row.version > schema.length ) {
 			console.log( '- Invalid database version: v' + row.version );
 			return Promise.reject();
 		}