search.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import { MessageEmbed, Util } from 'discord.js';
  2. import { got, escapeFormatting } from '../../util/functions.js';
  3. import { createRequire } from 'module';
  4. const require = createRequire(import.meta.url);
  5. const {limit: {search: searchLimit}} = require('../../util/default.json');
  6. /**
  7. * Searches a Gamepedia wiki.
  8. * @param {import('../../util/i18n.js').default} lang - The user language.
  9. * @param {import('discord.js').Message} msg - The Discord message.
  10. * @param {String} searchterm - The searchterm.
  11. * @param {import('../../util/wiki.js').default} wiki - The wiki for the search.
  12. * @param {Object} query - The siteinfo from the wiki.
  13. * @param {import('discord.js').MessageReaction} reaction - The reaction on the message.
  14. * @param {String} spoiler - If the response is in a spoiler.
  15. * @param {Boolean} noEmbed - If the response should be without an embed.
  16. */
  17. export default function gamepedia_search(lang, msg, searchterm, wiki, query, reaction, spoiler, noEmbed) {
  18. if ( searchterm.length > 250 ) {
  19. searchterm = searchterm.substring(0, 250);
  20. msg.reactEmoji('⚠️');
  21. }
  22. if ( !searchterm.trim() ) return this.special_page(lang, msg, {title: 'Special:Search'}, 'search', query, wiki, new URLSearchParams(), '', reaction, spoiler, noEmbed);
  23. var pagelink = wiki.toLink('Special:Search', {search:searchterm,fulltext:1});
  24. var resultText = '<' + pagelink + '>';
  25. var embed = null;
  26. if ( msg.showEmbed() && !noEmbed ) embed = new MessageEmbed().setAuthor( {name: query.general.sitename} ).setTitle( '`' + searchterm + '`' ).setURL( pagelink );
  27. else resultText += '\n\n**`' + searchterm + '`**';
  28. var querypage = ( Object.values(( query.pages || {} ))?.[0] || {title:'',ns:0,invalid:''} );
  29. var limit = searchLimit[( patreonGuildsPrefix.has(msg.guildId) ? 'patreon' : 'default' )];
  30. got.get( wiki + 'api.php?action=query&titles=Special:Search&list=search&srinfo=totalhits&srprop=redirecttitle|sectiontitle&srnamespace=4|12|14|' + ( querypage.ns >= 0 ? querypage.ns + '|' : '' ) + Object.values(query.namespaces).filter( ns => ns.content !== undefined ).map( ns => ns.id ).join('|') + '&srlimit=' + limit + '&srsearch=' + encodeURIComponent( searchterm ) + '&format=json' ).then( response => {
  31. var body = response.body;
  32. if ( body?.warnings ) log_warning(body.warnings);
  33. if ( response.statusCode !== 200 || !body?.query?.search || body.batchcomplete === undefined ) {
  34. return console.log( '- ' + response.statusCode + ': Error while getting the search results: ' + body?.error?.info );
  35. }
  36. if ( body.query.search.length < limit ) {
  37. return got.get( wiki + 'api.php?action=query&list=search&srwhat=text&srinfo=totalhits&srprop=redirecttitle|sectiontitle&srnamespace=4|12|14|' + ( querypage.ns >= 0 ? querypage.ns + '|' : '' ) + Object.values(query.namespaces).filter( ns => ns.content !== undefined ).map( ns => ns.id ).join('|') + '&srlimit=' + limit + '&srsearch=' + encodeURIComponent( searchterm ) + '&format=json' ).then( tresponse => {
  38. var tbody = tresponse.body;
  39. if ( tbody?.warnings ) log_warning(tbody.warnings);
  40. if ( tresponse.statusCode !== 200 || !tbody?.query?.search || tbody.batchcomplete === undefined ) {
  41. return console.log( '- ' + tresponse.statusCode + ': Error while getting the text search results: ' + tbody?.error?.info );
  42. }
  43. body.query.search.push(...tbody.query.search.filter( tresult => {
  44. return !body.query.search.some( result => result.pageid === tresult.pageid );
  45. } ).slice(0, limit - body.query.search.length));
  46. if ( body.query.searchinfo && tbody.query.searchinfo ) body.query.searchinfo.totalhits += tbody.query.searchinfo.totalhits;
  47. }, error => {
  48. console.log( '- Error while getting the text search results: ' + error );
  49. } ).then( () => {
  50. return body;
  51. } );
  52. }
  53. return body;
  54. } ).then( body => {
  55. if ( !body?.query?.search ) return;
  56. if ( body.query.pages?.['-1']?.title ) {
  57. pagelink = wiki.toLink(body.query.pages['-1'].title, {search:searchterm,fulltext:1});
  58. resultText = '<' + pagelink + '>';
  59. if ( msg.showEmbed() && !noEmbed ) embed.setURL( pagelink );
  60. else resultText += '\n\n**`' + searchterm + '`**';
  61. }
  62. var hasExactMatch = false;
  63. var description = [];
  64. body.query.search.forEach( result => {
  65. let text = '• ';
  66. let bold = '';
  67. if ( result.title.replace( /[_-]/g, ' ' ).toLowerCase() === querypage.title.replace( /-/g, ' ' ).toLowerCase() ) {
  68. bold = '**';
  69. hasExactMatch = true;
  70. if ( query.redirects?.[0] ) {
  71. if ( query.redirects[0].tofragment && !result.sectiontitle ) {
  72. result.sectiontitle = query.redirects[0].tofragment;
  73. }
  74. if ( !result.redirecttitle ) result.redirecttitle = query.redirects[0].from;
  75. }
  76. }
  77. text += bold;
  78. if ( msg.showEmbed() && !noEmbed ) {
  79. text += '[' + escapeFormatting(result.title) + '](' + wiki.toLink(result.title, '', '', true) + ')';
  80. if ( result.sectiontitle ) {
  81. text += ' § [' + escapeFormatting(result.sectiontitle) + '](' + wiki.toLink(result.title, '', result.sectiontitle, true) + ')';
  82. }
  83. if ( result.redirecttitle ) {
  84. text += ' (⤷ [' + escapeFormatting(result.redirecttitle) + '](' + wiki.toLink(result.redirecttitle, 'redirect=no', '', true) + '))';
  85. }
  86. }
  87. else {
  88. text += '<' + wiki.toLink(result.title) + '>';
  89. if ( result.sectiontitle ) text += ' § ' + escapeFormatting(result.sectiontitle);
  90. if ( result.redirecttitle ) text += ' (⤷ ' + escapeFormatting(result.redirecttitle) + ')';
  91. }
  92. text += bold;
  93. description.push( text );
  94. } );
  95. if ( !hasExactMatch ) {
  96. if ( query.interwiki?.[0] ) {
  97. let text = '• **⤷ ';
  98. if ( msg.showEmbed() && !noEmbed ) {
  99. text += '__[' + escapeFormatting(query.interwiki[0].title) + '](' + query.interwiki[0].url.replace( /[()]/g, '\\$&' ) + ')__';
  100. if ( query.redirects?.[0] ) {
  101. text += ' (⤷ [' + escapeFormatting(query.redirects[0].from) + '](' + wiki.toLink(query.redirects[0].from, 'redirect=no', '', true) + '))';
  102. }
  103. }
  104. else {
  105. text += '__<' + query.interwiki[0].url.replace( /[()]/g, '\\$&' ) + '>__';
  106. if ( query.redirects?.[0] ) text += ' (⤷ ' + escapeFormatting(query.redirects[0].from) + ')';
  107. }
  108. text += '**';
  109. description.unshift( text );
  110. }
  111. else if ( querypage.invalid === undefined && ( querypage.missing === undefined || querypage.known !== undefined ) ) {
  112. let text = '• **';
  113. if ( msg.showEmbed() && !noEmbed ) {
  114. text += '[' + escapeFormatting(querypage.title) + '](' + wiki.toLink(querypage.title, '', '', true) + ')';
  115. if ( query.redirects?.[0] ) {
  116. if ( query.redirects[0].tofragment ) {
  117. text += ' § [' + escapeFormatting(query.redirects[0].tofragment) + '](' + wiki.toLink(querypage.title, '', query.redirects[0].tofragment, true) + ')';
  118. }
  119. text += ' (⤷ [' + escapeFormatting(query.redirects[0].from) + '](' + wiki.toLink(query.redirects[0].from, 'redirect=no', '', true) + '))';
  120. }
  121. }
  122. else {
  123. text += '<' + wiki.toLink(querypage.title) + '>';
  124. if ( query.redirects?.[0] ) {
  125. if ( query.redirects[0].tofragment ) text += ' § ' + escapeFormatting(query.redirects[0].tofragment);
  126. text += ' (⤷ ' + escapeFormatting(query.redirects[0].from) + ')';
  127. }
  128. }
  129. text += '**';
  130. description.unshift( text );
  131. }
  132. }
  133. var footer = '';
  134. if ( body.query.searchinfo ) {
  135. footer = lang.get('search.results', body.query.searchinfo.totalhits.toLocaleString(lang.get('dateformat')), body.query.searchinfo.totalhits);
  136. }
  137. if ( msg.showEmbed() && !noEmbed ) {
  138. if ( description.length ) embed.setDescription( Util.splitMessage( description.join('\n') )[0] );
  139. if ( footer ) embed.setFooter( {text: footer} );
  140. }
  141. else {
  142. if ( description.length ) resultText += '\n' + Util.splitMessage( description.join('\n'), {maxLength: 1995 - resultText.length - footer.length} )[0];
  143. if ( footer ) resultText += '\n' + footer;
  144. }
  145. }, error => {
  146. console.log( '- Error while getting the search results.' + error );
  147. } ).then( () => {
  148. msg.sendChannel( {content: '🔍 ' + spoiler + resultText + spoiler, embeds: [embed]} );
  149. if ( reaction ) reaction.removeEmoji();
  150. } );
  151. }