verify.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. import { randomBytes } from 'crypto';
  2. import { MessageActionRow, MessageButton, Permissions } from 'discord.js';
  3. import db from '../util/database.js';
  4. import verify from '../functions/verify.js';
  5. import { got, oauthVerify, sendMessage } from '../util/functions.js';
  6. /**
  7. * Wiki user verification.
  8. * @param {import('discord.js').CommandInteraction} interaction - The interaction.
  9. * @param {import('../util/i18n.js').default} lang - The user language.
  10. * @param {import('../util/wiki.js').default} wiki - The wiki for the interaction.
  11. */
  12. function slash_verify(interaction, lang, wiki) {
  13. if ( !interaction.guild ) return interaction.reply( {content: lang.get('verify.missing'), ephemeral: true} ).catch(log_error);
  14. if ( !interaction.guild.me.permissions.has(Permissions.FLAGS.MANAGE_ROLES) ) {
  15. console.log( interaction.guildId + ': Missing permissions - MANAGE_ROLES' );
  16. return interaction.reply( {content: lang.get('general.missingperm') + ' `MANAGE_ROLES`', ephemeral: true} ).catch(log_error);
  17. }
  18. 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}) => {
  19. if ( !rows.length ) return interaction.reply( {content: lang.get('verify.missing') + ( interaction.member.permissions.has(Permissions.FLAGS.MANAGE_GUILD) && process.env.dashboard ? '\n' + new URL(`/guild/${interaction.guildId}/verification`, process.env.dashboard).href : '' ), ephemeral: true} ).catch(log_error);
  20. if ( wiki.hasOAuth2() && process.env.dashboard ) {
  21. let oauth = [wiki.hostname + wiki.pathname.slice(0, -1)];
  22. if ( wiki.isWikimedia() ) oauth.push('wikimedia');
  23. if ( wiki.isMiraheze() ) oauth.push('miraheze');
  24. if ( process.env['oauth_' + ( oauth[1] || oauth[0] )] && process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret'] ) {
  25. return interaction.deferReply( {ephemeral: ( (rows[0].flags & 1 << 0) === 1 << 0 )} ).then( () => {
  26. return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( ({rows: [row]}) => {
  27. if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
  28. form: {
  29. grant_type: 'refresh_token', refresh_token: row.token,
  30. redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  31. client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )],
  32. client_secret: process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret']
  33. }
  34. } ).then( response => {
  35. var body = response.body;
  36. if ( response.statusCode !== 200 || !body?.access_token ) {
  37. console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
  38. return Promise.reject(row);
  39. }
  40. 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( () => {
  41. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
  42. }, dberror => {
  43. console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  44. } );
  45. return verifyOauthUser('', body.access_token, {
  46. wiki: wiki.href, channel: interaction.channel,
  47. user: interaction.user.id, interaction,
  48. fail: () => sendMessage(interaction, lang.get('verify.error_reply'))
  49. });
  50. }, error => {
  51. console.log( '- Error while refreshing the mediawiki token: ' + error );
  52. return Promise.reject(row);
  53. } );
  54. return Promise.reject(row);
  55. }, dberror => {
  56. console.log( '- Error while getting the OAuth2 token: ' + dberror );
  57. return Promise.reject();
  58. } ).catch( row => {
  59. if ( row ) {
  60. if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
  61. else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
  62. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
  63. }, dberror => {
  64. console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  65. } );
  66. }
  67. let state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
  68. while ( oauthVerify.has(state) ) {
  69. state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
  70. }
  71. oauthVerify.set(state, {
  72. state, wiki: wiki.href, channel: interaction.channel,
  73. user: interaction.user.id, interaction
  74. });
  75. interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
  76. let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
  77. response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  78. client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )], state
  79. }).toString();
  80. let message = {
  81. content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
  82. components: [new MessageActionRow().addComponents(
  83. new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
  84. )],
  85. ephemeral: true
  86. };
  87. if ( (rows[0].flags & 1 << 0) === 1 << 0 ) return sendMessage(interaction, message, false);
  88. return interaction.deleteReply().then( () => {
  89. return interaction.followUp( message ).catch(log_error);
  90. }, log_error );
  91. } );
  92. }, log_error );
  93. }
  94. }
  95. var username = ( interaction.options.getString('username') || '' ).replace( /^\s*<@!?(\d+)>\s*$/, (mention, id) => {
  96. if ( id === interaction.user.id ) {
  97. return interaction.member.displayName;
  98. }
  99. let member = interaction.guild.members.cache.get(id);
  100. if ( member ) return member.displayName;
  101. else {
  102. let user = interaction.client.users.cache.get(id);
  103. if ( user ) return user.username;
  104. }
  105. return mention;
  106. } ).replace( /_/g, ' ' ).trim().replace( /^<\s*(.*)\s*>$/, '$1' ).split('#')[0].substring(0, 250).trim();
  107. if ( /^(?:https?:)?\/\/([a-z\d-]{1,50})\.(?:gamepedia\.com\/|(?:fandom\.com|wikia\.org)\/(?:[a-z-]{1,8}\/)?(?:wiki\/)?)/.test(username) ) {
  108. username = decodeURIComponent( username.replace( /^(?:https?:)?\/\/([a-z\d-]{1,50})\.(?:gamepedia\.com\/|(?:fandom\.com|wikia\.org)\/(?:[a-z-]{1,8}\/)?(?:wiki\/)?)/, '' ) );
  109. }
  110. if ( wiki.isGamepedia() ) username = username.replace( /^userprofile\s*:\s*/i, '' );
  111. if ( !username.trim() ) return interaction.reply( {content: lang.get('interaction.verify'), ephemeral: true} ).catch(log_error);
  112. return interaction.deferReply( {ephemeral: ( (rows[0].flags & 1 << 0) === 1 << 0 )} ).then( () => {
  113. return verify(lang, interaction.channel, interaction.member, username, wiki, rows).then( result => {
  114. if ( result.oauth.length ) {
  115. 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]}) => {
  116. if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
  117. form: {
  118. grant_type: 'refresh_token', refresh_token: row.token,
  119. redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  120. client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )],
  121. client_secret: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] ) + '_secret']
  122. }
  123. } ).then( response => {
  124. var body = response.body;
  125. if ( response.statusCode !== 200 || !body?.access_token ) {
  126. console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
  127. return Promise.reject(row);
  128. }
  129. 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( () => {
  130. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
  131. }, dberror => {
  132. console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  133. } );
  134. return verifyOauthUser('', body.access_token, {
  135. wiki: wiki.href, channel: interaction.channel,
  136. user: interaction.user.id, interaction,
  137. fail: () => sendMessage(interaction, lang.get('verify.error_reply'))
  138. });
  139. }, error => {
  140. console.log( '- Error while refreshing the mediawiki token: ' + error );
  141. return Promise.reject(row);
  142. } );
  143. return Promise.reject(row);
  144. }, dberror => {
  145. console.log( '- Error while getting the OAuth2 token: ' + dberror );
  146. return Promise.reject();
  147. } ).catch( row => {
  148. if ( row ) {
  149. if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
  150. 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( () => {
  151. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
  152. }, dberror => {
  153. console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  154. } );
  155. }
  156. let state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
  157. while ( oauthVerify.has(state) ) {
  158. state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
  159. }
  160. oauthVerify.set(state, {
  161. state, wiki: wiki.href, channel: interaction.channel,
  162. user: interaction.user.id, interaction
  163. });
  164. interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
  165. let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
  166. response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  167. client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )], state
  168. }).toString();
  169. let message = {
  170. content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
  171. components: [new MessageActionRow().addComponents(
  172. new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
  173. )],
  174. ephemeral: true
  175. }
  176. if ( result.send_private ) return sendMessage(interaction, message, false);
  177. return interaction.deleteReply().then( () => {
  178. return interaction.followUp( message ).catch(log_error);
  179. }, log_error );
  180. } );
  181. }
  182. var message = {
  183. content: interaction.member.toString() + ', ' + result.content,
  184. embeds: [result.embed],
  185. components: [],
  186. allowedMentions: {
  187. users: [interaction.user.id],
  188. repliedUser: true
  189. }
  190. };
  191. if ( result.reaction ) {
  192. if ( result.reaction === 'nowiki' ) message.content = lang.get('interaction.nowiki');
  193. else message.content = lang.get('verify.error_reply');
  194. message.embeds = [];
  195. }
  196. else if ( result.add_button && !result.send_private ) message.components.push(new MessageActionRow().addComponents(
  197. new MessageButton().setLabel(lang.get('verify.button_again')).setEmoji('🔂').setStyle('PRIMARY').setCustomId('verify_again')
  198. ));
  199. return sendMessage(interaction, message, false).then( msg => {
  200. if ( !result.logging.channel || !interaction.guild.channels.cache.has(result.logging.channel) ) return;
  201. if ( msg && !result.send_private ) {
  202. if ( result.logging.embed ) result.logging.embed.addField(msg.url, '<#' + interaction.channelId + '>');
  203. else result.logging.content += '\n<#' + interaction.channelId + '> – <' + msg.url + '>';
  204. }
  205. interaction.guild.channels.cache.get(result.logging.channel).send( {
  206. content: result.logging.content,
  207. embeds: ( result.logging.embed ? [result.logging.embed] : [] )
  208. } ).catch(log_error);
  209. } );
  210. }, error => {
  211. console.log( '- Error during the verifications: ' + error );
  212. return sendMessage(interaction, lang.get('verify.error_reply'));
  213. } );
  214. }, log_error );
  215. }, dberror => {
  216. console.log( '- Error while getting the verifications: ' + dberror );
  217. return interaction.reply( {content: lang.get('verify.error_reply'), ephemeral: true} ).catch(log_error);
  218. } );
  219. }
  220. /**
  221. * Wiki user verification.
  222. * @param {import('discord.js').ButtonInteraction} interaction - The interaction.
  223. * @param {import('../util/i18n.js').default} lang - The user language.
  224. * @param {import('../util/wiki.js').default} wiki - The wiki for the interaction.
  225. */
  226. function button_verify(interaction, lang, wiki) {
  227. var username = interaction.message?.embeds?.[0]?.title?.replace( /\\(\\)?/g, '$1' );
  228. if ( !username || !interaction.guild || !interaction.message.mentions?.users?.size ) {
  229. return interaction.update( {components: []} ).catch(log_error);
  230. }
  231. if ( !interaction.message.mentions.users.has(interaction.user.id) ) {
  232. return interaction.reply( {content: lang.get('verify.button_wrong_user', interaction.message.mentions.users.first().toString()), ephemeral: true} ).catch(log_error);
  233. }
  234. 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}) => {
  235. if ( !rows.length || !interaction.guild.me.permissions.has(Permissions.FLAGS.MANAGE_ROLES) ) return interaction.update( {components: []} ).catch(log_error);
  236. if ( wiki.hasOAuth2() && process.env.dashboard ) {
  237. let oauth = [wiki.hostname + wiki.pathname.slice(0, -1)];
  238. if ( wiki.isWikimedia() ) oauth.push('wikimedia');
  239. if ( wiki.isMiraheze() ) oauth.push('miraheze');
  240. if ( process.env['oauth_' + ( oauth[1] || oauth[0] )] && process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret'] ) {
  241. console.log( interaction.guildId + ': Button: ' + interaction.customId + ': OAuth2' );
  242. return interaction.update( {components: [new MessageActionRow().addComponents(
  243. new MessageButton(interaction.message.components[0].components[0]).setDisabled()
  244. )]} ).then( () => {
  245. return db.query( 'SELECT token FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( ({rows: [row]}) => {
  246. if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
  247. form: {
  248. grant_type: 'refresh_token', refresh_token: row.token,
  249. redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  250. client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )],
  251. client_secret: process.env['oauth_' + ( oauth[1] || oauth[0] ) + '_secret']
  252. }
  253. } ).then( response => {
  254. var body = response.body;
  255. if ( response.statusCode !== 200 || !body?.access_token ) {
  256. console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
  257. return Promise.reject(row);
  258. }
  259. 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( () => {
  260. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
  261. }, dberror => {
  262. console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  263. } );
  264. return verifyOauthUser('', body.access_token, {
  265. wiki: wiki.href, channel: interaction.channel,
  266. user: interaction.user.id, interaction,
  267. fail: () => sendMessage(interaction, {components: []}, false)
  268. });
  269. }, error => {
  270. console.log( '- Error while refreshing the mediawiki token: ' + error );
  271. return Promise.reject(row);
  272. } );
  273. return Promise.reject(row);
  274. }, dberror => {
  275. console.log( '- Error while getting the OAuth2 token: ' + dberror );
  276. return Promise.reject();
  277. } ).catch( row => {
  278. if ( row ) {
  279. if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
  280. else if ( row.token ) db.query( 'DELETE FROM oauthusers WHERE userid = $1 AND site = $2', [interaction.user.id, ( oauth[1] || oauth[0] )] ).then( () => {
  281. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
  282. }, dberror => {
  283. console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  284. } );
  285. }
  286. let state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
  287. while ( oauthVerify.has(state) ) {
  288. state = `${oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( oauth[1] ? ` ${oauth[1]}` : '' );
  289. }
  290. oauthVerify.set(state, {
  291. state, wiki: wiki.href, channel: interaction.channel,
  292. user: interaction.user.id, interaction
  293. });
  294. interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
  295. let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
  296. response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  297. client_id: process.env['oauth_' + ( oauth[1] || oauth[0] )], state
  298. }).toString();
  299. sendMessage(interaction, {components: []}, false);
  300. return interaction.followUp( {
  301. content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
  302. components: [new MessageActionRow().addComponents(
  303. new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
  304. )],
  305. ephemeral: true
  306. } ).catch(log_error);
  307. } );
  308. }, log_error );
  309. }
  310. }
  311. return interaction.update( {components: [new MessageActionRow().addComponents(
  312. new MessageButton(interaction.message.components[0].components[0]).setDisabled()
  313. )]} ).then( () => {
  314. console.log( interaction.guildId + ': Button: ' + interaction.customId + ' ' + username );
  315. return verify(lang, interaction.channel, interaction.member, username, wiki, rows).then( result => {
  316. if ( result.oauth.length ) {
  317. 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]}) => {
  318. if ( row?.token ) return got.post( wiki + 'rest.php/oauth2/access_token', {
  319. form: {
  320. grant_type: 'refresh_token', refresh_token: row.token,
  321. redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  322. client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )],
  323. client_secret: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] ) + '_secret']
  324. }
  325. } ).then( response => {
  326. var body = response.body;
  327. if ( response.statusCode !== 200 || !body?.access_token ) {
  328. console.log( '- ' + response.statusCode + ': Error while refreshing the mediawiki token: ' + ( body?.message || body?.error ) );
  329. return Promise.reject(row);
  330. }
  331. 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( () => {
  332. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully updated.' );
  333. }, dberror => {
  334. console.log( '- Dashboard: Error while updating the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  335. } );
  336. return verifyOauthUser('', body.access_token, {
  337. wiki: wiki.href, channel: interaction.channel,
  338. user: interaction.user.id, interaction,
  339. fail: () => sendMessage(interaction, {components: []}, false)
  340. });
  341. }, error => {
  342. console.log( '- Error while refreshing the mediawiki token: ' + error );
  343. return Promise.reject(row);
  344. } );
  345. return Promise.reject(row);
  346. }, dberror => {
  347. console.log( '- Error while getting the OAuth2 token: ' + dberror );
  348. return Promise.reject();
  349. } ).catch( row => {
  350. if ( row ) {
  351. if ( !row?.hasOwnProperty?.('token') ) console.log( '- Error while checking the OAuth2 refresh token: ' + row );
  352. 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( () => {
  353. console.log( '- Dashboard: OAuth2 token for ' + interaction.user.id + ' successfully deleted.' );
  354. }, dberror => {
  355. console.log( '- Dashboard: Error while deleting the OAuth2 token for ' + interaction.user.id + ': ' + dberror );
  356. } );
  357. }
  358. let state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
  359. while ( oauthVerify.has(state) ) {
  360. state = `${result.oauth[0]} ${process.env.SHARDS}` + Date.now().toString(16) + randomBytes(16).toString('hex') + ( result.oauth[1] ? ` ${result.oauth[1]}` : '' );
  361. }
  362. oauthVerify.set(state, {
  363. state, wiki: wiki.href, channel: interaction.channel,
  364. user: interaction.user.id, interaction
  365. });
  366. interaction.client.shard.send({id: 'verifyUser', state, user: ( row?.token === null ? '' : interaction.user.id )});
  367. let oauthURL = wiki + 'rest.php/oauth2/authorize?' + new URLSearchParams({
  368. response_type: 'code', redirect_uri: new URL('/oauth/mw', process.env.dashboard).href,
  369. client_id: process.env['oauth_' + ( result.oauth[1] || result.oauth[0] )], state
  370. }).toString();
  371. sendMessage(interaction, {components: []}, false);
  372. return interaction.followUp( {
  373. content: lang.get('verify.oauth_message', '<' + oauthURL + '>'),
  374. components: [new MessageActionRow().addComponents(
  375. new MessageButton().setLabel(lang.get('verify.oauth_button')).setEmoji('🔗').setStyle('LINK').setURL(oauthURL)
  376. )],
  377. ephemeral: true
  378. } ).catch(log_error);
  379. } );
  380. }
  381. var message = {
  382. content: interaction.member.toString() + ', ' + result.content,
  383. embeds: [result.embed],
  384. components: [],
  385. allowedMentions: {
  386. users: [interaction.user.id],
  387. repliedUser: true
  388. }
  389. };
  390. if ( result.reaction ) {
  391. if ( result.reaction === 'nowiki' ) message.content = lang.get('interaction.nowiki');
  392. else message.content = lang.get('verify.error_reply');
  393. message.embeds = [];
  394. }
  395. else if ( result.add_button ) message.components.push(new MessageActionRow().addComponents(
  396. new MessageButton().setLabel(lang.get('verify.button_again')).setEmoji('🔂').setStyle('PRIMARY').setCustomId('verify_again')
  397. ));
  398. sendMessage(interaction, message, false);
  399. if ( result.logging.channel && interaction.guild.channels.cache.has(result.logging.channel) ) {
  400. if ( result.logging.embed ) result.logging.embed.addField(interaction.message.url, '<#' + interaction.channelId + '>');
  401. else result.logging.content += '\n<#' + interaction.channelId + '> – <' + interaction.message.url + '>';
  402. interaction.guild.channels.cache.get(result.logging.channel).send( {
  403. content: result.logging.content,
  404. embeds: ( result.logging.embed ? [result.logging.embed] : [] )
  405. } ).catch(log_error);
  406. }
  407. interaction.followUp( {
  408. content: message.content,
  409. embeds: message.embeds,
  410. components: [],
  411. ephemeral: true
  412. } ).catch(log_error);
  413. }, error => {
  414. console.log( '- Error during the verifications: ' + error );
  415. return sendMessage(interaction, {components: []});
  416. } );
  417. }, log_error);
  418. }, dberror => {
  419. console.log( '- Error while getting the verifications: ' + dberror );
  420. return interaction.reply( {content: lang.get('verify.error_reply'), ephemeral: true} ).catch(log_error);
  421. } );
  422. }
  423. export default {
  424. name: 'verify',
  425. run: slash_verify,
  426. button: button_verify
  427. };