Browse Source

Fix race condition

Markus-Rost 4 years ago
parent
commit
600679dbcc
3 changed files with 82 additions and 63 deletions
  1. 1 0
      bot.js
  2. 9 0
      dashboard/src/index.js
  3. 72 63
      functions/verify.js

+ 1 - 0
bot.js

@@ -232,6 +232,7 @@ fs.readdir( './interactions', (error, files) => {
 client.ws.on( 'INTERACTION_CREATE', interaction => {
 	if ( interaction.version !== 1 ) return;
 	interaction.client = client;
+	/** @type {Discord.TextChannel} */
 	var channel = client.channels.cache.get(interaction.channel_id);
 	if ( interaction.guild_id ) {
 		interaction.user = interaction.member.user;

+ 9 - 0
dashboard/src/index.js

@@ -345,7 +345,16 @@ if ( avatar ) {
 			fetch( avatar.value, {
 				method: 'HEAD',
 				referrer: ''
+			} ).catch( function(error) {
+				if ( avatar.value.startsWith( 'https://cdn.discordapp.com/attachments/' ) && error.name === 'TypeError' ) {
+					return fetch( avatar.value.replace( 'https://cdn.discordapp.com/attachments/', 'https://media.discordapp.net/attachments/' ), {
+						method: 'HEAD',
+						referrer: ''
+					} );
+				}
+				throw error;
 			} ).then( function(response) {
+				avatar.value = response.url;
 				if ( !validContentTypes.includes( response.headers.get('content-type') ) ) {
 					var invalidContentType = lang('avatar.content_type').replace( /\$1/g, response.headers.get('content-type') );
 					avatar.setCustomValidity(invalidContentType + '\n' + validContentTypes.join(', ') );

+ 72 - 63
functions/verify.js

@@ -200,7 +200,9 @@ function verify(lang, channel, member, username, wiki, rows, old_username = '')
 					queryuser.editcount = body.query.usercontribs.length;
 					if ( body.continue?.uccontinue ) queryuser.editcount++;
 				}
+				/** @type {[Set<String>,Set<String>]} */
 				var addRoles = [new Set(), new Set()];
+				/** @type {[Set<String>,Set<String>]} */
 				var removeRoles = [new Set(), new Set()];
 				var verified = false;
 				var rename = false;
@@ -234,35 +236,36 @@ function verify(lang, channel, member, username, wiki, rows, old_username = '')
 				if ( verified ) {
 					embed.setColor('#00FF00').setDescription( lang.get('verify.user_verified', member.toString(), '[' + escapeFormatting(username) + '](' + pagelink + ')', queryuser.gender) + ( rename ? '\n' + lang.get('verify.user_renamed', queryuser.gender) : '' ) );
 					var text = lang.get('verify.user_verified_reply', escapeFormatting(username), queryuser.gender);
+					/** @type {Promise[]} */
+					var verifyPromise = [];
+					var editMember = {};
+					if ( rename && member.displayName !== username.substring(0, 32) ) {
+						if ( channel.guild.me.roles.highest.comparePositionTo(member.roles.highest) > 0 ) editMember.nick = username.substring(0, 32);
+						else comment.push(lang.get('verify.failed_rename', queryuser.gender));
+					}
 					removeRoles[0].forEach( role => addRoles[0].delete(role) );
 					removeRoles[1].forEach( role => addRoles[1].delete(role) );
-					var changeRoles = [];
-					if ( addRoles[0].size + removeRoles[0].size === 1 ) {
-						if ( addRoles[0].size === 1 ) changeRoles.push('add', [...addRoles[0]][0]);
-						else changeRoles.push('remove', [...removeRoles[0]][0]);
+					if ( !editMember.nick && addRoles[0].size + removeRoles[0].size <= 1 ) {
+						if ( removeRoles[0].size === 1 ) verifyPromise.push(member.roles.remove( [...removeRoles[0]][0], lang.get('verify.audit_reason', username) ).catch( error => {
+							log_error(error);
+							comment.push(lang.get('verify.failed_roles'));
+						} ));
+						else if ( addRoles[0].size === 1 ) verifyPromise.push(member.roles.add( [...addRoles[0]][0], lang.get('verify.audit_reason', username) ).catch( error => {
+							log_error(error);
+							comment.push(lang.get('verify.failed_roles'));
+						} ));
 					}
 					else {
-						let roles = new Set([...member.roles.cache.filter( role => {
+						if ( addRoles[0].size + removeRoles[0].size ) editMember.roles = [...new Set([...member.roles.cache.filter( role => {
 							return !removeRoles[0].has(role.id);
-						} ).keys(), ...addRoles[0]]);
-						changeRoles.push('set', [...roles]);
-					}
-					var verify_promise = [
-						member.roles[changeRoles[0]]( changeRoles[1], lang.get('verify.audit_reason', username) ).catch( error => {
+						} ).keys(), ...addRoles[0]])];
+						verifyPromise.push(member.edit( editMember, lang.get('verify.audit_reason', username) ).catch( error => {
 							log_error(error);
 							comment.push(lang.get('verify.failed_roles'));
-						} )
-					];
-					if ( rename && member.displayName !== username ) {
-						if ( channel.guild.me.roles.highest.comparePositionTo(member.roles.highest) > 0 ) {
-							verify_promise.push(member.setNickname( username.substring(0, 32), lang.get('verify.audit_reason', username) ).catch( error => {
-								log_error(error);
-								comment.push(lang.get('verify.failed_rename', queryuser.gender));
-							} ));
-						}
-						else comment.push(lang.get('verify.failed_rename', queryuser.gender));
+							if ( editMember.nick ) comment.push(lang.get('verify.failed_rename', queryuser.gender));
+						} ));
 					}
-					return Promise.all(verify_promise).then( () => {
+					return Promise.all(verifyPromise).then( () => {
 						var addRolesMentions = [
 							[...addRoles[0]].map( role => '<@&' + role + '>' ),
 							[...addRoles[1]].map( role => '<@&' + role + '>' )
@@ -432,7 +435,9 @@ function verify(lang, channel, member, username, wiki, rows, old_username = '')
 				return;
 			}
 			
+			/** @type {[Set<String>,Set<String>]} */
 			var addRoles = [new Set(), new Set()];
+			/** @type {[Set<String>,Set<String>]} */
 			var removeRoles = [new Set(), new Set()];
 			var verified = false;
 			var rename = false;
@@ -462,35 +467,36 @@ function verify(lang, channel, member, username, wiki, rows, old_username = '')
 			if ( verified ) {
 				embed.setColor('#00FF00').setDescription( lang.get('verify.user_verified', member.toString(), '[' + escapeFormatting(username) + '](' + pagelink + ')', queryuser.gender) + ( rename ? '\n' + lang.get('verify.user_renamed', queryuser.gender) : '' ) );
 				var text = lang.get('verify.user_verified_reply', escapeFormatting(username), queryuser.gender);
+				/** @type {Promise[]} */
+				var verifyPromise = [];
+				var editMember = {};
+				if ( rename && member.displayName !== username.substring(0, 32) ) {
+					if ( channel.guild.me.roles.highest.comparePositionTo(member.roles.highest) > 0 ) editMember.nick = username.substring(0, 32);
+					else comment.push(lang.get('verify.failed_rename', queryuser.gender));
+				}
 				removeRoles[0].forEach( role => addRoles[0].delete(role) );
 				removeRoles[1].forEach( role => addRoles[1].delete(role) );
-				var changeRoles = [];
-				if ( addRoles[0].size + removeRoles[0].size === 1 ) {
-					if ( addRoles[0].size === 1 ) changeRoles.push('add', [...addRoles[0]][0]);
-					else changeRoles.push('remove', [...removeRoles[0]][0]);
+				if ( !editMember.nick && addRoles[0].size + removeRoles[0].size <= 1 ) {
+					if ( removeRoles[0].size === 1 ) verifyPromise.push(member.roles.remove( [...removeRoles[0]][0], lang.get('verify.audit_reason', username) ).catch( error => {
+						log_error(error);
+						comment.push(lang.get('verify.failed_roles'));
+					} ));
+					else if ( addRoles[0].size === 1 ) verifyPromise.push(member.roles.add( [...addRoles[0]][0], lang.get('verify.audit_reason', username) ).catch( error => {
+						log_error(error);
+						comment.push(lang.get('verify.failed_roles'));
+					} ));
 				}
 				else {
-					let roles = new Set([...member.roles.cache.filter( role => {
+					if ( addRoles[0].size + removeRoles[0].size ) editMember.roles = [...new Set([...member.roles.cache.filter( role => {
 						return !removeRoles[0].has(role.id);
-					} ).keys(), ...addRoles[0]]);
-					changeRoles.push('set', [...roles]);
-				}
-				var verify_promise = [
-					member.roles[changeRoles[0]]( changeRoles[1], lang.get('verify.audit_reason', username) ).catch( error => {
+					} ).keys(), ...addRoles[0]])];
+					verifyPromise.push(member.edit( editMember, lang.get('verify.audit_reason', username) ).catch( error => {
 						log_error(error);
 						comment.push(lang.get('verify.failed_roles'));
-					} )
-				];
-				if ( rename && member.displayName !== username ) {
-					if ( channel.guild.me.roles.highest.comparePositionTo(member.roles.highest) > 0 ) {
-						verify_promise.push(member.setNickname( username.substring(0, 32), lang.get('verify.audit_reason', username) ).catch( error => {
-							log_error(error);
-							comment.push(lang.get('verify.failed_rename', queryuser.gender));
-						} ));
-					}
-					else comment.push(lang.get('verify.failed_rename', queryuser.gender));
+						if ( editMember.nick ) comment.push(lang.get('verify.failed_rename', queryuser.gender));
+					} ));
 				}
-				return Promise.all(verify_promise).then( () => {
+				return Promise.all(verifyPromise).then( () => {
 					var addRolesMentions = [
 						[...addRoles[0]].map( role => '<@&' + role + '>' ),
 						[...addRoles[1]].map( role => '<@&' + role + '>' )
@@ -703,7 +709,9 @@ global.verifyOauthUser = function(state, access_token, settings) {
 			}
 			queryuser.groups.push(...body.query.globaluserinfo.groups);
 
+			/** @type {[Set<String>,Set<String>]} */
 			var addRoles = [new Set(), new Set()];
+			/** @type {[Set<String>,Set<String>]} */
 			var removeRoles = [new Set(), new Set()];
 			var verified = false;
 			var rename = false;
@@ -734,35 +742,36 @@ global.verifyOauthUser = function(state, access_token, settings) {
 				embed.setColor('#00FF00').setDescription( lang.get('verify.user_verified', member.toString(), '[' + escapeFormatting(username) + '](' + pagelink + ')', queryuser.gender) + ( rename ? '\n' + lang.get('verify.user_renamed', queryuser.gender) : '' ) );
 				var text = lang.get('verify.user_verified_reply', escapeFormatting(username), queryuser.gender);
 				var comment = [];
+				/** @type {Promise[]} */
+				var verifyPromise = [];
+				var editMember = {};
+				if ( rename && member.displayName !== username.substring(0, 32) ) {
+					if ( channel.guild.me.roles.highest.comparePositionTo(member.roles.highest) > 0 ) editMember.nick = username.substring(0, 32);
+					else comment.push(lang.get('verify.failed_rename', queryuser.gender));
+				}
 				removeRoles[0].forEach( role => addRoles[0].delete(role) );
 				removeRoles[1].forEach( role => addRoles[1].delete(role) );
-				var changeRoles = [];
-				if ( addRoles[0].size + removeRoles[0].size === 1 ) {
-					if ( addRoles[0].size === 1 ) changeRoles.push('add', [...addRoles[0]][0]);
-					else changeRoles.push('remove', [...removeRoles[0]][0]);
+				if ( !editMember.nick && addRoles[0].size + removeRoles[0].size <= 1 ) {
+					if ( removeRoles[0].size === 1 ) verifyPromise.push(member.roles.remove( [...removeRoles[0]][0], lang.get('verify.audit_reason', username) ).catch( error => {
+						log_error(error);
+						comment.push(lang.get('verify.failed_roles'));
+					} ));
+					else if ( addRoles[0].size === 1 ) verifyPromise.push(member.roles.add( [...addRoles[0]][0], lang.get('verify.audit_reason', username) ).catch( error => {
+						log_error(error);
+						comment.push(lang.get('verify.failed_roles'));
+					} ));
 				}
 				else {
-					let roles = new Set([...member.roles.cache.filter( role => {
+					if ( addRoles[0].size + removeRoles[0].size ) editMember.roles = [...new Set([...member.roles.cache.filter( role => {
 						return !removeRoles[0].has(role.id);
-					} ).keys(), ...addRoles[0]]);
-					changeRoles.push('set', [...roles]);
-				}
-				var verify_promise = [
-					member.roles[changeRoles[0]]( changeRoles[1], lang.get('verify.audit_reason', username) ).catch( error => {
+					} ).keys(), ...addRoles[0]])];
+					verifyPromise.push(member.edit( editMember, lang.get('verify.audit_reason', username) ).catch( error => {
 						log_error(error);
 						comment.push(lang.get('verify.failed_roles'));
-					} )
-				];
-				if ( rename && member.displayName !== username ) {
-					if ( channel.guild.me.roles.highest.comparePositionTo(member.roles.highest) > 0 ) {
-						verify_promise.push(member.setNickname( username.substring(0, 32), lang.get('verify.audit_reason', username) ).catch( error => {
-							log_error(error);
-							comment.push(lang.get('verify.failed_rename', queryuser.gender));
-						} ));
-					}
-					else comment.push(lang.get('verify.failed_rename', queryuser.gender));
+						if ( editMember.nick ) comment.push(lang.get('verify.failed_rename', queryuser.gender));
+					} ));
 				}
-				return Promise.all(verify_promise).then( () => {
+				return Promise.all(verifyPromise).then( () => {
 					var addRolesMentions = [
 						[...addRoles[0]].map( role => '<@&' + role + '>' ),
 						[...addRoles[1]].map( role => '<@&' + role + '>' )