Browse Source

Merge pull request #63 from Markus-Rost/gender

Add gender function to translations
MarkusRost 4 years ago
parent
commit
351ec24f4b

+ 4 - 2
cmds/patreon.js

@@ -1,4 +1,4 @@
-const {limit: {verification: verificationLimit, rcgcdw: rcgcdwLimit}} = require('../util/default.json');
+const {defaultPermissions, limit: {verification: verificationLimit, rcgcdw: rcgcdwLimit}} = require('../util/default.json');
 var db = require('../util/database.js');
 var db = require('../util/database.js');
 
 
 /**
 /**
@@ -17,7 +17,9 @@ function cmd_patreon(lang, msg, args, line, wiki) {
 	
 	
 	if ( args[0] === 'enable' && /^\d+$/.test(args.slice(1).join(' ')) ) return msg.client.shard.broadcastEval( `this.guilds.cache.get('${args[1]}')?.name` ).then( results => {
 	if ( args[0] === 'enable' && /^\d+$/.test(args.slice(1).join(' ')) ) return msg.client.shard.broadcastEval( `this.guilds.cache.get('${args[1]}')?.name` ).then( results => {
 		var guild = results.find( result => result !== null );
 		var guild = results.find( result => result !== null );
-		if ( guild === undefined ) return msg.replyMsg( 'I\'m not on a server with the id `' + args[1] + '`.', {}, true );
+		if ( guild === undefined ) return msg.client.generateInvite(defaultPermissions).then( invite => {
+			msg.replyMsg( 'I\'m not on a server with the id `' + args[1] + '`.\n<' + invite + '&guild_id=' + args[1] + '>', {}, true )
+		}, log_error );
 		if ( args[1] in patreons ) return msg.replyMsg( '"' + guild + '" has the patreon features already enabled.', {}, true );
 		if ( args[1] in patreons ) 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) => {
 		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 ) {
 			if ( dberror ) {

+ 31 - 25
cmds/rcscript.js

@@ -28,10 +28,6 @@ const display_types = [
 function cmd_rcscript(lang, msg, args, line, wiki) {
 function cmd_rcscript(lang, msg, args, line, wiki) {
 	if ( args[0] === 'block' && msg.isOwner() ) return blocklist(msg, args.slice(1));
 	if ( args[0] === 'block' && msg.isOwner() ) return blocklist(msg, args.slice(1));
 	if ( !msg.isAdmin() ) return msg.reactEmoji('❌');
 	if ( !msg.isAdmin() ) return msg.reactEmoji('❌');
-	if ( !msg.channel.permissionsFor(msg.client.user).has('MANAGE_WEBHOOKS') ) {
-		console.log( msg.guild.id + ': Missing permissions - MANAGE_WEBHOOKS' );
-		return msg.replyMsg( lang.get('general.missingperm') + ' `MANAGE_WEBHOOKS`' );
-	}
 	
 	
 	db.all( 'SELECT configid, webhook, wiki, lang, display, wikiid, rcid FROM rcgcdw WHERE guild = ? ORDER BY configid ASC', [msg.guild.id], (dberror, rows) => {
 	db.all( 'SELECT configid, webhook, wiki, lang, display, wikiid, rcid FROM rcgcdw WHERE guild = ? ORDER BY configid ASC', [msg.guild.id], (dberror, rows) => {
 		if ( dberror || !rows ) {
 		if ( dberror || !rows ) {
@@ -50,7 +46,11 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 		}
 		}
 
 
 		if ( args[0] === 'add' ) {
 		if ( args[0] === 'add' ) {
-			if ( !msg.channel.permissionsFor(msg.member).has('MANAGE_WEBHOOKS') ) {
+			if ( !msg.channel.permissionsFor(msg.client.user).has('MANAGE_WEBHOOKS') ) {
+				console.log( msg.guild.id + ': Missing permissions - MANAGE_WEBHOOKS' );
+				return msg.replyMsg( lang.get('general.missingperm') + ' `MANAGE_WEBHOOKS`' );
+			}
+			if ( !( msg.channel.permissionsFor(msg.member).has('MANAGE_WEBHOOKS') || ( this.isOwner() && this.evalUsed ) ) ) {
 				return msg.replyMsg( lang.get('rcscript.noadmin') );
 				return msg.replyMsg( lang.get('rcscript.noadmin') );
 			}
 			}
 			if ( rows.length >= limit ) return msg.replyMsg( lang.get('rcscript.max_entries'), {}, true );
 			if ( rows.length >= limit ) return msg.replyMsg( lang.get('rcscript.max_entries'), {}, true );
@@ -452,19 +452,21 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 				} ) );
 				} ) );
 			}
 			}
 
 
-			return msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
+			if ( rows.length > 1 ) return msg.client.fetchWebhook(...selected_row.webhook.split('/')).then( webhook => {
 				return webhook.channelID;
 				return webhook.channelID;
 			}, error => {
 			}, error => {
 				log_error(error);
 				log_error(error);
-				if ( error.name === 'DiscordAPIError' && ['Unknown Webhook', 'Invalid Webhook Token'].includes( error.message ) ) return;
-				db.run( 'DELETE FROM rcgcdw WHERE webhook = ?', [selected_row.webhook], function (delerror) {
-					if ( delerror ) {
-						console.log( '- Error while removing the RcGcDw: ' + delerror );
-						return delerror;
-					}
-					console.log( '- RcGcDw successfully removed.' );
-				} );
-				Promise.reject();
+				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;
+						}
+						console.log( '- RcGcDw successfully removed.' );
+					} );
+					Promise.reject();
+				}
+				return;
 			} ).then( channel => {
 			} ).then( channel => {
 				var text = lang.get('rcscript.current_selected') + '\n';
 				var text = lang.get('rcscript.current_selected') + '\n';
 				text += '\n' + lang.get('rcscript.channel') + ' <#' + channel + '>\n';
 				text += '\n' + lang.get('rcscript.channel') + ' <#' + channel + '>\n';
@@ -487,17 +489,21 @@ function cmd_rcscript(lang, msg, args, line, wiki) {
 			}, () => msg.replyMsg( lang.get('rcscript.deleted'), {}, true ) );
 			}, () => msg.replyMsg( lang.get('rcscript.deleted'), {}, true ) );
 		}
 		}
 
 
-		Promise.all(rows.map( row => msg.client.fetchWebhook(...row.webhook.split('/')).catch( error => {
+		Promise.all(rows.map( row => msg.client.fetchWebhook(...row.webhook.split('/')).then( webhook => {
+			return webhook.channelID;
+		}, error => {
 			log_error(error);
 			log_error(error);
-			if ( error.name === 'DiscordAPIError' && ['Unknown Webhook', 'Invalid Webhook Token'].includes( error.message ) ) return {};
-			db.run( 'DELETE FROM rcgcdw WHERE webhook = ?', [row.webhook], function (delerror) {
-				if ( delerror ) {
-					console.log( '- Error while removing the RcGcDw: ' + delerror );
-					return delerror;
-				}
-				console.log( '- RcGcDw successfully removed.' );
-			} );
-			return;
+			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;
+					}
+					console.log( '- RcGcDw successfully removed.' );
+				} );
+				return;
+			}
+			return {};
 		} ) )).then( webhooks => {
 		} ) )).then( webhooks => {
 			rows.forEach( (row, i) => {
 			rows.forEach( (row, i) => {
 				if ( webhooks[i] ) row.channel = webhooks[i].channelID;
 				if ( webhooks[i] ) row.channel = webhooks[i].channelID;

+ 22 - 22
cmds/verify.js

@@ -95,8 +95,8 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 			var pagelink = wiki.toLink('User:' + username, '', '', body.query.general, true);
 			var pagelink = wiki.toLink('User:' + username, '', '', body.query.general, true);
 			embed.setTitle( username.escapeFormatting() ).setURL( pagelink );
 			embed.setTitle( username.escapeFormatting() ).setURL( pagelink );
 			if ( queryuser.blockexpiry ) {
 			if ( queryuser.blockexpiry ) {
-				embed.setColor('#FF0000').setDescription( lang.get('verify.user_blocked', '[' + username.escapeFormatting() + '](' + pagelink + ')') );
-				msg.replyMsg( lang.get('verify.user_blocked_reply', username.escapeFormatting()), {embed}, false, false );
+				embed.setColor('#FF0000').setDescription( lang.get('verify.user_blocked', '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) );
+				msg.replyMsg( lang.get('verify.user_blocked_reply', username.escapeFormatting(), queryuser.gender), {embed}, false, false );
 				
 				
 				if ( reaction ) reaction.removeEmoji();
 				if ( reaction ) reaction.removeEmoji();
 				return;
 				return;
@@ -122,22 +122,22 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 					if ( wiki.endsWith( '.gamepedia.com/' ) ) {
 					if ( wiki.endsWith( '.gamepedia.com/' ) ) {
 						if ( $('.mw-blocklist').length ) {
 						if ( $('.mw-blocklist').length ) {
 							return Promise.reject({
 							return Promise.reject({
-								desc: lang.get('verify.user_gblocked', '[' + username.escapeFormatting() + '](' + pagelink + ')'),
-								reply: lang.get('verify.user_gblocked_reply', username.escapeFormatting())
+								desc: lang.get('verify.user_gblocked', '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender),
+								reply: lang.get('verify.user_gblocked_reply', username.escapeFormatting(), queryuser.gender)
 							});
 							});
 						}
 						}
 					}
 					}
 					else if ( wiki.isFandom() ) {
 					else if ( wiki.isFandom() ) {
 						if ( $('#mw-content-text .errorbox').length ) {
 						if ( $('#mw-content-text .errorbox').length ) {
 							return Promise.reject({
 							return Promise.reject({
-								desc: lang.get('verify.user_disabled', '[' + username.escapeFormatting() + '](' + pagelink + ')'),
-								reply: lang.get('verify.user_disabled_reply', username.escapeFormatting())
+								desc: lang.get('verify.user_disabled', '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender),
+								reply: lang.get('verify.user_disabled_reply', username.escapeFormatting(), queryuser.gender)
 							});
 							});
 						}
 						}
 						else if ( $('.mw-warning-with-logexcerpt').length && !$(".mw-warning-with-logexcerpt .mw-logline-block").length ) {
 						else if ( $('.mw-warning-with-logexcerpt').length && !$(".mw-warning-with-logexcerpt .mw-logline-block").length ) {
 							return Promise.reject({
 							return Promise.reject({
-								desc: lang.get('verify.user_gblocked', '[' + username.escapeFormatting() + '](' + pagelink + ')'),
-								reply: lang.get('verify.user_gblocked_reply', username.escapeFormatting())
+								desc: lang.get('verify.user_gblocked', '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender),
+								reply: lang.get('verify.user_gblocked_reply', username.escapeFormatting(), queryuser.gender)
 							});
 							});
 						}
 						}
 					}
 					}
@@ -183,12 +183,12 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 					if ( discordname.length > 50 ) discordname = discordname.substring(0, 50) + '\u2026';
 					if ( discordname.length > 50 ) discordname = discordname.substring(0, 50) + '\u2026';
 					embed.addField( lang.get('verify.discord'), msg.author.tag.escapeFormatting(), true ).addField( lang.get('verify.wiki'), ( discordname || lang.get('verify.empty') ), true );
 					embed.addField( lang.get('verify.discord'), msg.author.tag.escapeFormatting(), true ).addField( lang.get('verify.wiki'), ( discordname || lang.get('verify.empty') ), true );
 					if ( msg.author.tag.escapeFormatting() !== discordname ) {
 					if ( msg.author.tag.escapeFormatting() !== discordname ) {
-						embed.setColor('#FFFF00').setDescription( lang.get('verify.user_failed', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')') );
+						embed.setColor('#FFFF00').setDescription( lang.get('verify.user_failed', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) );
 						var help_link = '';
 						var help_link = '';
 						if ( wiki.endsWith( '.gamepedia.com/' ) ) help_link = lang.get('verify.help_gamepedia') + '?c=' + ( msg.guild.id in patreons && patreons[msg.guild.id] !== process.env.prefix ? encodeURIComponent( patreons[msg.guild.id] + ' verify' ) : 'wb' ) + ( msg.channel.name !== 'verification' ? '&ch=' + encodeURIComponent( msg.channel.name ) : '' ) + '&user=' + username.toTitle(true, true) + '&discord=' + encodeURIComponent( msg.author.username ) + '&tag=' + msg.author.discriminator;
 						if ( wiki.endsWith( '.gamepedia.com/' ) ) help_link = lang.get('verify.help_gamepedia') + '?c=' + ( msg.guild.id in patreons && patreons[msg.guild.id] !== process.env.prefix ? encodeURIComponent( patreons[msg.guild.id] + ' verify' ) : 'wb' ) + ( msg.channel.name !== 'verification' ? '&ch=' + encodeURIComponent( msg.channel.name ) : '' ) + '&user=' + username.toTitle(true, true) + '&discord=' + encodeURIComponent( msg.author.username ) + '&tag=' + msg.author.discriminator;
 						else if ( wiki.isFandom() ) help_link = lang.get('verify.help_fandom') + '/' + username.toTitle(true) + '?c=' + ( msg.guild.id in patreons && patreons[msg.guild.id] !== process.env.prefix ? encodeURIComponent( patreons[msg.guild.id] + ' verify' ) : 'wb' ) + ( msg.channel.name !== 'verification' ? '&ch=' + encodeURIComponent( msg.channel.name ) : '' ) + '&user=' + encodeURIComponent( msg.author.username ) + '&tag=' + msg.author.discriminator;
 						else if ( wiki.isFandom() ) help_link = lang.get('verify.help_fandom') + '/' + username.toTitle(true) + '?c=' + ( msg.guild.id in patreons && patreons[msg.guild.id] !== process.env.prefix ? encodeURIComponent( patreons[msg.guild.id] + ' verify' ) : 'wb' ) + ( msg.channel.name !== 'verification' ? '&ch=' + encodeURIComponent( msg.channel.name ) : '' ) + '&user=' + encodeURIComponent( msg.author.username ) + '&tag=' + msg.author.discriminator;
-						if ( help_link.length ) embed.addField( lang.get('verify.notice'), lang.get('verify.help_guide', help_link) + '\n' + help_link );
-						msg.replyMsg( lang.get('verify.user_failed_reply', username.escapeFormatting()), {embed}, false, false );
+						if ( help_link.length ) embed.addField( lang.get('verify.notice'), lang.get('verify.help_guide', help_link, queryuser.gender) + '\n' + help_link );
+						msg.replyMsg( lang.get('verify.user_failed_reply', username.escapeFormatting(), queryuser.gender), {embed}, false, false );
 						
 						
 						if ( reaction ) reaction.removeEmoji();
 						if ( reaction ) reaction.removeEmoji();
 						return;
 						return;
@@ -223,8 +223,8 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 						}
 						}
 					} );
 					} );
 					if ( verified ) {
 					if ( verified ) {
-						embed.setColor('#00FF00').setDescription( lang.get('verify.user_verified', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')') + ( rename ? '\n' + lang.get('verify.user_renamed') : '' ) );
-						var text = lang.get('verify.user_verified_reply', username.escapeFormatting());
+						embed.setColor('#00FF00').setDescription( lang.get('verify.user_verified', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) + ( rename ? '\n' + lang.get('verify.user_renamed', queryuser.gender) : '' ) );
+						var text = lang.get('verify.user_verified_reply', username.escapeFormatting(), queryuser.gender);
 						var verify_promise = [
 						var verify_promise = [
 							msg.member.roles.add( roles, lang.get('verify.audit_reason', username) ).catch( error => {
 							msg.member.roles.add( roles, lang.get('verify.audit_reason', username) ).catch( error => {
 								log_error(error);
 								log_error(error);
@@ -256,8 +256,8 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 						} );
 						} );
 					}
 					}
 					
 					
-					embed.setColor('#FFFF00').setDescription( lang.get('verify.user_matches', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')') );
-					msg.replyMsg( lang.get('verify.user_matches_reply', username.escapeFormatting()), {embed}, false, false );
+					embed.setColor('#FFFF00').setDescription( lang.get('verify.user_matches', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) );
+					msg.replyMsg( lang.get('verify.user_matches_reply', username.escapeFormatting(), queryuser.gender), {embed}, false, false );
 					
 					
 					if ( reaction ) reaction.removeEmoji();
 					if ( reaction ) reaction.removeEmoji();
 				}, error => {
 				}, error => {
@@ -292,9 +292,9 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 				if ( discordname.length > 50 ) discordname = discordname.substring(0, 50) + '\u2026';
 				if ( discordname.length > 50 ) discordname = discordname.substring(0, 50) + '\u2026';
 				embed.addField( lang.get('verify.discord'), msg.author.tag.escapeFormatting(), true ).addField( lang.get('verify.wiki'), ( discordname || lang.get('verify.empty') ), true );
 				embed.addField( lang.get('verify.discord'), msg.author.tag.escapeFormatting(), true ).addField( lang.get('verify.wiki'), ( discordname || lang.get('verify.empty') ), true );
 				if ( msg.author.tag.escapeFormatting() !== discordname ) {
 				if ( msg.author.tag.escapeFormatting() !== discordname ) {
-					embed.setColor('#FFFF00').setDescription( lang.get('verify.user_failed', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')') );
-					embed.addField( lang.get('verify.notice'), lang.get('verify.help_subpage', '**`' + msg.author.tag + '`**') + '\n' + wiki.toLink('Special:MyPage/Discord', 'action=edit', '', body.query.general) );
-					msg.replyMsg( lang.get('verify.user_failed_reply', username.escapeFormatting()), {embed}, false, false );
+					embed.setColor('#FFFF00').setDescription( lang.get('verify.user_failed', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) );
+					embed.addField( lang.get('verify.notice'), lang.get('verify.help_subpage', '**`' + msg.author.tag + '`**', queryuser.gender) + '\n' + wiki.toLink('Special:MyPage/Discord', 'action=edit', '', body.query.general) );
+					msg.replyMsg( lang.get('verify.user_failed_reply', username.escapeFormatting(), queryuser.gender), {embed}, false, false );
 					
 					
 					if ( reaction ) reaction.removeEmoji();
 					if ( reaction ) reaction.removeEmoji();
 					return;
 					return;
@@ -329,8 +329,8 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 					}
 					}
 				} );
 				} );
 				if ( verified ) {
 				if ( verified ) {
-					embed.setColor('#00FF00').setDescription( lang.get('verify.user_verified', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')') + ( rename ? '\n' + lang.get('verify.user_renamed') : '' ) );
-					var text = lang.get('verify.user_verified_reply', username.escapeFormatting());
+					embed.setColor('#00FF00').setDescription( lang.get('verify.user_verified', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) + ( rename ? '\n' + lang.get('verify.user_renamed', queryuser.gender) : '' ) );
+					var text = lang.get('verify.user_verified_reply', username.escapeFormatting(), queryuser.gender);
 					var verify_promise = [
 					var verify_promise = [
 						msg.member.roles.add( roles, lang.get('verify.audit_reason', username) ).catch( error => {
 						msg.member.roles.add( roles, lang.get('verify.audit_reason', username) ).catch( error => {
 							log_error(error);
 							log_error(error);
@@ -362,8 +362,8 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 					} );
 					} );
 				}
 				}
 				
 				
-				embed.setColor('#FFFF00').setDescription( lang.get('verify.user_matches', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')') );
-				msg.replyMsg( lang.get('verify.user_matches_reply', username.escapeFormatting()), {embed}, false, false );
+				embed.setColor('#FFFF00').setDescription( lang.get('verify.user_matches', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) );
+				msg.replyMsg( lang.get('verify.user_matches_reply', username.escapeFormatting(), queryuser.gender), {embed}, false, false );
 				
 				
 				if ( reaction ) reaction.removeEmoji();
 				if ( reaction ) reaction.removeEmoji();
 			}, error => {
 			}, error => {

+ 4 - 4
cmds/wiki/fandom/user.js

@@ -240,9 +240,9 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 					for ( var i = 0; i < usergroups.length; i++ ) {
 					for ( var i = 0; i < usergroups.length; i++ ) {
 						if ( groups.includes( usergroups[i] ) && ( group.length === 1 || !['autoconfirmed', 'user'].includes( usergroups[i] ) ) ) {
 						if ( groups.includes( usergroups[i] ) && ( group.length === 1 || !['autoconfirmed', 'user'].includes( usergroups[i] ) ) ) {
 							if ( usergroups[i] === 'wiki-manager' && body.query.allmessages[0]['*'] === username ) {
 							if ( usergroups[i] === 'wiki-manager' && body.query.allmessages[0]['*'] === username ) {
-								group.push('**' + lang.get('user.groups.' + usergroups[i]) + '**');
+								group.push('**' + lang.get('user.groups.' + usergroups[i], queryuser.gender) + '**');
 							}
 							}
-							else group.push(lang.get('user.groups.' + usergroups[i]));
+							else group.push(lang.get('user.groups.' + usergroups[i], queryuser.gender));
 						}
 						}
 					}
 					}
 					var isBlocked = false;
 					var isBlocked = false;
@@ -258,7 +258,7 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 					var blockedby = '[[User:' + queryuser.blockedby + '|' + queryuser.blockedby + ']]';
 					var blockedby = '[[User:' + queryuser.blockedby + '|' + queryuser.blockedby + ']]';
 					var blockreason = queryuser.blockreason;
 					var blockreason = queryuser.blockreason;
 					var block = {
 					var block = {
-						header: lang.get('user.block.header', username).escapeFormatting(),
+						header: lang.get('user.block.header', username, queryuser.gender).escapeFormatting(),
 						text: lang.get('user.block.nofrom' + ( blockreason ? 'text' : 'noreason' ), '', blockexpiry ),
 						text: lang.get('user.block.nofrom' + ( blockreason ? 'text' : 'noreason' ), '', blockexpiry ),
 						by: blockedby,
 						by: blockedby,
 						reason: blockreason
 						reason: blockreason
@@ -331,7 +331,7 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 							if ( msg.channel.type === 'text' && msg.guild.id in patreons ) text += '\n\n<a:loading:641343250661113886> **' + lang.get('user.info.loading') + '**';
 							if ( msg.channel.type === 'text' && msg.guild.id in patreons ) text += '\n\n<a:loading:641343250661113886> **' + lang.get('user.info.loading') + '**';
 						}
 						}
 						
 						
-						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler) );
+						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler, queryuser.gender) );
 						
 						
 						if ( reaction ) reaction.removeEmoji();
 						if ( reaction ) reaction.removeEmoji();
 					} );
 					} );

+ 75 - 56
cmds/wiki/gamepedia/overview.js

@@ -67,6 +67,15 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 			}
 			}
 			
 			
 			if ( wiki.isFandom() ) got.get( 'https://community.fandom.com/api/v1/Wikis/ByString?expand=true&includeDomain=true&limit=10&string=' + body.query.general.servername + body.query.general.scriptpath + '&format=json&cache=' + Date.now() ).then( ovresponse => {
 			if ( wiki.isFandom() ) got.get( 'https://community.fandom.com/api/v1/Wikis/ByString?expand=true&includeDomain=true&limit=10&string=' + body.query.general.servername + body.query.general.scriptpath + '&format=json&cache=' + Date.now() ).then( ovresponse => {
+				var manager = [lang.get('overview.manager'), body.query.allmessages[0]['*']];
+				var crossover = [lang.get('overview.crossover')];
+				if ( body.query.allmessages[1]['*'] ) {
+					crossover.push('<https://' + body.query.allmessages[1]['*'] + '.gamepedia.com/>');
+				}
+				else if ( body.query.allmessages[2]['*'] ) {
+					let merge = body.query.allmessages[2]['*'].split('/');
+					crossover.push('<https://' + merge[0] + '.fandom.com/' + ( merge[1] ? merge[1] + '/' : '' ) + '>');
+				}
 				var ovbody = ovresponse.body;
 				var ovbody = ovresponse.body;
 				if ( ovresponse.statusCode !== 200 || !ovbody || ovbody.exception || !ovbody.items || !ovbody.items.length ) {
 				if ( ovresponse.statusCode !== 200 || !ovbody || ovbody.exception || !ovbody.items || !ovbody.items.length ) {
 					console.log( '- ' + ovresponse.statusCode + ': Error while getting the wiki details: ' + ( ovbody && ovbody.exception && ovbody.exception.details ) );
 					console.log( '- ' + ovresponse.statusCode + ': Error while getting the wiki details: ' + ( ovbody && ovbody.exception && ovbody.exception.details ) );
@@ -80,16 +89,10 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 					var vertical = [lang.get('overview.vertical'), site.hub];
 					var vertical = [lang.get('overview.vertical'), site.hub];
 					var topic = [lang.get('overview.topic'), site.topic];
 					var topic = [lang.get('overview.topic'), site.topic];
 					var founder = [lang.get('overview.founder'), site.founding_user_id];
 					var founder = [lang.get('overview.founder'), site.founding_user_id];
-					var manager = [lang.get('overview.manager'), body.query.allmessages[0]['*']];
-					var crossover = [lang.get('overview.crossover')];
-					if ( body.query.allmessages[1]['*'] ) {
-						crossover.push('<https://' + body.query.allmessages[1]['*'] + '.gamepedia.com/>');
-					}
-					else if ( body.query.allmessages[2]['*'] ) {
-						let merge = body.query.allmessages[2]['*'].split('/');
-						crossover.push('<https://' + merge[0] + '.fandom.com/' + ( merge[1] ? merge[1] + '/' : '' ) + '>');
-					}
 					var created = [lang.get('overview.created'), new Date(site.creation_date).toLocaleString(lang.get('dateformat'), timeoptions)];
 					var created = [lang.get('overview.created'), new Date(site.creation_date).toLocaleString(lang.get('dateformat'), timeoptions)];
+					var posts = [lang.get('overview.posts')];
+					var walls = [lang.get('overview.walls')];
+					var comments = [lang.get('overview.comments')];
 					var description = [lang.get('overview.description'), site.desc];
 					var description = [lang.get('overview.description'), site.desc];
 					var image = [lang.get('overview.image'), site.image];
 					var image = [lang.get('overview.image'), site.image];
 					
 					
@@ -105,26 +108,50 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 					}
 					}
 					else text += vertical.join(' ') + ( topic[1] ? '\n' + topic.join(' ') : '' );
 					else text += vertical.join(' ') + ( topic[1] ? '\n' + topic.join(' ') : '' );
 					
 					
-					if ( founder[1] > 0 ) got.get( wiki + 'api.php?action=query&list=users&usprop=&ususerids=' + founder[1] + '&format=json' ).then( usresponse => {
-						var usbody = usresponse.body;
-						if ( usbody && usbody.warnings ) log_warn(usbody.warnings);
-						if ( usresponse.statusCode !== 200 || !usbody || !usbody.query || !usbody.query.users || !usbody.query.users[0] ) {
-							console.log( '- ' + usresponse.statusCode + ': Error while getting the wiki founder: ' + ( usbody && usbody.error && usbody.error.info ) );
+					Promise.all([
+						( founder[1] > 0 ? got.get( wiki + 'api.php?action=query&list=users&usprop=&ususerids=' + founder[1] + '&format=json' ).then( usresponse => {
+							var usbody = usresponse.body;
+							if ( usbody && usbody.warnings ) log_warn(usbody.warnings);
+							if ( usresponse.statusCode !== 200 || !usbody || !usbody.query || !usbody.query.users || !usbody.query.users[0] ) {
+								console.log( '- ' + usresponse.statusCode + ': Error while getting the wiki founder: ' + ( usbody && usbody.error && usbody.error.info ) );
+								founder[1] = 'ID: ' + founder[1];
+							}
+							else {
+								var user = usbody.query.users[0].name;
+								if ( msg.showEmbed() ) founder[1] = '[' + user + '](' + wiki.toLink('User:' + user, '', '', body.query.general, true) + ')';
+								else founder[1] = user;
+							}
+						}, error => {
+							console.log( '- Error while getting the wiki founder: ' + error );
 							founder[1] = 'ID: ' + founder[1];
 							founder[1] = 'ID: ' + founder[1];
-						}
-						else {
-							var user = usbody.query.users[0].name;
-							if ( msg.showEmbed() ) founder[1] = '[' + user + '](' + wiki.toLink('User:' + user, '', '', body.query.general, true) + ')';
-							else founder[1] = user;
-						}
-					}, error => {
-						console.log( '- Error while getting the wiki founder: ' + error );
-						founder[1] = 'ID: ' + founder[1];
-					} ).finally( () => {
+						} ) : founder[1] = lang.get('overview.none') ),
+						got.get( 'https://services.fandom.com/discussion/' + site.id + '/posts?limit=1&format=json&cache=' + Date.now(), {
+							headers: {
+								Accept: 'application/hal+json'
+							}
+						} ).then( dsresponse => {
+							var dsbody = dsresponse.body;
+							if ( dsresponse.statusCode !== 200 || !dsbody || dsbody.title ) {
+								if ( dsbody?.title !== 'site doesn\'t exists' ) console.log( '- ' + dsresponse.statusCode + ': Error while getting discussions stats: ' + dsbody?.title );
+							}
+							else {
+								let counts = dsbody?._embedded?.count?.[0];
+								if ( counts?.FORUM ) posts.push(counts.FORUM);
+								if ( counts?.WALL ) walls.push(counts.WALL);
+								if ( counts?.ARTICLE_COMMENT ) comments.push(counts.ARTICLE_COMMENT);
+							}
+						}, error => {
+							console.log( '- Error while getting discussions stats: ' + error );
+						} )
+					]).finally( () => {
 						if ( msg.showEmbed() ) {
 						if ( msg.showEmbed() ) {
 							embed.addField( founder[0], founder[1], true );
 							embed.addField( founder[0], founder[1], true );
 							if ( manager[1] ) embed.addField( manager[0], '[' + manager[1] + '](' + wiki.toLink('User:' + manager[1], '', '', body.query.general, true) + ') ([' + lang.get('overview.talk') + '](' + wiki.toLink('User talk:' + manager[1], '', '', body.query.general, true) + '))', true );
 							if ( manager[1] ) embed.addField( manager[0], '[' + manager[1] + '](' + wiki.toLink('User:' + manager[1], '', '', body.query.general, true) + ') ([' + lang.get('overview.talk') + '](' + wiki.toLink('User talk:' + manager[1], '', '', body.query.general, true) + '))', true );
-							embed.addField( created[0], created[1], true ).addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setFooter( lang.get('overview.inaccurate') );
+							embed.addField( created[0], created[1], true ).addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true );
+							if ( posts[1] ) embed.addField( posts[0], posts[1], true );
+							if ( walls[1] ) embed.addField( walls[0], walls[1], true );
+							if ( comments[1] ) embed.addField( comments[0], comments[1], true );
+							embed.addField( users[0], users[1], true ).setFooter( lang.get('overview.inaccurate') + ' • ' + lang.get('overview.wikiid') + ' ' + site.id );
 							if ( crossover[1] ) {
 							if ( crossover[1] ) {
 								var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
 								var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
 								if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
 								if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
@@ -134,7 +161,11 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 							if ( image[1] ) embed.addField( image[0], image[1] ).setImage( image[1] );
 							if ( image[1] ) embed.addField( image[0], image[1] ).setImage( image[1] );
 						}
 						}
 						else {
 						else {
-							text += '\n' + founder.join(' ') + ( manager[1] ? '\n' + manager.join(' ') : '' ) + '\n' + created.join(' ') + '\n' + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ');
+							text += '\n' + founder.join(' ') + ( manager[1] ? '\n' + manager.join(' ') : '' ) + '\n' + created.join(' ') + '\n' + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ');
+							if ( posts[1] ) text += '\n' + posts.join(' ');
+							if ( walls[1] ) text += '\n' + walls.join(' ');
+							if ( comments[1] ) text += '\n' + comments.join(' ');
+							text += '\n' + users.join(' ');
 							if ( crossover[1] ) text += '\n' + crossover.join(' ');
 							if ( crossover[1] ) text += '\n' + crossover.join(' ');
 							if ( description[1] ) text += '\n' + description.join(' ');
 							if ( description[1] ) text += '\n' + description.join(' ');
 							if ( image[1] ) {
 							if ( image[1] ) {
@@ -148,37 +179,21 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 						
 						
 						if ( reaction ) reaction.removeEmoji();
 						if ( reaction ) reaction.removeEmoji();
 					} );
 					} );
-					else {
-						founder[1] = lang.get('overview.none');
-						if ( msg.showEmbed() ) {
-							embed.addField( founder[0], founder[1], true ).addField( created[0], created[1], true ).addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setFooter( lang.get('overview.inaccurate') );
-							if ( crossover[1] ) {
-								var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
-								if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
-								else embed.addField( crossover[0], crossover[1], true );
-							}
-							if ( description[1] ) embed.addField( description[0], description[1] );
-							if ( image[1] ) embed.addField( image[0], image[1] ).setImage( image[1] );
-						}
-						else {
-							text += '\n' + founder.join(' ') + '\n' + created.join(' ') + '\n' + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ');
-							if ( crossover[1] ) text += '\n' + crossover.join(' ');
-							if ( description[1] ) text += '\n' + description.join(' ');
-							if ( image[1] ) {
-								text += '\n' + image.join(' ');
-								if ( msg.uploadFiles() ) embed.files = [image[1]];
-							}
-							text += '\n\n*' + lang.get('overview.inaccurate') + '*';
-						}
-						
-						msg.sendChannel( spoiler + text + spoiler, {embed} );
-						
-						if ( reaction ) reaction.removeEmoji();
-					}
 				}
 				}
 				else {
 				else {
-					if ( msg.showEmbed() ) embed.addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setTimestamp( msg.client.readyTimestamp ).setFooter( lang.get('overview.inaccurate') );
-					else text = articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ') + '\n\n*' + lang.get('overview.inaccurate') + '*';
+					if ( msg.showEmbed() ) {
+						if ( manager[1] ) embed.addField( manager[0], '[' + manager[1] + '](' + wiki.toLink('User:' + manager[1], '', '', body.query.general, true) + ') ([' + lang.get('overview.talk') + '](' + wiki.toLink('User talk:' + manager[1], '', '', body.query.general, true) + '))', true );
+						embed.addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setTimestamp( msg.client.readyTimestamp ).setFooter( lang.get('overview.inaccurate') );
+						if ( crossover[1] ) {
+							var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
+							if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
+							else embed.addField( crossover[0], crossover[1], true );
+						}
+					}
+					else {
+						text = ( manager[1] ? manager.join(' ') + '\n' : '' ) + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ') + '\n\n*' + lang.get('overview.inaccurate') + '*';
+						if ( crossover[1] ) text += '\n' + crossover.join(' ');
+					}
 					
 					
 					msg.sendChannel( spoiler + text + spoiler, {embed} );
 					msg.sendChannel( spoiler + text + spoiler, {embed} );
 					
 					
@@ -186,7 +201,11 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 				}
 				}
 			}, error => {
 			}, error => {
 				console.log( '- Error while getting the wiki details: ' + error );
 				console.log( '- Error while getting the wiki details: ' + error );
-				msg.sendChannelError( spoiler + '<' + wiki.toLink('Special:Statistics', '', '', body.query.general) + '>' + spoiler );
+
+				if ( msg.showEmbed() ) embed.addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setTimestamp( msg.client.readyTimestamp ).setFooter( lang.get('overview.inaccurate') );
+				else text = articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ') + '\n\n*' + lang.get('overview.inaccurate') + '*';
+
+				msg.sendChannelError( spoiler + text + spoiler, {embed} );
 				
 				
 				if ( reaction ) reaction.removeEmoji();
 				if ( reaction ) reaction.removeEmoji();
 			} );
 			} );

+ 7 - 6
cmds/wiki/gamepedia/user.js

@@ -219,6 +219,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 						case 'female':
 						case 'female':
 							gender.push(lang.get('user.gender.female'));
 							gender.push(lang.get('user.gender.female'));
 							break;
 							break;
+						case 'unknown':
 						default: 
 						default: 
 							gender.push(lang.get('user.gender.unknown'));
 							gender.push(lang.get('user.gender.unknown'));
 					}
 					}
@@ -230,10 +231,10 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 						if ( groups.includes( usergroups[i] ) && ( group.length === 1 || !['autoconfirmed', 'user'].includes( usergroups[i] ) ) ) {
 						if ( groups.includes( usergroups[i] ) && ( group.length === 1 || !['autoconfirmed', 'user'].includes( usergroups[i] ) ) ) {
 							var thisSite = allSites.find( site => site.wiki_domain === body.query.general.servername );
 							var thisSite = allSites.find( site => site.wiki_domain === body.query.general.servername );
 							if ( usergroups[i] === 'wiki_manager' && thisSite && thisSite.wiki_managers.includes( username ) ) {
 							if ( usergroups[i] === 'wiki_manager' && thisSite && thisSite.wiki_managers.includes( username ) ) {
-								group.push('**' + lang.get('user.groups.' + usergroups[i]) + '**');
+								group.push('**' + lang.get('user.groups.' + usergroups[i], queryuser.gender) + '**');
 							}
 							}
 							else if ( !groups.includes( 'global_' + usergroups[i] ) || queryuser.groupmemberships.some( member => member.group === usergroups[i] ) ) {
 							else if ( !groups.includes( 'global_' + usergroups[i] ) || queryuser.groupmemberships.some( member => member.group === usergroups[i] ) ) {
-								group.push(lang.get('user.groups.' + usergroups[i]));
+								group.push(lang.get('user.groups.' + usergroups[i], queryuser.gender));
 							}
 							}
 						}
 						}
 					}
 					}
@@ -251,7 +252,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 					var blockedby = queryuser.blockedby;
 					var blockedby = queryuser.blockedby;
 					var blockreason = queryuser.blockreason;
 					var blockreason = queryuser.blockreason;
 					var block = {
 					var block = {
-						header: lang.get('user.block.header', username).escapeFormatting(),
+						header: lang.get('user.block.header', username, queryuser.gender).escapeFormatting(),
 						text: lang.get('user.block.' + ( blockreason ? 'text' : 'noreason' ), blockedtimestamp, blockexpiry),
 						text: lang.get('user.block.' + ( blockreason ? 'text' : 'noreason' ), blockedtimestamp, blockexpiry),
 						by: blockedby,
 						by: blockedby,
 						reason: blockreason
 						reason: blockreason
@@ -321,7 +322,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 							if ( msg.channel.type === 'text' && msg.guild.id in patreons ) text += '\n\n<a:loading:641343250661113886> **' + lang.get('user.info.loading') + '**';
 							if ( msg.channel.type === 'text' && msg.guild.id in patreons ) text += '\n\n<a:loading:641343250661113886> **' + lang.get('user.info.loading') + '**';
 						}
 						}
 						
 						
-						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler) );
+						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler, queryuser.gender) );
 						
 						
 						if ( reaction ) reaction.removeEmoji();
 						if ( reaction ) reaction.removeEmoji();
 					} );
 					} );
@@ -382,7 +383,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 							if ( msg.channel.type === 'text' && msg.guild.id in patreons ) text += '\n\n<a:loading:641343250661113886> **' + lang.get('user.info.loading') + '**';
 							if ( msg.channel.type === 'text' && msg.guild.id in patreons ) text += '\n\n<a:loading:641343250661113886> **' + lang.get('user.info.loading') + '**';
 						}
 						}
 						
 						
-						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler) );
+						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler, queryuser.gender) );
 						
 						
 						if ( reaction ) reaction.removeEmoji();
 						if ( reaction ) reaction.removeEmoji();
 					} );
 					} );
@@ -400,7 +401,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 							}
 							}
 						}
 						}
 						
 						
-						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler) );
+						msg.sendChannel( spoiler + text + spoiler, {embed} ).then( message => global_block(lang, message, username, text, embed, wiki, spoiler, queryuser.gender) );
 						
 						
 						if ( reaction ) reaction.removeEmoji();
 						if ( reaction ) reaction.removeEmoji();
 					}
 					}

+ 11 - 10
functions/global_block.js

@@ -10,8 +10,9 @@ const {timeoptions} = require('../util/default.json');
  * @param {import('discord.js').MessageEmbed} embed - The embed for the page.
  * @param {import('discord.js').MessageEmbed} embed - The embed for the page.
  * @param {String} wiki - The wiki for the page.
  * @param {String} wiki - The wiki for the page.
  * @param {String} spoiler - If the response is in a spoiler.
  * @param {String} spoiler - If the response is in a spoiler.
+ * @param {String} [gender] - The gender of the user.
  */
  */
-function global_block(lang, msg, username, text, embed, wiki, spoiler) {
+function global_block(lang, msg, username, text, embed, wiki, spoiler, gender = 'unknown') {
 	if ( !msg || msg.channel.type !== 'text' || !( msg.guild.id in patreons ) ) return;
 	if ( !msg || msg.channel.type !== 'text' || !( msg.guild.id in patreons ) ) return;
 	
 	
 	if ( msg.showEmbed() ) embed.fields.pop();
 	if ( msg.showEmbed() ) embed.fields.pop();
@@ -31,12 +32,12 @@ function global_block(lang, msg, username, text, embed, wiki, spoiler) {
 		else {
 		else {
 			let $ = cheerio.load(body);
 			let $ = cheerio.load(body);
 			if ( $('#mw-content-text .errorbox').length ) {
 			if ( $('#mw-content-text .errorbox').length ) {
-				if ( msg.showEmbed() ) embed.addField( lang.get('user.gblock.disabled'), '\u200b' );
-				else text += '\n\n**' + lang.get('user.gblock.disabled') + '**';
+				if ( msg.showEmbed() ) embed.addField( lang.get('user.gblock.disabled', gender), '\u200b' );
+				else text += '\n\n**' + lang.get('user.gblock.disabled', gender) + '**';
 			}
 			}
 			else if ( $('.mw-warning-with-logexcerpt').length && !$(".mw-warning-with-logexcerpt .mw-logline-block").length ) {
 			else if ( $('.mw-warning-with-logexcerpt').length && !$(".mw-warning-with-logexcerpt .mw-logline-block").length ) {
-				if ( msg.showEmbed() ) embed.addField( lang.get('user.gblock.header', username).escapeFormatting(), '\u200b' );
-				else text += '\n\n**' + lang.get('user.gblock.header', username).escapeFormatting() + '**';
+				if ( msg.showEmbed() ) embed.addField( lang.get('user.gblock.header', username, gender).escapeFormatting(), '\u200b' );
+				else text += '\n\n**' + lang.get('user.gblock.header', username, gender).escapeFormatting() + '**';
 			}
 			}
 		}
 		}
 	}, error => {
 	}, error => {
@@ -89,8 +90,8 @@ function global_block(lang, msg, username, text, embed, wiki, spoiler) {
 				if ( expiry.startsWith( '(infiniteblock)' ) ) expiry = lang.get('user.block.until_infinity');
 				if ( expiry.startsWith( '(infiniteblock)' ) ) expiry = lang.get('user.block.until_infinity');
 				else expiry = new Date(expiry.replace( /(\d{2}:\d{2}), (\d{1,2}) \((\w+)\) (\d{4})/, '$3 $2, $4 $1 UTC' )).toLocaleString(lang.get('dateformat'), timeoptions);
 				else expiry = new Date(expiry.replace( /(\d{2}:\d{2}), (\d{1,2}) \((\w+)\) (\d{4})/, '$3 $2, $4 $1 UTC' )).toLocaleString(lang.get('dateformat'), timeoptions);
 				if ( msg.showEmbed() ) {
 				if ( msg.showEmbed() ) {
-					var gblocktitle = lang.get('user.gblock.header', username).escapeFormatting();
-					var globalblock = embed.fields.find( field => field.inline === false && field.name === lang.get('user.block.header', username).escapeFormatting() && field.value.replace( /\[([^\]]*)\]\([^\)]*\)/g, '$1' ) === lang.get('user.block.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason.slice(4).join(', ').escapeFormatting()) );
+					var gblocktitle = lang.get('user.gblock.header', username, gender).escapeFormatting();
+					var globalblock = embed.fields.find( field => field.inline === false && field.name === lang.get('user.block.header', username, gender).escapeFormatting() && field.value.replace( /\[([^\]]*)\]\([^\)]*\)/g, '$1' ) === lang.get('user.block.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason.slice(4).join(', ').escapeFormatting()) );
 					if ( globalblock ) globalblock.name = gblocktitle;
 					if ( globalblock ) globalblock.name = gblocktitle;
 					else {
 					else {
 						var block_wiki = reason[3].replace( /Special:BlockList$/, '' );
 						var block_wiki = reason[3].replace( /Special:BlockList$/, '' );
@@ -99,9 +100,9 @@ function global_block(lang, msg, username, text, embed, wiki, spoiler) {
 					}
 					}
 				}
 				}
 				else {
 				else {
-					var globalblock = splittext.indexOf('**' + lang.get('user.block.header', username).escapeFormatting() + '**\n' + lang.get('user.block.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason.slice(4).join(', ').escapeFormatting()));
-					if ( globalblock !== -1 ) splittext[globalblock] = '**' + lang.get('user.gblock.header', username).escapeFormatting() + '**\n' + lang.get('user.block.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason.slice(4).join(', ').escapeFormatting());
-					else splittext.push('**' + lang.get('user.gblock.header', username).escapeFormatting() + '**\n' + lang.get('user.gblock.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason[2], reason.slice(4).join(', ').escapeFormatting()));
+					var globalblock = splittext.indexOf('**' + lang.get('user.block.header', username, gender).escapeFormatting() + '**\n' + lang.get('user.block.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason.slice(4).join(', ').escapeFormatting()));
+					if ( globalblock !== -1 ) splittext[globalblock] = '**' + lang.get('user.gblock.header', username, gender).escapeFormatting() + '**\n' + lang.get('user.block.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason.slice(4).join(', ').escapeFormatting());
+					else splittext.push('**' + lang.get('user.gblock.header', username, gender).escapeFormatting() + '**\n' + lang.get('user.gblock.' + ( reason.length > 4 ? 'text' : 'noreason' ), timestamp, expiry, reason[1].escapeFormatting(), reason[2], reason.slice(4).join(', ').escapeFormatting()));
 				}
 				}
 			} );
 			} );
 			text = splittext.join('\n\n');
 			text = splittext.join('\n\n');

+ 65 - 65
i18n/en.json

@@ -588,7 +588,7 @@
     },
     },
     "user": {
     "user": {
         "block": {
         "block": {
-            "header": "$1 is currently blocked!",
+            "header": "$1 is currently {{GENDER:$2|blocked}}!",
             "nofromnoreason": "Blocked until $2 by $3.",
             "nofromnoreason": "Blocked until $2 by $3.",
             "nofromtext": "Blocked until $2 by $3 with reason \"$4\".",
             "nofromtext": "Blocked until $2 by $3 with reason \"$4\".",
             "noreason": "Blocked on $1 until $2 by $3.",
             "noreason": "Blocked on $1 until $2 by $3.",
@@ -596,8 +596,8 @@
             "until_infinity": "the end of all days"
             "until_infinity": "the end of all days"
         },
         },
         "gblock": {
         "gblock": {
-            "disabled": "This account is currently disabled!",
-            "header": "$1 is currently globally blocked!",
+            "disabled": "This account is currently {{GENDER:$1|disabled}}!",
+            "header": "$1 is currently globally {{GENDER:$2|blocked}}!",
             "noreason": "Blocked on $1 until $2 by $3 on $4.",
             "noreason": "Blocked on $1 until $2 by $3 on $4.",
             "text": "Blocked on $1 until $2 by $3 on $4 with reason \"$5\"."
             "text": "Blocked on $1 until $2 by $3 on $4 with reason \"$5\"."
         },
         },
@@ -607,53 +607,53 @@
             "unknown": "Unknown"
             "unknown": "Unknown"
         },
         },
         "groups": {
         "groups": {
-            "Elite_users": "Elite user",
-            "Patrol": "Inspector",
-            "assistant": "Assistant",
-            "authenticated": "authenticated",
-            "autoconfirmed": "Autoconfirmed user",
-            "autopatrol": "autopatrol",
-            "autopatroller": "Auto patroller",
-            "autoreview": "autoreview",
-            "blogpatrol": "Blog patroller",
-            "bot": "Bot",
-            "bot-global": "Global bot",
-            "bureaucrat": "Bureaucrat",
-            "chatmoderator": "Chat moderator",
-            "checkuser": "Check user",
-            "codeeditor": "Code editor",
-            "commentcontrol": "Comment controller",
-            "content-moderator": "Content moderator",
-            "content-team-member": "Content Team Member",
-            "content-volunteer": "Content volunteer",
-            "content_team_member": "Content Team Member",
-            "custodian": "Custodian",
-            "directors": "Director",
-            "doyen": "Dean",
-            "editor": "Editor",
-            "global-discussions-moderator": "Global discussions moderator",
-            "global_bot": "Global bot",
-            "grasp": "GRASP",
-            "helper": "Fandom helper",
-            "hydra_staff": "Gamepedia staff",
-            "imagecontrol": "Image controller",
-            "interface-admin": "Interface administrator",
-            "junioradmin": "Junior administrator",
-            "moderator": "Moderator",
-            "patroller": "Patroller",
-            "patrollers": "Patroller",
-            "rollback": "rollback",
-            "soap": "SOAP",
-            "staff": "Fandom staff",
-            "supmoderator": "Senior moderator",
-            "sysop": "Administrator",
-            "threadmoderator": "Discussions moderator",
-            "user": "User",
-            "vanguard": "Vanguard",
-            "voldev": "Volunteer Developer",
-            "widgeteditor": "Widget editor",
-            "wiki-manager": "Wiki manager",
-            "wiki_manager": "Wiki manager"
+            "Elite_users": "{{GENDER:$1|Elite user}}",
+            "Patrol": "{{GENDER:$1|{{GENDER:$1|Inspector}}}}",
+            "assistant": "{{GENDER:$1|Assistant}}",
+            "authenticated": "{{GENDER:$1|authenticated}}",
+            "autoconfirmed": "{{GENDER:$1|Autoconfirmed user}}",
+            "autopatrol": "{{GENDER:$1|autopatrol}}",
+            "autopatroller": "{{GENDER:$1|Auto patroller}}",
+            "autoreview": "{{GENDER:$1|autoreview}}",
+            "blogpatrol": "{{GENDER:$1|Blog patroller}}",
+            "bot": "{{GENDER:$1|Bot}}",
+            "bot-global": "{{GENDER:$1|Global bot}}",
+            "bureaucrat": "{{GENDER:$1|Bureaucrat}}",
+            "chatmoderator": "{{GENDER:$1|Chat moderator}}",
+            "checkuser": "{{GENDER:$1|Check user}}",
+            "codeeditor": "{{GENDER:$1|Code editor}}",
+            "commentcontrol": "{{GENDER:$1|Comment controller}}",
+            "content-moderator": "{{GENDER:$1|Content moderator}}",
+            "content-team-member": "{{GENDER:$1|Content Team Member}}",
+            "content-volunteer": "{{GENDER:$1|Content volunteer}}",
+            "content_team_member": "{{GENDER:$1|Content Team Member}}",
+            "custodian": "{{GENDER:$1|Custodian}}",
+            "directors": "{{GENDER:$1|Director}}",
+            "doyen": "{{GENDER:$1|Dean}}",
+            "editor": "{{GENDER:$1|Editor}}",
+            "global-discussions-moderator": "{{GENDER:$1|Global discussions moderator}}",
+            "global_bot": "{{GENDER:$1|Global bot}}",
+            "grasp": "{{GENDER:$1|GRASP}}",
+            "helper": "{{GENDER:$1|Fandom helper}}",
+            "hydra_staff": "{{GENDER:$1|Gamepedia staff}}",
+            "imagecontrol": "{{GENDER:$1|Image controller}}",
+            "interface-admin": "{{GENDER:$1|Interface administrator}}",
+            "junioradmin": "{{GENDER:$1|Junior administrator}}",
+            "moderator": "{{GENDER:$1|Moderator}}",
+            "patroller": "{{GENDER:$1|Patroller}}",
+            "patrollers": "{{GENDER:$1|Patroller}}",
+            "rollback": "{{GENDER:$1|rollback}}",
+            "soap": "{{GENDER:$1|SOAP}}",
+            "staff": "{{GENDER:$1|Fandom staff}}",
+            "supmoderator": "{{GENDER:$1|Senior moderator}}",
+            "sysop": "{{GENDER:$1|Administrator}}",
+            "threadmoderator": "{{GENDER:$1|Discussions moderator}}",
+            "user": "{{GENDER:$1|User}}",
+            "vanguard": "{{GENDER:$1|Vanguard}}",
+            "voldev": "{{GENDER:$1|Volunteer Developer}}",
+            "widgeteditor": "{{GENDER:$1|Widget editor}}",
+            "wiki-manager": "{{GENDER:$1|Wiki manager}}",
+            "wiki_manager": "{{GENDER:$1|Wiki manager}}"
         },
         },
         "info": {
         "info": {
             "discord": "Discord:",
             "discord": "Discord:",
@@ -719,27 +719,27 @@
         "footer": "Wiki Account Verification",
         "footer": "Wiki Account Verification",
         "help_fandom": "https://community.fandom.com/wiki/Special:VerifyUser",
         "help_fandom": "https://community.fandom.com/wiki/Special:VerifyUser",
         "help_gamepedia": "https://help.gamepedia.com/Gamepedia_Help_Wiki:Discord_verification",
         "help_gamepedia": "https://help.gamepedia.com/Gamepedia_Help_Wiki:Discord_verification",
-        "help_guide": "Follow [this guide]($1) to add your Discord tag to your wiki profile:",
-        "help_subpage": "Please add your Discord tag ($1) to your Discord subpage on the wiki:",
+        "help_guide": "Follow [this guide]($1) to {{GENDER:$2|add}} your Discord tag to your wiki profile:",
+        "help_subpage": "Please {{GENDER:$2|add}} your Discord tag ($1) to your Discord subpage on the wiki:",
         "missing": "there are no verifications set up for this channel.",
         "missing": "there are no verifications set up for this channel.",
         "notice": "Notice:",
         "notice": "Notice:",
         "qualified": "Qualified for:",
         "qualified": "Qualified for:",
         "qualified_error": "Qualified for, but can't add:",
         "qualified_error": "Qualified for, but can't add:",
-        "user_blocked": "**The wiki user $1 is blocked!**",
-        "user_blocked_reply": "your linked wiki user **\"$1\" is blocked!**",
-        "user_disabled": "**The wiki user $1 is disabled!**",
-        "user_disabled_reply": "your linked wiki user **\"$1\" is disabled!**",
-        "user_failed": "Discord user $1 doesn't match the wiki user $2.",
-        "user_failed_reply": "your Discord tag doesn't match the wiki user \"$1\".",
-        "user_gblocked": "**The wiki user $1 is globally blocked!**",
-        "user_gblocked_reply": "your linked wiki user **\"$1\" is globally blocked!**",
-        "user_matches": "Discord user $1 matches the wiki user $2, but doesn't meet the requirements for any roles.",
-        "user_matches_reply": "your Discord tag matches the wiki user \"$1\", but you don't meet the requirements for any roles.",
+        "user_blocked": "**The wiki user $1 is {{GENDER:$2|blocked}}!**",
+        "user_blocked_reply": "your linked wiki user **\"$1\" is {{GENDER:$2|blocked}}!**",
+        "user_disabled": "**The wiki user $1 is {{GENDER:$2|disabled}}!**",
+        "user_disabled_reply": "your linked wiki user **\"$1\" is {{GENDER:$2|disabled}}!**",
+        "user_failed": "Discord user $1 doesn't {{GENDER:$3|match}} the wiki user $2.",
+        "user_failed_reply": "your Discord tag doesn't {{GENDER:$3|match}} the wiki user \"$1\".",
+        "user_gblocked": "**The wiki user $1 is globally {{GENDER:$2|blocked}}!**",
+        "user_gblocked_reply": "your linked wiki user **\"$1\" is globally {{GENDER:$2|blocked}}!**",
+        "user_matches": "Discord user $1 {{GENDER:$3|matches}} the wiki user $2, but doesn't {{GENDER:$3|meet}} the requirements for any roles.",
+        "user_matches_reply": "your Discord tag {{GENDER:$2|matches}} the wiki user \"$1\", but you don't {{GENDER:$2|meet}} the requirements for any roles.",
         "user_missing": "The wiki user \"$1\" doesn't exist.",
         "user_missing": "The wiki user \"$1\" doesn't exist.",
         "user_missing_reply": "your linked wiki user \"$1\" doesn't exist.",
         "user_missing_reply": "your linked wiki user \"$1\" doesn't exist.",
-        "user_renamed": "Their Discord nickname has been changed to their wiki username.",
-        "user_verified": "Discord user $1 has been successfully verified as wiki user $2.",
-        "user_verified_reply": "you have been successfully verified as wiki user \"$1\".",
+        "user_renamed": "Their Discord nickname has been {{GENDER:$1|changed}} to their wiki username.",
+        "user_verified": "Discord user $1 has been successfully {{GENDER:$3|verified}} as wiki user $2.",
+        "user_verified_reply": "you have been successfully {{GENDER:$2|verified}} as wiki user \"$1\".",
         "wiki": "Wiki user:"
         "wiki": "Wiki user:"
     },
     },
     "voice": {
     "voice": {

+ 1 - 1
util/default.json

@@ -18,7 +18,7 @@
 		},
 		},
 		"rcgcdw": {
 		"rcgcdw": {
 			"default": 1,
 			"default": 1,
-			"patreon": 3,
+			"patreon": 5,
 			"display": 2
 			"display": 2
 		}
 		}
 	},
 	},

+ 29 - 3
util/i18n.js

@@ -74,7 +74,9 @@ class Lang {
 			args.forEach( (arg, i) => {
 			args.forEach( (arg, i) => {
 				text = text.replaceSave( new RegExp( `\\$${i + 1}`, 'g' ), arg );
 				text = text.replaceSave( new RegExp( `\\$${i + 1}`, 'g' ), arg );
 			} );
 			} );
-			text = text.replace( /{{\s*PLURAL:\s*[+-]?(\d+)\s*\|\s*([^\{\}]*?)\s*}}/g, (m, number, cases) => {
+			text = text.replace( /{{\s*GENDER:\s*([a-z]+)\s*\|\s*([^\{\}]*?)\s*}}/g, (m, type, cases) => {
+				return gender(type, cases.split(/\s*\|\s*/));
+			} ).replace( /{{\s*PLURAL:\s*[+-]?(\d+)\s*\|\s*([^\{\}]*?)\s*}}/g, (m, number, cases) => {
 				return plural(lang, parseInt(number, 10), cases.split(/\s*\|\s*/));
 				return plural(lang, parseInt(number, 10), cases.split(/\s*\|\s*/));
 			} );
 			} );
 		}
 		}
@@ -104,7 +106,9 @@ class Lang {
 //			args.forEach( (arg, i) => {
 //			args.forEach( (arg, i) => {
 //				text = text.replaceSave( new RegExp( `\\$${i + 1}`, 'g' ), arg );
 //				text = text.replaceSave( new RegExp( `\\$${i + 1}`, 'g' ), arg );
 //			} );
 //			} );
-//			text = text.replace( /{{\s*PLURAL:\s*[+-]?(\d+)\s*\|\s*([^\{\}]*?)\s*}}/g, (m, number, cases) => {
+//			text = text.replace( /{{\s*GENDER:\s*([a-z]+)\s*\|\s*([^\{\}]*?)\s*}}/g, (m, type, cases) => {
+//				return gender(type, cases.split(/\s*\|\s*/));
+//			} ).replace( /{{\s*PLURAL:\s*[+-]?(\d+)\s*\|\s*([^\{\}]*?)\s*}}/g, (m, number, cases) => {
 //				return plural(lang, parseInt(number, 10), cases.split(/\s*\|\s*/));
 //				return plural(lang, parseInt(number, 10), cases.split(/\s*\|\s*/));
 //			} );
 //			} );
 //		}
 //		}
@@ -162,7 +166,7 @@ function plural(lang, number, args) {
 		case 'en':
 		case 'en':
 		case 'es':
 		case 'es':
 		case 'nl':
 		case 'nl':
-		case 'pt':
+		case 'pt-br':
 		case 'tr':
 		case 'tr':
 		case 'ja':
 		case 'ja':
 		case 'zh-hans':
 		case 'zh-hans':
@@ -184,4 +188,26 @@ function getArg(args, index) {
 	return ( args.length > index ? args[index] : args[args.length - 1] );
 	return ( args.length > index ? args[index] : args[args.length - 1] );
 }
 }
 
 
+/**
+ * Parse gender text.
+ * @param {String} gender - The gender.
+ * @param {String[]} args - The possible text.
+ * @returns {String}
+ */
+function gender(gender, args) {
+	var text = args[0];
+	switch ( gender ) {
+		case 'male':
+			if ( args.length > 0 ) text = args[0];
+			break;
+		case 'female':
+			if ( args.length > 1 ) text = args[1];
+			break;
+		case 'unknown':
+		default:
+			if ( args.length > 2 ) text = args[2];
+	}
+	return text;
+}
+
 module.exports = Lang;
 module.exports = Lang;

+ 6 - 4
util/newMessage.js

@@ -48,8 +48,10 @@ function newMessage(msg, lang, wiki = defaultSettings.wiki, prefix = process.env
 	}
 	}
 	var count = 0;
 	var count = 0;
 	var maxcount = commandLimit[( msg?.guild?.id in patreons ? 'patreon' : 'default' )];
 	var maxcount = commandLimit[( msg?.guild?.id in patreons ? 'patreon' : 'default' )];
-	cleanCont.replace( /\u200b/g, '' ).split('\n').forEach( line => {
-		if ( !line.hasPrefix(prefix) || count > maxcount ) return;
+	var breakLines = false;
+	cleanCont.replace( /\u200b/g, '' ).replace( /(?<!\\)```.+?```/gs, '<codeblock>' ).split('\n').forEach( line => {
+		if ( line.startsWith( '>>> ' ) ) breakLines = true;
+		if ( !line.hasPrefix(prefix) || breakLines || count > maxcount ) return;
 		count++;
 		count++;
 		if ( count === maxcount ) {
 		if ( count === maxcount ) {
 			console.log( '- Message contains too many commands!' );
 			console.log( '- Message contains too many commands!' );
@@ -101,8 +103,8 @@ function newMessage(msg, lang, wiki = defaultSettings.wiki, prefix = process.env
 		var linkcount = 0;
 		var linkcount = 0;
 		var linkmaxcount = maxcount + 5;
 		var linkmaxcount = maxcount + 5;
 		var breakInline = false;
 		var breakInline = false;
-		msg.cleanContent.replace( /\u200b/g, '' ).replace( /(?<!\\)```.+?```/gs, '<codeblock>' ).replace( /(?<!\\)`.+?`/gs, '<code>' ).split('\n').forEach( line => {
-			if ( line.startsWith( '>>> ' ) ) breakinline = true;
+		cleanCont.replace( /\u200b/g, '' ).replace( /(?<!\\)```.+?```/gs, '<codeblock>' ).replace( /(?<!\\)`.+?`/gs, '<code>' ).split('\n').forEach( line => {
+			if ( line.startsWith( '>>> ' ) ) breakInline = true;
 			if ( line.startsWith( '> ' ) || breakInline ) return;
 			if ( line.startsWith( '> ' ) || breakInline ) return;
 			if ( line.hasPrefix(prefix) || !( line.includes( '[[' ) || line.includes( '{{' ) ) ) return;
 			if ( line.hasPrefix(prefix) || !( line.includes( '[[' ) || line.includes( '{{' ) ) ) return;
 			if ( line.includes( '[[' ) && line.includes( ']]' ) && linkcount <= linkmaxcount ) {
 			if ( line.includes( '[[' ) && line.includes( ']]' ) && linkcount <= linkmaxcount ) {