bug.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. const {MessageEmbed} = require('discord.js');
  2. /**
  3. * Sends a Minecraft issue.
  4. * @param {import('../../util/i18n.js')} lang - The user language.
  5. * @param {import('discord.js').Message} msg - The Discord message.
  6. * @param {import('../../util/wiki.js')} wiki - The wiki.
  7. * @param {String[]} args - The command arguments.
  8. * @param {String} title - The page title.
  9. * @param {String} cmd - The command at this point.
  10. * @param {import('discord.js').MessageReaction} reaction - The reaction on the message.
  11. * @param {String} spoiler - If the response is in a spoiler.
  12. */
  13. function minecraft_bug(lang, msg, wiki, args, title, cmd, reaction, spoiler) {
  14. var invoke = args[0];
  15. args = args.slice(1);
  16. if ( invoke && /\d+$/.test(invoke) && !args.length ) {
  17. if ( /^\d+$/.test(invoke) ) invoke = 'MC-' + invoke;
  18. var baseBrowseUrl = 'https://bugs.mojang.com/browse/';
  19. got.get( 'https://bugs.mojang.com/rest/api/2/issue/' + encodeURIComponent( invoke ) + '?fields=summary,description,issuelinks,fixVersions,resolution,status' ).then( response => {
  20. var body = response.body;
  21. if ( response.statusCode !== 200 || !body || body['status-code'] === 404 || body.errorMessages || body.errors ) {
  22. if ( body && body.errorMessages ) {
  23. if ( body.errorMessages.includes( 'Issue Does Not Exist' ) ) {
  24. msg.reactEmoji('🤷');
  25. }
  26. else if ( body.errorMessages.includes( 'You do not have the permission to see the specified issue.' ) ) {
  27. msg.sendChannel( spoiler + lang.get('minecraft.private') + '\n<' + baseBrowseUrl + invoke + '>' + spoiler );
  28. }
  29. else {
  30. console.log( '- ' + ( response && response.statusCode ) + ': Error while getting the issue: ' + body.errorMessages.join(' - ') );
  31. msg.reactEmoji('error');
  32. }
  33. }
  34. else {
  35. console.log( '- ' + response.statusCode + ': Error while getting the issue: ' + ( body && body.message ) );
  36. if ( body && body['status-code'] === 404 ) msg.reactEmoji('error');
  37. else msg.sendChannelError( spoiler + '<' + baseBrowseUrl + invoke + '>' + spoiler );
  38. }
  39. }
  40. else {
  41. if ( !body.fields ) {
  42. msg.reactEmoji('error');
  43. }
  44. else {
  45. var statusList = lang.get('minecraft.status');
  46. var summary = body.fields.summary.escapeFormatting();
  47. if ( summary.length > 250 ) summary = summary.substring(0, 250) + '\u2026';
  48. var description = ( body.fields.description || '' ).replace( /\{code\}/g, '```' );
  49. if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
  50. var embed = new MessageEmbed().setAuthor( 'Mojira' ).setTitle( summary ).setURL( baseBrowseUrl + body.key ).setDescription( parse_links( description ) );
  51. var links = body.fields.issuelinks.filter( link => link.outwardIssue || ( link.inwardIssue && link.type.name !== 'Duplicate' ) );
  52. if ( links.length ) {
  53. var linkList = lang.get('minecraft.issue_link');
  54. var extralinks = [];
  55. links.forEach( link => {
  56. var ward = ( link.outwardIssue ? 'outward' : 'inward' );
  57. var issue = link[ward + 'Issue']; // looks for property (in|out)wardIssue
  58. var name = ( linkList?.[link.type.name]?.[ward]?.replaceSave( /\$1/g, issue.key ) || link.type[ward] + ' ' + issue.key );
  59. var status = issue.fields.status.name;
  60. var value = ( statusList?.[status] || status ) + ': [' + issue.fields.summary.escapeFormatting() + '](' + baseBrowseUrl + issue.key + ')';
  61. if ( embed.fields.length < 25 && ( embed.length + name.length + value.length ) < 6000 ) embed.addField( name, value );
  62. else extralinks.push({name,value,inline:false});
  63. } );
  64. if ( extralinks.length ) embed.setFooter( lang.get('minecraft.more', extralinks.length.toLocaleString(lang.get('dateformat')), extralinks.length) );
  65. }
  66. var status = ( body.fields.resolution ? body.fields.resolution.name : body.fields.status.name );
  67. var fixed = '';
  68. if ( body.fields.resolution && body.fields.fixVersions && body.fields.fixVersions.length ) {
  69. fixed = '\n' + lang.get('minecraft.fixed', body.fields.fixVersions.length) + ' ' + body.fields.fixVersions.map( v => v.name ).join(', ');
  70. }
  71. msg.sendChannel( spoiler + '**' + ( statusList?.[status] || status ) + '**: ' + body.fields.summary.escapeFormatting() + '\n<' + baseBrowseUrl + body.key + '>' + fixed + spoiler, {embed} );
  72. }
  73. }
  74. }, error => {
  75. console.log( '- Error while getting the issue: ' + error );
  76. msg.sendChannelError( spoiler + '<' + baseBrowseUrl + invoke + '>' + spoiler );
  77. } ).finally( () => {
  78. if ( reaction ) reaction.removeEmoji();
  79. } );
  80. }
  81. else if ( invoke && invoke.toLowerCase() === 'version' && args.length && args.join(' ').length < 100 ) {
  82. var jql = new URLSearchParams({
  83. jql: 'fixVersion="' + args.join(' ').replace( /["\\]/g, '\\$&' ) + '" order by key'
  84. });
  85. var uri = 'https://bugs.mojang.com/issues/?' + jql;
  86. got.get( 'https://bugs.mojang.com/rest/api/2/search?fields=summary,resolution,status&' + jql + '&maxResults=25' ).then( response => {
  87. var body = response.body;
  88. if ( response.statusCode !== 200 || !body || body['status-code'] === 404 || body.errorMessages || body.errors ) {
  89. if ( body && body.errorMessages ) {
  90. if ( body.errorMessages.includes( 'The value \'' + args.join(' ') + '\' does not exist for the field \'fixVersion\'.' ) ) {
  91. msg.reactEmoji('🤷');
  92. }
  93. else {
  94. console.log( '- ' + response.statusCode + ': Error while getting the issues: ' + body.errorMessages.join(' - ') );
  95. msg.reactEmoji('error');
  96. }
  97. }
  98. else {
  99. console.log( '- ' + response.statusCode + ': Error while getting the issues: ' + ( body && body.message ) );
  100. if ( body && body['status-code'] === 404 ) msg.reactEmoji('error');
  101. else msg.sendChannelError( spoiler + '<' + uri + '>' + spoiler );
  102. }
  103. }
  104. else {
  105. if ( !body.issues ) {
  106. msg.reactEmoji('error');
  107. }
  108. else {
  109. var embed = new MessageEmbed().setAuthor( 'Mojira' ).setTitle( args.join(' ') ).setURL( uri );
  110. if ( body.total > 0 ) {
  111. var statusList = lang.get('minecraft.status');
  112. body.issues.forEach( bug => {
  113. var status = ( bug.fields.resolution ? bug.fields.resolution.name : bug.fields.status.name );
  114. var value = ( statusList?.[status] || status ) + ': [' + bug.fields.summary.escapeFormatting() + '](https://bugs.mojang.com/browse/' + bug.key + ')';
  115. embed.addField( bug.key, value );
  116. } );
  117. if ( body.total > 25 ) {
  118. var extrabugs = body.total - 25;
  119. embed.setFooter( lang.get('minecraft.more', extrabugs.toLocaleString(lang.get('dateformat')), extrabugs) );
  120. }
  121. }
  122. var total = '**' + args.join(' ') + ':** ' + lang.get('minecraft.total', body.total.toLocaleString(lang.get('dateformat')), body.total);
  123. msg.sendChannel( spoiler + total + '\n<' + uri + '>' + spoiler, {embed} );
  124. }
  125. }
  126. }, error => {
  127. console.log( '- Error while getting the issues: ' + error );
  128. msg.sendChannelError( spoiler + '<' + uri + '>' + spoiler );
  129. } ).finally( () => {
  130. if ( reaction ) reaction.removeEmoji();
  131. } );
  132. }
  133. else {
  134. msg.notMinecraft = true;
  135. this.WIKI.general(lang, msg, title, wiki, cmd, reaction, spoiler);
  136. }
  137. }
  138. /**
  139. * Parse Mojira links.
  140. * @param {String} text - The text to parse.
  141. * @returns {String}
  142. */
  143. function parse_links(text) {
  144. text = text.replace( /\[~([^\]]+)\]/g, '[$1](https://bugs.mojang.com/secure/ViewProfile.jspa?name=$1)' );
  145. text = text.replace( /\[([^\|]+)\|([^\]]+)\]/g, '[$1]($2)' );
  146. return text;
  147. }
  148. module.exports = {
  149. name: 'bug',
  150. run: minecraft_bug
  151. };