|  | @@ -1,164 +1,109 @@
 | 
	
		
			
				|  |  |  const {randomBytes} = require('crypto');
 | 
	
		
			
				|  |  | +const {MessageActionRow, MessageButton, Permissions: {FLAGS}} = require('discord.js');
 | 
	
		
			
				|  |  |  var db = require('../util/database.js');
 | 
	
		
			
				|  |  |  var verify = require('../functions/verify.js');
 | 
	
		
			
				|  |  |  const {got, oauthVerify, sendMessage} = require('../util/functions.js');
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Wiki user verification.
 | 
	
		
			
				|  |  | - * @param {Object} interaction - The interaction.
 | 
	
		
			
				|  |  | - * @param {import('discord.js').Client} interaction.client - The client of the interaction.
 | 
	
		
			
				|  |  | + * @param {import('discord.js').CommandInteraction} interaction - The interaction.
 | 
	
		
			
				|  |  |   * @param {import('../util/i18n.js')} lang - The user language.
 | 
	
		
			
				|  |  |   * @param {import('../util/wiki.js')} wiki - The wiki for the interaction.
 | 
	
		
			
				|  |  | - * @param {import('discord.js').TextChannel} [channel] - The channel for the interaction.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -function slash_verify(interaction, lang, wiki, channel) {
 | 
	
		
			
				|  |  | -	var reply = '<@' + ( interaction.member?.nick ? '!' : '' ) + interaction.user.id + '>, ';
 | 
	
		
			
				|  |  | -	var allowed_mentions = {
 | 
	
		
			
				|  |  | -		users: [interaction.user.id]
 | 
	
		
			
				|  |  | -	};
 | 
	
		
			
				|  |  | -	if ( !channel?.guild ) return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -		data: {
 | 
	
		
			
				|  |  | -			type: 4,
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				content: reply + lang.get('verify.missing'),
 | 
	
		
			
				|  |  | -				allowed_mentions,
 | 
	
		
			
				|  |  | -				flags: 64
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	} ).catch(log_error);
 | 
	
		
			
				|  |  | -	if ( !channel.guild.me.permissions.has('MANAGE_ROLES') ) {
 | 
	
		
			
				|  |  | -		console.log( channel.guild.id + ': Missing permissions - MANAGE_ROLES' );
 | 
	
		
			
				|  |  | -		return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				type: 4,
 | 
	
		
			
				|  |  | -				data: {
 | 
	
		
			
				|  |  | -					content: reply + lang.get('general.missingperm') + ' `MANAGE_ROLES`',
 | 
	
		
			
				|  |  | -					allowed_mentions,
 | 
	
		
			
				|  |  | -					flags: 64
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} ).catch(log_error);
 | 
	
		
			
				|  |  | +function slash_verify(interaction, lang, wiki) {
 | 
	
		
			
				|  |  | +	if ( !interaction.guild ) return interaction.reply( {content: lang.get('verify.missing'), ephemeral: true} ).catch(log_error);
 | 
	
		
			
				|  |  | +	if ( !interaction.guild.me.permissions.has(FLAGS.MANAGE_ROLES) ) {
 | 
	
		
			
				|  |  | +		console.log( interaction.guildId + ': Missing permissions - MANAGE_ROLES' );
 | 
	
		
			
				|  |  | +		return interaction.reply( {content: lang.get('general.missingperm') + ' `MANAGE_ROLES`', ephemeral: true} ).catch(log_error);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  | -	return db.query( 'SELECT logchannel, flags, onsuccess, onmatch, role, editcount, postcount, usergroup, accountage, rename FROM verification LEFT JOIN verifynotice ON verification.guild = verifynotice.guild WHERE verification.guild = $1 AND channel LIKE $2 ORDER BY configid ASC', [interaction.guild_id, '%|' + interaction.channel_id + '|%'] ).then( ({rows}) => {
 | 
	
		
			
				|  |  | -		if ( !rows.length ) return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				type: 4,
 | 
	
		
			
				|  |  | -				data: {
 | 
	
		
			
				|  |  | -					content: reply + lang.get('verify.missing') + ( interaction.member.permissions.has('MANAGE_GUILD') && process.env.dashboard ? '\n' + new URL(`/guild/${interaction.guild_id}/verification`, process.env.dashboard).href : '' ),
 | 
	
		
			
				|  |  | -					allowed_mentions,
 | 
	
		
			
				|  |  | -					flags: 64
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} ).catch(log_error);
 | 
	
		
			
				|  |  | +	return db.query( 'SELECT logchannel, flags, onsuccess, onmatch, role, editcount, postcount, usergroup, accountage, rename FROM verification LEFT JOIN verifynotice ON verification.guild = verifynotice.guild WHERE verification.guild = $1 AND channel LIKE $2 ORDER BY configid ASC', [interaction.guildId, '%|' + ( interaction.channel?.isThread() ? interaction.channel.parentId : interaction.channelId ) + '|%'] ).then( ({rows}) => {
 | 
	
		
			
				|  |  | +		if ( !rows.length ) return interaction.reply( {content: lang.get('verify.missing') + ( interaction.member.permissions.has(FLAGS.MANAGE_GUILD) && process.env.dashboard ? '\n' + new URL(`/guild/${interaction.guildId}/verification`, process.env.dashboard).href : '' ), ephemeral: true} ).catch(log_error);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		if ( wiki.hasOAuth2() && process.env.dashboard ) {
 | 
	
		
			
				|  |  |  			let oauth = [wiki.hostname + wiki.pathname.slice(0, -1)];
 | 
	
		
			
				|  |  |  			if ( wiki.isWikimedia() ) oauth.push('wikimedia');
 | 
	
		
			
				|  |  |  			if ( wiki.isMiraheze() ) oauth.push('miraheze');
 | 
	
		
			
				|  |  |  			if ( process.env['oauth_' + ( oauth[1] || oauth[0] )] && process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret'] ) {
 | 
	
		
			
				|  |  | -				return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | -					if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | -						form: {
 | 
	
		
			
				|  |  | -							grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | -							redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -							client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )],
 | 
	
		
			
				|  |  | -							client_secret: process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  | -						}
 | 
	
		
			
				|  |  | -					} ).then( response => {
 | 
	
		
			
				|  |  | -						var body = response.body;
 | 
	
		
			
				|  |  | -						if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | -							console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | -							return Promise.reject(row);
 | 
	
		
			
				|  |  | -						}
 | 
	
		
			
				|  |  | -						if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | -						}, dberror => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | -						} );
 | 
	
		
			
				|  |  | -						return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -							data: {
 | 
	
		
			
				|  |  | -								type: 5,
 | 
	
		
			
				|  |  | -								data: {
 | 
	
		
			
				|  |  | -									allowed_mentions,
 | 
	
		
			
				|  |  | -									flags: ( (rows[0].flags & 1 << 0) === 1 << 0 ? 64 : 0 )
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | +				return interaction.deferReply( {ephemeral: ( (rows[0].flags & 1 << 0) === 1 << 0 )} ).then( () => {
 | 
	
		
			
				|  |  | +					return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | +						if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | +							form: {
 | 
	
		
			
				|  |  | +								grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | +								redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +								client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )],
 | 
	
		
			
				|  |  | +								client_secret: process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  |  							}
 | 
	
		
			
				|  |  | -						} ).then( () => {
 | 
	
		
			
				|  |  | +						} ).then( response => {
 | 
	
		
			
				|  |  | +							var body = response.body;
 | 
	
		
			
				|  |  | +							if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | +								console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | +								return Promise.reject(row);
 | 
	
		
			
				|  |  | +							}
 | 
	
		
			
				|  |  | +							if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  |  							return global.verifyOauthUser('', body.access_token, {
 | 
	
		
			
				|  |  | -								wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -								user: interaction.user.id,
 | 
	
		
			
				|  |  | -								token: interaction.token
 | 
	
		
			
				|  |  | +								wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +								user: interaction.user.id, interaction,
 | 
	
		
			
				|  |  | +								fail: () => sendMessage(interaction, lang.get('verify.error_reply'))
 | 
	
		
			
				|  |  |  							});
 | 
	
		
			
				|  |  | -						}, log_error );
 | 
	
		
			
				|  |  | -					}, error => {
 | 
	
		
			
				|  |  | -						console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | -						return Promise.reject(row);
 | 
	
		
			
				|  |  | -					} );
 | 
	
		
			
				|  |  | -					return Promise.reject(row);
 | 
	
		
			
				|  |  | -				}, dberror => {
 | 
	
		
			
				|  |  | -					console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | -					return Promise.reject();
 | 
	
		
			
				|  |  | -				} ).catch( row => {
 | 
	
		
			
				|  |  | -					if ( row ) {
 | 
	
		
			
				|  |  | -						if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | -						else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | -						}, dberror => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +						}, error => {
 | 
	
		
			
				|  |  | +							console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | +							return Promise.reject(row);
 | 
	
		
			
				|  |  |  						} );
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					let state = `${oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  | -					while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | -						state = `${oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					oauthVerify.set(state, {
 | 
	
		
			
				|  |  | -						state, wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -						user: interaction.user.id,
 | 
	
		
			
				|  |  | -						token: interaction.token
 | 
	
		
			
				|  |  | -					});
 | 
	
		
			
				|  |  | -					interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | -					let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | -						response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -						client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )], state
 | 
	
		
			
				|  |  | -					}).toString();
 | 
	
		
			
				|  |  | -					return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -						data: {
 | 
	
		
			
				|  |  | -							type: 4,
 | 
	
		
			
				|  |  | -							data: {
 | 
	
		
			
				|  |  | -								content: reply + lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | -								allowed_mentions,
 | 
	
		
			
				|  |  | -								components: [
 | 
	
		
			
				|  |  | -									{
 | 
	
		
			
				|  |  | -										type: 1,
 | 
	
		
			
				|  |  | -										components: [
 | 
	
		
			
				|  |  | -											{
 | 
	
		
			
				|  |  | -												type: 2,
 | 
	
		
			
				|  |  | -												style: 5,
 | 
	
		
			
				|  |  | -												label: lang.get('verify.oauth_button'),
 | 
	
		
			
				|  |  | -												emoji: {id: null, name: '🔗'},
 | 
	
		
			
				|  |  | -												url: oauthURL,
 | 
	
		
			
				|  |  | -												disabled: false
 | 
	
		
			
				|  |  | -											}
 | 
	
		
			
				|  |  | -										]
 | 
	
		
			
				|  |  | -									}
 | 
	
		
			
				|  |  | -								],
 | 
	
		
			
				|  |  | -								flags: 64
 | 
	
		
			
				|  |  | -							}
 | 
	
		
			
				|  |  | +						return Promise.reject(row);
 | 
	
		
			
				|  |  | +					}, dberror => {
 | 
	
		
			
				|  |  | +						console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | +						return Promise.reject();
 | 
	
		
			
				|  |  | +					} ).catch( row => {
 | 
	
		
			
				|  |  | +						if ( row ) {
 | 
	
		
			
				|  |  | +							if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | +							else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  |  						}
 | 
	
		
			
				|  |  | -					} ).catch(log_error);
 | 
	
		
			
				|  |  | -				} );
 | 
	
		
			
				|  |  | +						let state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | +							state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						}
 | 
	
		
			
				|  |  | +						oauthVerify.set(state, {
 | 
	
		
			
				|  |  | +							state, wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +							user: interaction.user.id, interaction
 | 
	
		
			
				|  |  | +						});
 | 
	
		
			
				|  |  | +						interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | +						let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | +							response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +							client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )], state
 | 
	
		
			
				|  |  | +						}).toString();
 | 
	
		
			
				|  |  | +						let message = {
 | 
	
		
			
				|  |  | +							content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | +							components: [new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +								new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
 | 
	
		
			
				|  |  | +							)],
 | 
	
		
			
				|  |  | +							ephemeral: true
 | 
	
		
			
				|  |  | +						};
 | 
	
		
			
				|  |  | +						if ( (rows[0].flags & 1 << 0) === 1 << 0 ) return sendMessage(interaction, message, false);
 | 
	
		
			
				|  |  | +						return interaction.deleteReply().then( () => {
 | 
	
		
			
				|  |  | +							return interaction.followUp( message ).catch(log_error);
 | 
	
		
			
				|  |  | +						}, log_error );
 | 
	
		
			
				|  |  | +					} );
 | 
	
		
			
				|  |  | +				}, log_error );
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  | -		var username = ( interaction.data.options?.[0]?.value || '' ).replace( /^\s*<@!?(\d+)>\s*$/, (mention, id) => {
 | 
	
		
			
				|  |  | +		var username = ( interaction.options.getString('username') || '' ).replace( /^\s*<@!?(\d+)>\s*$/, (mention, id) => {
 | 
	
		
			
				|  |  |  			if ( id === interaction.user.id ) {
 | 
	
		
			
				|  |  | -				return ( interaction.member?.nick || interaction.user.username );
 | 
	
		
			
				|  |  | +				return interaction.member.displayName;
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -			let user = channel.guild.members.cache.get(id);
 | 
	
		
			
				|  |  | -			if ( user ) return user.displayName;
 | 
	
		
			
				|  |  | +			let member = interaction.guild.members.cache.get(id);
 | 
	
		
			
				|  |  | +			if ( member ) return member.displayName;
 | 
	
		
			
				|  |  |  			else {
 | 
	
		
			
				|  |  | -				user = interaction.client.users.cache.get(user);
 | 
	
		
			
				|  |  | +				let user = interaction.client.users.cache.get(id);
 | 
	
		
			
				|  |  |  				if ( user ) return user.username;
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  			return mention;
 | 
	
	
		
			
				|  | @@ -168,524 +113,320 @@ function slash_verify(interaction, lang, wiki, channel) {
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		if ( wiki.isGamepedia() ) username = username.replace( /^userprofile\s*:\s*/i, '' );
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  | -		if ( !username.trim() ) return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				type: 4,
 | 
	
		
			
				|  |  | -				data: {
 | 
	
		
			
				|  |  | -					content: lang.get('interaction.verify'),
 | 
	
		
			
				|  |  | -					allowed_mentions,
 | 
	
		
			
				|  |  | -					flags: 64
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} ).catch(log_error);
 | 
	
		
			
				|  |  | +		if ( !username.trim() ) return interaction.reply( {content: lang.get('interaction.verify'), ephemeral: true} ).catch(log_error);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				type: 5,
 | 
	
		
			
				|  |  | -				data: {
 | 
	
		
			
				|  |  | -					allowed_mentions,
 | 
	
		
			
				|  |  | -					flags: ( (rows[0].flags & 1 << 0) === 1 << 0 ? 64 : 0 )
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} ).then( () => {
 | 
	
		
			
				|  |  | -			return channel.guild.members.fetch(interaction.user.id).then( member => {
 | 
	
		
			
				|  |  | -				return verify(lang, channel, member, username, wiki, rows).then( result => {
 | 
	
		
			
				|  |  | -					if ( result.oauth.length ) {
 | 
	
		
			
				|  |  | -						return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | -							if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | -								form: {
 | 
	
		
			
				|  |  | -									grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | -									redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -									client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )],
 | 
	
		
			
				|  |  | -									client_secret: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | -							} ).then( response => {
 | 
	
		
			
				|  |  | -								var body = response.body;
 | 
	
		
			
				|  |  | -								if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | -									console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | -									return Promise.reject(row);
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | -								if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | -								}, dberror => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | -								} );
 | 
	
		
			
				|  |  | -								return global.verifyOauthUser('', body.access_token, {
 | 
	
		
			
				|  |  | -									wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -									user: interaction.user.id,
 | 
	
		
			
				|  |  | -									token: interaction.token
 | 
	
		
			
				|  |  | -								});
 | 
	
		
			
				|  |  | -							}, error => {
 | 
	
		
			
				|  |  | -								console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | -								return Promise.reject(row);
 | 
	
		
			
				|  |  | -							} );
 | 
	
		
			
				|  |  | -							return Promise.reject(row);
 | 
	
		
			
				|  |  | -						}, dberror => {
 | 
	
		
			
				|  |  | -							console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | -							return Promise.reject();
 | 
	
		
			
				|  |  | -						} ).catch( row => {
 | 
	
		
			
				|  |  | -							if ( row ) {
 | 
	
		
			
				|  |  | -								if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | -								else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | -								}, dberror => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | -								} );
 | 
	
		
			
				|  |  | +		return interaction.deferReply( {ephemeral: ( (rows[0].flags & 1 << 0) === 1 << 0 )} ).then( () => {
 | 
	
		
			
				|  |  | +			return verify(lang, interaction.channel, interaction.member, username, wiki, rows).then( result => {
 | 
	
		
			
				|  |  | +				if ( result.oauth.length ) {
 | 
	
		
			
				|  |  | +					return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | +						if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | +							form: {
 | 
	
		
			
				|  |  | +								grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | +								redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +								client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )],
 | 
	
		
			
				|  |  | +								client_secret: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  |  							}
 | 
	
		
			
				|  |  | -							let state = `${result.oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  | -							while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | -								state = `${result.oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						} ).then( response => {
 | 
	
		
			
				|  |  | +							var body = response.body;
 | 
	
		
			
				|  |  | +							if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | +								console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | +								return Promise.reject(row);
 | 
	
		
			
				|  |  |  							}
 | 
	
		
			
				|  |  | -							oauthVerify.set(state, {
 | 
	
		
			
				|  |  | -								state, wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -								user: interaction.user.id,
 | 
	
		
			
				|  |  | -								token: interaction.token
 | 
	
		
			
				|  |  | +							if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  | +							return global.verifyOauthUser('', body.access_token, {
 | 
	
		
			
				|  |  | +								wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +								user: interaction.user.id, interaction,
 | 
	
		
			
				|  |  | +								fail: () => sendMessage(interaction, lang.get('verify.error_reply'))
 | 
	
		
			
				|  |  |  							});
 | 
	
		
			
				|  |  | -							interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | -							let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | -								response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -								client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )], state
 | 
	
		
			
				|  |  | -							}).toString();
 | 
	
		
			
				|  |  | -							let message = {
 | 
	
		
			
				|  |  | -								content: reply + lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | -								allowed_mentions,
 | 
	
		
			
				|  |  | -								components: [
 | 
	
		
			
				|  |  | -									{
 | 
	
		
			
				|  |  | -										type: 1,
 | 
	
		
			
				|  |  | -										components: [
 | 
	
		
			
				|  |  | -											{
 | 
	
		
			
				|  |  | -												type: 2,
 | 
	
		
			
				|  |  | -												style: 5,
 | 
	
		
			
				|  |  | -												label: lang.get('verify.oauth_button'),
 | 
	
		
			
				|  |  | -												emoji: {id: null, name: '🔗'},
 | 
	
		
			
				|  |  | -												url: oauthURL,
 | 
	
		
			
				|  |  | -												disabled: false
 | 
	
		
			
				|  |  | -											}
 | 
	
		
			
				|  |  | -										]
 | 
	
		
			
				|  |  | -									}
 | 
	
		
			
				|  |  | -								]
 | 
	
		
			
				|  |  | -							}
 | 
	
		
			
				|  |  | -							if ( result.send_private ) return sendMessage(interaction, message, channel, false);
 | 
	
		
			
				|  |  | -							message.flags = 64;
 | 
	
		
			
				|  |  | -							return interaction.client.api.webhooks(interaction.application_id, interaction.token).messages('@original').delete().then( () => {
 | 
	
		
			
				|  |  | -								return interaction.client.api.webhooks(interaction.application_id, interaction.token).post( {
 | 
	
		
			
				|  |  | -									data: message
 | 
	
		
			
				|  |  | -								} ).catch(log_error);
 | 
	
		
			
				|  |  | -							}, log_error );
 | 
	
		
			
				|  |  | +						}, error => {
 | 
	
		
			
				|  |  | +							console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | +							return Promise.reject(row);
 | 
	
		
			
				|  |  |  						} );
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					var message = {
 | 
	
		
			
				|  |  | -						content: reply + result.content,
 | 
	
		
			
				|  |  | -						embeds: [result.embed],
 | 
	
		
			
				|  |  | -						allowed_mentions,
 | 
	
		
			
				|  |  | -						components: []
 | 
	
		
			
				|  |  | -					};
 | 
	
		
			
				|  |  | -					if ( result.add_button && !result.send_private ) message.components.push({
 | 
	
		
			
				|  |  | -						type: 1,
 | 
	
		
			
				|  |  | -						components: [
 | 
	
		
			
				|  |  | -							{
 | 
	
		
			
				|  |  | -								type: 2,
 | 
	
		
			
				|  |  | -								style: 1,
 | 
	
		
			
				|  |  | -								label: lang.get('verify.button_again'),
 | 
	
		
			
				|  |  | -								emoji: {id: null, name: '🔂'},
 | 
	
		
			
				|  |  | -								custom_id: 'verify_again',
 | 
	
		
			
				|  |  | -								disabled: false
 | 
	
		
			
				|  |  | -							}
 | 
	
		
			
				|  |  | -						]
 | 
	
		
			
				|  |  | -					});
 | 
	
		
			
				|  |  | -					if ( result.reaction ) {
 | 
	
		
			
				|  |  | -						if ( result.reaction === 'nowiki' ) message.content = lang.get('interaction.nowiki');
 | 
	
		
			
				|  |  | -						else message.content = reply + lang.get('verify.error_reply');
 | 
	
		
			
				|  |  | -						message.embeds = [];
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					return sendMessage(interaction, message, channel, false).then( msg => {
 | 
	
		
			
				|  |  | -						if ( !result.logging.channel || !channel.guild.channels.cache.has(result.logging.channel) ) return;
 | 
	
		
			
				|  |  | -						if ( msg && !result.send_private ) {
 | 
	
		
			
				|  |  | -							if ( result.logging.embed ) result.logging.embed.addField(msg.url, '<#' + channel.id + '>');
 | 
	
		
			
				|  |  | -							else result.logging.content += '\n<#' + channel.id + '> – <' + msg.url + '>';
 | 
	
		
			
				|  |  | +						return Promise.reject(row);
 | 
	
		
			
				|  |  | +					}, dberror => {
 | 
	
		
			
				|  |  | +						console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | +						return Promise.reject();
 | 
	
		
			
				|  |  | +					} ).catch( row => {
 | 
	
		
			
				|  |  | +						if ( row ) {
 | 
	
		
			
				|  |  | +							if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | +							else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  |  						}
 | 
	
		
			
				|  |  | -						channel.guild.channels.cache.get(result.logging.channel).send(result.logging.content, {
 | 
	
		
			
				|  |  | -							embed: result.logging.embed,
 | 
	
		
			
				|  |  | -							allowedMentions: {parse: []}
 | 
	
		
			
				|  |  | -						}).catch(log_error);
 | 
	
		
			
				|  |  | +						let state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | +							state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						}
 | 
	
		
			
				|  |  | +						oauthVerify.set(state, {
 | 
	
		
			
				|  |  | +							state, wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +							user: interaction.user.id, interaction
 | 
	
		
			
				|  |  | +						});
 | 
	
		
			
				|  |  | +						interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | +						let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | +							response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +							client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )], state
 | 
	
		
			
				|  |  | +						}).toString();
 | 
	
		
			
				|  |  | +						let message = {
 | 
	
		
			
				|  |  | +							content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | +							components: [new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +								new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
 | 
	
		
			
				|  |  | +							)],
 | 
	
		
			
				|  |  | +							ephemeral: true
 | 
	
		
			
				|  |  | +						}
 | 
	
		
			
				|  |  | +						if ( result.send_private ) return sendMessage(interaction, message, false);
 | 
	
		
			
				|  |  | +						return interaction.deleteReply().then( () => {
 | 
	
		
			
				|  |  | +							return interaction.followUp( message ).catch(log_error);
 | 
	
		
			
				|  |  | +						}, log_error );
 | 
	
		
			
				|  |  |  					} );
 | 
	
		
			
				|  |  | -				}, error => {
 | 
	
		
			
				|  |  | -					console.log( '- Error during the verifications: ' + error );
 | 
	
		
			
				|  |  | -					return sendMessage(interaction, {
 | 
	
		
			
				|  |  | -						content: reply + lang.get('verify.error_reply'),
 | 
	
		
			
				|  |  | -						allowed_mentions
 | 
	
		
			
				|  |  | -					}, channel);
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				var message = {
 | 
	
		
			
				|  |  | +					content: interaction.member.toString() + ', ' + result.content,
 | 
	
		
			
				|  |  | +					embeds: [result.embed],
 | 
	
		
			
				|  |  | +					components: [],
 | 
	
		
			
				|  |  | +					allowedMentions: {
 | 
	
		
			
				|  |  | +						users: [interaction.user.id],
 | 
	
		
			
				|  |  | +						repliedUser: true
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +				};
 | 
	
		
			
				|  |  | +				if ( result.reaction ) {
 | 
	
		
			
				|  |  | +					if ( result.reaction === 'nowiki' ) message.content = lang.get('interaction.nowiki');
 | 
	
		
			
				|  |  | +					else message.content = lang.get('verify.error_reply');
 | 
	
		
			
				|  |  | +					message.embeds = [];
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				else if ( result.add_button && !result.send_private ) message.components.push(new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +					new MessageButton().setLabel(lang.get('verify.button_again')).setEmoji('🔂').setStyle('PRIMARY').setCustomId('verify_again')
 | 
	
		
			
				|  |  | +				));
 | 
	
		
			
				|  |  | +				return sendMessage(interaction, message, false).then( msg => {
 | 
	
		
			
				|  |  | +					if ( !result.logging.channel || !interaction.guild.channels.cache.has(result.logging.channel) ) return;
 | 
	
		
			
				|  |  | +					if ( msg && !result.send_private ) {
 | 
	
		
			
				|  |  | +						if ( result.logging.embed ) result.logging.embed.addField(msg.url, '<#' + interaction.channelId + '>');
 | 
	
		
			
				|  |  | +						else result.logging.content += '\n<#' + interaction.channelId + '> – <' + msg.url + '>';
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +					interaction.guild.channels.cache.get(result.logging.channel).send( {
 | 
	
		
			
				|  |  | +						content: result.logging.content,
 | 
	
		
			
				|  |  | +						embeds: [result.logging.embed]
 | 
	
		
			
				|  |  | +					} ).catch(log_error);
 | 
	
		
			
				|  |  |  				} );
 | 
	
		
			
				|  |  |  			}, error => {
 | 
	
		
			
				|  |  | -				console.log( '- Error while getting the member: ' + error );
 | 
	
		
			
				|  |  | -				return sendMessage(interaction, {
 | 
	
		
			
				|  |  | -					content: reply + lang.get('verify.error_reply'),
 | 
	
		
			
				|  |  | -					allowed_mentions
 | 
	
		
			
				|  |  | -				}, channel);
 | 
	
		
			
				|  |  | +				console.log( '- Error during the verifications: ' + error );
 | 
	
		
			
				|  |  | +				return sendMessage(interaction, lang.get('verify.error_reply'));
 | 
	
		
			
				|  |  |  			} );
 | 
	
		
			
				|  |  |  		}, log_error );
 | 
	
		
			
				|  |  |  	}, dberror => {
 | 
	
		
			
				|  |  |  		console.log( '- Error while getting the verifications: ' + dberror );
 | 
	
		
			
				|  |  | -		return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				type: 4,
 | 
	
		
			
				|  |  | -				data: {
 | 
	
		
			
				|  |  | -					content: reply + lang.get('verify.error_reply'),
 | 
	
		
			
				|  |  | -					allowed_mentions,
 | 
	
		
			
				|  |  | -					flags: 64
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} ).catch(log_error);
 | 
	
		
			
				|  |  | +		return interaction.reply( {content: lang.get('verify.error_reply'), ephemeral: true} ).catch(log_error);
 | 
	
		
			
				|  |  |  	} );
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Wiki user verification.
 | 
	
		
			
				|  |  | - * @param {Object} interaction - The interaction.
 | 
	
		
			
				|  |  | - * @param {import('discord.js').Client} interaction.client - The client of the interaction.
 | 
	
		
			
				|  |  | + * @param {import('discord.js').ButtonInteraction} interaction - The interaction.
 | 
	
		
			
				|  |  |   * @param {import('../util/i18n.js')} lang - The user language.
 | 
	
		
			
				|  |  |   * @param {import('../util/wiki.js')} wiki - The wiki for the interaction.
 | 
	
		
			
				|  |  | - * @param {import('discord.js').TextChannel} [channel] - The channel for the interaction.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | - function button_verify(interaction, lang, wiki, channel) {
 | 
	
		
			
				|  |  | -	var username = interaction?.message?.embeds?.[0]?.title?.replace( /\\(\\)?/g, '$1' );
 | 
	
		
			
				|  |  | -	if ( !username || !channel?.guild || !interaction.message?.mentions?.[0]?.id ) {
 | 
	
		
			
				|  |  | -		interaction.message.allowed_mentions = {
 | 
	
		
			
				|  |  | -			users: [interaction.user.id]
 | 
	
		
			
				|  |  | -		};
 | 
	
		
			
				|  |  | -		interaction.message.components = [];
 | 
	
		
			
				|  |  | -		return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				type: 7,
 | 
	
		
			
				|  |  | -				data: interaction.message
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} ).catch(log_error);
 | 
	
		
			
				|  |  | + function button_verify(interaction, lang, wiki) {
 | 
	
		
			
				|  |  | +	var username = interaction.message?.embeds?.[0]?.title?.replace( /\\(\\)?/g, '$1' );
 | 
	
		
			
				|  |  | +	if ( !username || !interaction.guild || !interaction.message.mentions?.users?.size ) {
 | 
	
		
			
				|  |  | +		return interaction.update( {components: []} ).catch(log_error);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	if ( interaction.user.id !== interaction.message.mentions[0].id ) {
 | 
	
		
			
				|  |  | -		return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {type: 6}
 | 
	
		
			
				|  |  | -		} ).then( () => {
 | 
	
		
			
				|  |  | -			interaction.client.api.webhooks(interaction.application_id, interaction.token).post( {
 | 
	
		
			
				|  |  | -				data: {
 | 
	
		
			
				|  |  | -					content: lang.get('verify.button_wrong_user', `<@${interaction.message.mentions[0].id}>`),
 | 
	
		
			
				|  |  | -					allowed_mentions: {
 | 
	
		
			
				|  |  | -						parse: []
 | 
	
		
			
				|  |  | -					},
 | 
	
		
			
				|  |  | -					flags: 64
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			} ).catch(log_error);
 | 
	
		
			
				|  |  | -		}, log_error);
 | 
	
		
			
				|  |  | +	if ( !interaction.message.mentions.users.has(interaction.user.id) ) {
 | 
	
		
			
				|  |  | +		return interaction.reply( {content: lang.get('verify.button_wrong_user', interaction.message.mentions.users.first().toString()), ephemeral: true} ).catch(log_error);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	return db.query( 'SELECT logchannel, flags, onsuccess, onmatch, role, editcount, postcount, usergroup, accountage, rename FROM verification LEFT JOIN verifynotice ON verification.guild = verifynotice.guild WHERE verification.guild = $1 AND channel LIKE $2 ORDER BY configid ASC', [interaction.guild_id, '%|' + interaction.channel_id + '|%'] ).then( ({rows}) => {
 | 
	
		
			
				|  |  | -		if ( !rows.length || !channel.guild.me.permissions.has('MANAGE_ROLES') ) {
 | 
	
		
			
				|  |  | -			return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -				data: {type: 6}
 | 
	
		
			
				|  |  | -			} ).catch(log_error);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		var reply = '<@' + ( interaction.member?.nick ? '!' : '' ) + interaction.user.id + '>, ';
 | 
	
		
			
				|  |  | -		var allowed_mentions = {
 | 
	
		
			
				|  |  | -			users: [interaction.user.id]
 | 
	
		
			
				|  |  | -		};
 | 
	
		
			
				|  |  | -		interaction.message.allowed_mentions = allowed_mentions;
 | 
	
		
			
				|  |  | +	return db.query( 'SELECT logchannel, flags, onsuccess, onmatch, role, editcount, postcount, usergroup, accountage, rename FROM verification LEFT JOIN verifynotice ON verification.guild = verifynotice.guild WHERE verification.guild = $1 AND channel LIKE $2 ORDER BY configid ASC', [interaction.guildId, '%|' + ( interaction.channel?.isThread() ? interaction.channel.parentId : interaction.channelId ) + '|%'] ).then( ({rows}) => {
 | 
	
		
			
				|  |  | +		if ( !rows.length || !interaction.guild.me.permissions.has(FLAGS.MANAGE_ROLES) ) return interaction.update( {components: []} ).catch(log_error);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		if ( interaction?.message?.embeds?.[0]?.fields?.[1]?.value === lang.get('verify.oauth_used') && interaction?.message?.embeds?.[0]?.url?.startsWith( wiki.origin ) ) {
 | 
	
		
			
				|  |  | -			console.log( interaction.guild_id + ': Button: ' + interaction.data.custom_id + ': OAuth2: ' + username );
 | 
	
		
			
				|  |  | -			interaction.message.components[0].components[0].disabled = true;
 | 
	
		
			
				|  |  | -			return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -				data: {
 | 
	
		
			
				|  |  | -					type: 7,
 | 
	
		
			
				|  |  | -					data: interaction.message
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			} ).then( () => {
 | 
	
		
			
				|  |  | -				return global.verifyOauthUser('', '', {
 | 
	
		
			
				|  |  | -					channel, username, user: interaction.user.id,
 | 
	
		
			
				|  |  | -					send: function(content, options) {
 | 
	
		
			
				|  |  | -						if ( !content && !options ) {
 | 
	
		
			
				|  |  | -							interaction.message.components = [];
 | 
	
		
			
				|  |  | -							return sendMessage(interaction, interaction.message, channel, false);
 | 
	
		
			
				|  |  | -						}
 | 
	
		
			
				|  |  | -						var message = {
 | 
	
		
			
				|  |  | -							content, allowed_mentions,
 | 
	
		
			
				|  |  | -							embeds: ( options.embed ? [options.embed] : [] ),
 | 
	
		
			
				|  |  | -							components: ( options.components ? options.components : [] )
 | 
	
		
			
				|  |  | -						};
 | 
	
		
			
				|  |  | -						var msg = sendMessage(interaction, message, channel, false);
 | 
	
		
			
				|  |  | -						interaction.client.api.webhooks(interaction.application_id, interaction.token).post( {
 | 
	
		
			
				|  |  | -							data: {
 | 
	
		
			
				|  |  | -								content, allowed_mentions,
 | 
	
		
			
				|  |  | -								embeds: ( options.embed ? [options.embed] : [] ),
 | 
	
		
			
				|  |  | -								components: [],
 | 
	
		
			
				|  |  | -								flags: 64
 | 
	
		
			
				|  |  | -							}
 | 
	
		
			
				|  |  | -						} ).catch(log_error);
 | 
	
		
			
				|  |  | -						return msg;
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -				});
 | 
	
		
			
				|  |  | -			}, log_error );
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  |  		if ( wiki.hasOAuth2() && process.env.dashboard ) {
 | 
	
		
			
				|  |  |  			let oauth = [wiki.hostname + wiki.pathname.slice(0, -1)];
 | 
	
		
			
				|  |  |  			if ( wiki.isWikimedia() ) oauth.push('wikimedia');
 | 
	
		
			
				|  |  |  			if ( wiki.isMiraheze() ) oauth.push('miraheze');
 | 
	
		
			
				|  |  |  			if ( process.env['oauth_' + ( oauth[1] || oauth[0] )] && process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret'] ) {
 | 
	
		
			
				|  |  | -				console.log( interaction.guild_id + ': Button: ' + interaction.data.custom_id + ': OAuth2' );
 | 
	
		
			
				|  |  | -				return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | -					if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | -						form: {
 | 
	
		
			
				|  |  | -							grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | -							redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -							client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )],
 | 
	
		
			
				|  |  | -							client_secret: process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  | -						}
 | 
	
		
			
				|  |  | -					} ).then( response => {
 | 
	
		
			
				|  |  | -						var body = response.body;
 | 
	
		
			
				|  |  | -						if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | -							console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | -							return Promise.reject(row);
 | 
	
		
			
				|  |  | -						}
 | 
	
		
			
				|  |  | -						if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | -						}, dberror => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | -						} );
 | 
	
		
			
				|  |  | -						return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -							data: {
 | 
	
		
			
				|  |  | -								type: 7,
 | 
	
		
			
				|  |  | -								data: interaction.message
 | 
	
		
			
				|  |  | +				console.log( interaction.guildId + ': Button: ' + interaction.customId + ': OAuth2' );
 | 
	
		
			
				|  |  | +				return interaction.update( {components: [new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +					new MessageButton(interaction.message.components[0].components[0]).setDisabled()
 | 
	
		
			
				|  |  | +				)]} ).then( () => {
 | 
	
		
			
				|  |  | +					return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | +						if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | +							form: {
 | 
	
		
			
				|  |  | +								grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | +								redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +								client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )],
 | 
	
		
			
				|  |  | +								client_secret: process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  | +							}
 | 
	
		
			
				|  |  | +						} ).then( response => {
 | 
	
		
			
				|  |  | +							var body = response.body;
 | 
	
		
			
				|  |  | +							if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | +								console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | +								return Promise.reject(row);
 | 
	
		
			
				|  |  |  							}
 | 
	
		
			
				|  |  | -						} ).then( () => {
 | 
	
		
			
				|  |  | +							if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  |  							return global.verifyOauthUser('', body.access_token, {
 | 
	
		
			
				|  |  | -								wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -								user: interaction.user.id,
 | 
	
		
			
				|  |  | -								token: interaction.token
 | 
	
		
			
				|  |  | +								wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +								user: interaction.user.id, interaction,
 | 
	
		
			
				|  |  | +								fail: () => sendMessage(interaction, {components: []}, false)
 | 
	
		
			
				|  |  |  							});
 | 
	
		
			
				|  |  | -						}, log_error );
 | 
	
		
			
				|  |  | -					}, error => {
 | 
	
		
			
				|  |  | -						console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | -						return Promise.reject(row);
 | 
	
		
			
				|  |  | -					} );
 | 
	
		
			
				|  |  | -					return Promise.reject(row);
 | 
	
		
			
				|  |  | -				}, dberror => {
 | 
	
		
			
				|  |  | -					console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | -					return Promise.reject();
 | 
	
		
			
				|  |  | -				} ).catch( row => {
 | 
	
		
			
				|  |  | -					if ( row ) {
 | 
	
		
			
				|  |  | -						if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | -						else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | -						}, dberror => {
 | 
	
		
			
				|  |  | -							console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +						}, error => {
 | 
	
		
			
				|  |  | +							console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | +							return Promise.reject(row);
 | 
	
		
			
				|  |  |  						} );
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					let state = `${oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  | -					while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | -						state = `${oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					oauthVerify.set(state, {
 | 
	
		
			
				|  |  | -						state, wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -						user: interaction.user.id,
 | 
	
		
			
				|  |  | -						token: interaction.token
 | 
	
		
			
				|  |  | -					});
 | 
	
		
			
				|  |  | -					interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | -					let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | -						response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -						client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )], state
 | 
	
		
			
				|  |  | -					}).toString();
 | 
	
		
			
				|  |  | -					interaction.message.components = [];
 | 
	
		
			
				|  |  | -					interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -						data: {
 | 
	
		
			
				|  |  | -							type: 7,
 | 
	
		
			
				|  |  | -							data: interaction.message
 | 
	
		
			
				|  |  | +						return Promise.reject(row);
 | 
	
		
			
				|  |  | +					}, dberror => {
 | 
	
		
			
				|  |  | +						console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | +						return Promise.reject();
 | 
	
		
			
				|  |  | +					} ).catch( row => {
 | 
	
		
			
				|  |  | +						if ( row ) {
 | 
	
		
			
				|  |  | +							if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | +							else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  |  						}
 | 
	
		
			
				|  |  | -					} ).catch(log_error);
 | 
	
		
			
				|  |  | -					return interaction.client.api.webhooks(interaction.application_id, interaction.token).post( {
 | 
	
		
			
				|  |  | -						data: {
 | 
	
		
			
				|  |  | -							content: reply + lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | -							allowed_mentions,
 | 
	
		
			
				|  |  | -							components: [
 | 
	
		
			
				|  |  | -								{
 | 
	
		
			
				|  |  | -									type: 1,
 | 
	
		
			
				|  |  | -									components: [
 | 
	
		
			
				|  |  | -										{
 | 
	
		
			
				|  |  | -											type: 2,
 | 
	
		
			
				|  |  | -											style: 5,
 | 
	
		
			
				|  |  | -											label: lang.get('verify.oauth_button'),
 | 
	
		
			
				|  |  | -											emoji: {id: null, name: '🔗'},
 | 
	
		
			
				|  |  | -											url: oauthURL,
 | 
	
		
			
				|  |  | -											disabled: false
 | 
	
		
			
				|  |  | -										}
 | 
	
		
			
				|  |  | -									]
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | -							],
 | 
	
		
			
				|  |  | -							flags: 64
 | 
	
		
			
				|  |  | +						let state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | +							state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
 | 
	
		
			
				|  |  |  						}
 | 
	
		
			
				|  |  | -					} ).catch(log_error);
 | 
	
		
			
				|  |  | -				} );
 | 
	
		
			
				|  |  | +						oauthVerify.set(state, {
 | 
	
		
			
				|  |  | +							state, wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +							user: interaction.user.id, interaction
 | 
	
		
			
				|  |  | +						});
 | 
	
		
			
				|  |  | +						interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | +						let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | +							response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +							client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )], state
 | 
	
		
			
				|  |  | +						}).toString();
 | 
	
		
			
				|  |  | +						sendMessage(interaction, {components: []}, false);
 | 
	
		
			
				|  |  | +						return interaction.followUp( {
 | 
	
		
			
				|  |  | +							content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | +							components: [new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +								new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
 | 
	
		
			
				|  |  | +							)],
 | 
	
		
			
				|  |  | +							ephemeral: true
 | 
	
		
			
				|  |  | +						} ).catch(log_error);
 | 
	
		
			
				|  |  | +					} );
 | 
	
		
			
				|  |  | +				}, log_error );
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		interaction.message.components[0].components[0].disabled = true;
 | 
	
		
			
				|  |  | -		return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {
 | 
	
		
			
				|  |  | -				type: 7,
 | 
	
		
			
				|  |  | -				data: interaction.message
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} ).then( () => {
 | 
	
		
			
				|  |  | -			return channel.guild.members.fetch(interaction.user.id).then( member => {
 | 
	
		
			
				|  |  | -				console.log( interaction.guild_id + ': Button: ' + interaction.data.custom_id + ' ' + username );
 | 
	
		
			
				|  |  | -				return verify(lang, channel, member, username, wiki, rows).then( result => {
 | 
	
		
			
				|  |  | -					if ( result.oauth.length ) {
 | 
	
		
			
				|  |  | -						return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | -							if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | -								form: {
 | 
	
		
			
				|  |  | -									grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | -									redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -									client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )],
 | 
	
		
			
				|  |  | -									client_secret: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | -							} ).then( response => {
 | 
	
		
			
				|  |  | -								var body = response.body;
 | 
	
		
			
				|  |  | -								if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | -									console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | -									return Promise.reject(row);
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | -								if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | -								}, dberror => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | -								} );
 | 
	
		
			
				|  |  | -								return global.verifyOauthUser('', body.access_token, {
 | 
	
		
			
				|  |  | -									wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -									user: interaction.user.id,
 | 
	
		
			
				|  |  | -									token: interaction.token
 | 
	
		
			
				|  |  | -								});
 | 
	
		
			
				|  |  | -							}, error => {
 | 
	
		
			
				|  |  | -								console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | -								return Promise.reject(row);
 | 
	
		
			
				|  |  | -							} );
 | 
	
		
			
				|  |  | -							return Promise.reject(row);
 | 
	
		
			
				|  |  | -						}, dberror => {
 | 
	
		
			
				|  |  | -							console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | -							return Promise.reject();
 | 
	
		
			
				|  |  | -						} ).catch( row => {
 | 
	
		
			
				|  |  | -							if ( row ) {
 | 
	
		
			
				|  |  | -								if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | -								else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | -								}, dberror => {
 | 
	
		
			
				|  |  | -									console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | -								} );
 | 
	
		
			
				|  |  | +		return interaction.update( {components: [new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +			new MessageButton(interaction.message.components[0].components[0]).setDisabled()
 | 
	
		
			
				|  |  | +		)]} ).then( () => {
 | 
	
		
			
				|  |  | +			console.log( interaction.guildId + ': Button: ' + interaction.customId + ' ' + username );
 | 
	
		
			
				|  |  | +			return verify(lang, interaction.channel, interaction.member, username, wiki, rows).then( result => {
 | 
	
		
			
				|  |  | +				if ( result.oauth.length ) {
 | 
	
		
			
				|  |  | +					return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( ({rows: [row]}) => {
 | 
	
		
			
				|  |  | +						if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
 | 
	
		
			
				|  |  | +							form: {
 | 
	
		
			
				|  |  | +								grant_type: 'refresh_token', refresh_token: row.token,
 | 
	
		
			
				|  |  | +								redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +								client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )],
 | 
	
		
			
				|  |  | +								client_secret: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] ) + '_secret']
 | 
	
		
			
				|  |  |  							}
 | 
	
		
			
				|  |  | -							let state = `${result.oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  | -							while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | -								state = `${result.oauth[0]} ${global.shardId}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						} ).then( response => {
 | 
	
		
			
				|  |  | +							var body = response.body;
 | 
	
		
			
				|  |  | +							if ( response.statusCode !== 200 || !body?.access_token ) {
 | 
	
		
			
				|  |  | +								console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
 | 
	
		
			
				|  |  | +								return Promise.reject(row);
 | 
	
		
			
				|  |  |  							}
 | 
	
		
			
				|  |  | -							oauthVerify.set(state, {
 | 
	
		
			
				|  |  | -								state, wiki: wiki.href, channel,
 | 
	
		
			
				|  |  | -								user: interaction.user.id,
 | 
	
		
			
				|  |  | -								token: interaction.token
 | 
	
		
			
				|  |  | +							if ( body?.refresh_token ) db.query( 'UPDATE oauthusers SET token = $1 WHERE userid = $2 AND site = $3', [body.refresh_token, interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  | +							return global.verifyOauthUser('', body.access_token, {
 | 
	
		
			
				|  |  | +								wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +								user: interaction.user.id, interaction,
 | 
	
		
			
				|  |  | +								fail: () => sendMessage(interaction, {components: []}, false)
 | 
	
		
			
				|  |  |  							});
 | 
	
		
			
				|  |  | -							interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | -							let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | -								response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | -								client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )], state
 | 
	
		
			
				|  |  | -							}).toString();
 | 
	
		
			
				|  |  | -							interaction.message.components = [];
 | 
	
		
			
				|  |  | -							interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -								data: {
 | 
	
		
			
				|  |  | -									type: 7,
 | 
	
		
			
				|  |  | -									data: interaction.message
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | -							} ).catch(log_error);
 | 
	
		
			
				|  |  | -							return interaction.client.api.webhooks(interaction.application_id, interaction.token).post( {
 | 
	
		
			
				|  |  | -								data: {
 | 
	
		
			
				|  |  | -									content: reply + lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | -									allowed_mentions,
 | 
	
		
			
				|  |  | -									components: [
 | 
	
		
			
				|  |  | -										{
 | 
	
		
			
				|  |  | -											type: 1,
 | 
	
		
			
				|  |  | -											components: [
 | 
	
		
			
				|  |  | -												{
 | 
	
		
			
				|  |  | -													type: 2,
 | 
	
		
			
				|  |  | -													style: 5,
 | 
	
		
			
				|  |  | -													label: lang.get('verify.oauth_button'),
 | 
	
		
			
				|  |  | -													emoji: {id: null, name: '🔗'},
 | 
	
		
			
				|  |  | -													url: oauthURL,
 | 
	
		
			
				|  |  | -													disabled: false
 | 
	
		
			
				|  |  | -												}
 | 
	
		
			
				|  |  | -											]
 | 
	
		
			
				|  |  | -										}
 | 
	
		
			
				|  |  | -									],
 | 
	
		
			
				|  |  | -									flags: 64
 | 
	
		
			
				|  |  | -								}
 | 
	
		
			
				|  |  | -							} ).catch(log_error);
 | 
	
		
			
				|  |  | +						}, error => {
 | 
	
		
			
				|  |  | +							console.log( '- Error while refreshing the mediawiki token: ' + error );
 | 
	
		
			
				|  |  | +							return Promise.reject(row);
 | 
	
		
			
				|  |  |  						} );
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					var message = {
 | 
	
		
			
				|  |  | -						content: reply + result.content,
 | 
	
		
			
				|  |  | -						embeds: [result.embed],
 | 
	
		
			
				|  |  | -						allowed_mentions,
 | 
	
		
			
				|  |  | -						components: []
 | 
	
		
			
				|  |  | -					};
 | 
	
		
			
				|  |  | -					if ( result.reaction ) {
 | 
	
		
			
				|  |  | -						if ( result.reaction === 'nowiki' ) message.content = lang.get('interaction.nowiki');
 | 
	
		
			
				|  |  | -						else message.content = reply + lang.get('verify.error_reply');
 | 
	
		
			
				|  |  | -						message.embeds = [];
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					else if ( result.add_button ) message.components.push({
 | 
	
		
			
				|  |  | -						type: 1,
 | 
	
		
			
				|  |  | -						components: [
 | 
	
		
			
				|  |  | -							{
 | 
	
		
			
				|  |  | -								type: 2,
 | 
	
		
			
				|  |  | -								style: 1,
 | 
	
		
			
				|  |  | -								label: lang.get('verify.button_again'),
 | 
	
		
			
				|  |  | -								emoji: {id: null, name: '🔂'},
 | 
	
		
			
				|  |  | -								custom_id: 'verify_again',
 | 
	
		
			
				|  |  | -								disabled: false
 | 
	
		
			
				|  |  | -							}
 | 
	
		
			
				|  |  | -						]
 | 
	
		
			
				|  |  | -					});
 | 
	
		
			
				|  |  | -					sendMessage(interaction, message, channel, false);
 | 
	
		
			
				|  |  | -					if ( result.logging.channel && channel.guild.channels.cache.has(result.logging.channel) ) {
 | 
	
		
			
				|  |  | -						if ( !result.send_private ) {
 | 
	
		
			
				|  |  | -							let msg_url = `https://discord.com/channels/${channel.guild.id}/${channel.id}/${interaction.message.id}`;
 | 
	
		
			
				|  |  | -							if ( result.logging.embed ) result.logging.embed.addField(msg_url, '<#' + channel.id + '>');
 | 
	
		
			
				|  |  | -							else result.logging.content += '\n<#' + channel.id + '> – <' + msg_url + '>';
 | 
	
		
			
				|  |  | +						return Promise.reject(row);
 | 
	
		
			
				|  |  | +					}, dberror => {
 | 
	
		
			
				|  |  | +						console.log( '- Error while getting the OAuth2 token: ' + dberror );
 | 
	
		
			
				|  |  | +						return Promise.reject();
 | 
	
		
			
				|  |  | +					} ).catch( row => {
 | 
	
		
			
				|  |  | +						if ( row ) {
 | 
	
		
			
				|  |  | +							if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
 | 
	
		
			
				|  |  | +							else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( result.oauth[1] || result.oauth[0] )] ).then( () => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
 | 
	
		
			
				|  |  | +							}, dberror => {
 | 
	
		
			
				|  |  | +								console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
 | 
	
		
			
				|  |  | +							} );
 | 
	
		
			
				|  |  |  						}
 | 
	
		
			
				|  |  | -						channel.guild.channels.cache.get(result.logging.channel).send(result.logging.content, {
 | 
	
		
			
				|  |  | -							embed: result.logging.embed,
 | 
	
		
			
				|  |  | -							allowedMentions: {parse: []}
 | 
	
		
			
				|  |  | -						}).catch(log_error);
 | 
	
		
			
				|  |  | -					}
 | 
	
		
			
				|  |  | -					interaction.client.api.webhooks(interaction.application_id, interaction.token).post( {
 | 
	
		
			
				|  |  | -						data: {
 | 
	
		
			
				|  |  | -							content: message.content,
 | 
	
		
			
				|  |  | -							embeds: message.embeds,
 | 
	
		
			
				|  |  | -							allowed_mentions,
 | 
	
		
			
				|  |  | -							components: [],
 | 
	
		
			
				|  |  | -							flags: 64
 | 
	
		
			
				|  |  | +						let state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  | +						while ( oauthVerify.has(state) ) {
 | 
	
		
			
				|  |  | +							state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
 | 
	
		
			
				|  |  |  						}
 | 
	
		
			
				|  |  | +						oauthVerify.set(state, {
 | 
	
		
			
				|  |  | +							state, wiki: wiki.href, channel: interaction.channel,
 | 
	
		
			
				|  |  | +							user: interaction.user.id, interaction
 | 
	
		
			
				|  |  | +						});
 | 
	
		
			
				|  |  | +						interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
 | 
	
		
			
				|  |  | +						let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
 | 
	
		
			
				|  |  | +							response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
 | 
	
		
			
				|  |  | +							client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )], state
 | 
	
		
			
				|  |  | +						}).toString();
 | 
	
		
			
				|  |  | +						sendMessage(interaction, {components: []}, false);
 | 
	
		
			
				|  |  | +						return interaction.followUp( {
 | 
	
		
			
				|  |  | +							content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
 | 
	
		
			
				|  |  | +							components: [new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +								new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
 | 
	
		
			
				|  |  | +							)],
 | 
	
		
			
				|  |  | +							ephemeral: true
 | 
	
		
			
				|  |  | +						} ).catch(log_error);
 | 
	
		
			
				|  |  | +					} );
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				var message = {
 | 
	
		
			
				|  |  | +					content: interaction.member.toString() + ', ' + result.content,
 | 
	
		
			
				|  |  | +					embeds: [result.embed],
 | 
	
		
			
				|  |  | +					components: [],
 | 
	
		
			
				|  |  | +					allowedMentions: {
 | 
	
		
			
				|  |  | +						users: [interaction.user.id],
 | 
	
		
			
				|  |  | +						repliedUser: true
 | 
	
		
			
				|  |  | +					}
 | 
	
		
			
				|  |  | +				};
 | 
	
		
			
				|  |  | +				if ( result.reaction ) {
 | 
	
		
			
				|  |  | +					if ( result.reaction === 'nowiki' ) message.content = lang.get('interaction.nowiki');
 | 
	
		
			
				|  |  | +					else message.content = lang.get('verify.error_reply');
 | 
	
		
			
				|  |  | +					message.embeds = [];
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				else if ( result.add_button ) message.components.push(new MessageActionRow().addComponents(
 | 
	
		
			
				|  |  | +					new MessageButton().setLabel(lang.get('verify.button_again')).setEmoji('🔂').setStyle('PRIMARY').setCustomId('verify_again')
 | 
	
		
			
				|  |  | +				));
 | 
	
		
			
				|  |  | +				sendMessage(interaction, message, false);
 | 
	
		
			
				|  |  | +				if ( result.logging.channel && interaction.guild.channels.cache.has(result.logging.channel) ) {
 | 
	
		
			
				|  |  | +					if ( result.logging.embed ) result.logging.embed.addField(interaction.message.url, '<#' + interaction.channelId + '>');
 | 
	
		
			
				|  |  | +					else result.logging.content += '\n<#' + interaction.channelId + '> – <' + interaction.message.url + '>';
 | 
	
		
			
				|  |  | +					interaction.guild.channels.cache.get(result.logging.channel).send( {
 | 
	
		
			
				|  |  | +						content: result.logging.content,
 | 
	
		
			
				|  |  | +						embeds: [result.logging.embed]
 | 
	
		
			
				|  |  |  					} ).catch(log_error);
 | 
	
		
			
				|  |  | -				}, error => {
 | 
	
		
			
				|  |  | -					console.log( '- Error during the verifications: ' + error );
 | 
	
		
			
				|  |  | -					return sendMessage(interaction, {
 | 
	
		
			
				|  |  | -						content: reply + lang.get('verify.error_reply'),
 | 
	
		
			
				|  |  | -						allowed_mentions
 | 
	
		
			
				|  |  | -					}, channel);
 | 
	
		
			
				|  |  | -				} );
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				interaction.followUp( {
 | 
	
		
			
				|  |  | +					content: message.content,
 | 
	
		
			
				|  |  | +					embeds: message.embeds,
 | 
	
		
			
				|  |  | +					components: [],
 | 
	
		
			
				|  |  | +					ephemeral: true
 | 
	
		
			
				|  |  | +				} ).catch(log_error);
 | 
	
		
			
				|  |  |  			}, error => {
 | 
	
		
			
				|  |  | -				console.log( '- Error while getting the member: ' + error );
 | 
	
		
			
				|  |  | -				return sendMessage(interaction, {
 | 
	
		
			
				|  |  | -					content: reply + lang.get('verify.error_reply'),
 | 
	
		
			
				|  |  | -					allowed_mentions
 | 
	
		
			
				|  |  | -				}, channel);
 | 
	
		
			
				|  |  | +				console.log( '- Error during the verifications: ' + error );
 | 
	
		
			
				|  |  | +				return sendMessage(interaction, {components: []});
 | 
	
		
			
				|  |  |  			} );
 | 
	
		
			
				|  |  |  		}, log_error);
 | 
	
		
			
				|  |  |  	}, dberror => {
 | 
	
		
			
				|  |  |  		console.log( '- Error while getting the verifications: ' + dberror );
 | 
	
		
			
				|  |  | -		return interaction.client.api.interactions(interaction.id, interaction.token).callback.post( {
 | 
	
		
			
				|  |  | -			data: {type: 6}
 | 
	
		
			
				|  |  | -		} ).catch(log_error);
 | 
	
		
			
				|  |  | +		return interaction.reply( {content: lang.get('verify.error_reply'), ephemeral: true} ).catch(log_error);
 | 
	
		
			
				|  |  |  	} );
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |