search.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. const {MessageEmbed, Util} = require('discord.js');
  2. const {limit: {search: searchLimit}} = require('../../util/default.json');
  3. /**
  4. * Searches a Gamepedia wiki.
  5. * @param {import('../../util/i18n.js')} lang - The user language.
  6. * @param {import('discord.js').Message} msg - The Discord message.
  7. * @param {String} searchterm - The searchterm.
  8. * @param {import('../../util/wiki.js')} wiki - The wiki for the search.
  9. * @param {Object} query - The siteinfo from the wiki.
  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 gamepedia_search(lang, msg, searchterm, wiki, query, reaction, spoiler) {
  14. if ( searchterm.length > 250 ) {
  15. searchterm = searchterm.substring(0, 250);
  16. msg.reactEmoji('⚠️');
  17. }
  18. var pagelink = wiki.toLink('Special:Search', {search:searchterm,fulltext:1});
  19. var embed = new MessageEmbed().setAuthor( query.general.sitename ).setTitle( '`' + searchterm + '`' ).setURL( pagelink );
  20. if ( !searchterm.trim() ) {
  21. pagelink = wiki.toLink('Special:Search');
  22. embed.setTitle( 'Special:Search' ).setURL( pagelink );
  23. }
  24. var querypage = ( Object.values(( query.pages || {} ))?.[0] || {title:'',ns:0,invalid:''} );
  25. var description = [];
  26. var limit = searchLimit[( patreons[msg.guild?.id] ? 'patreon' : 'default' )];
  27. 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 => {
  28. var body = response.body;
  29. if ( body?.warnings ) log_warn(body.warnings);
  30. if ( response.statusCode !== 200 || !body?.query?.search || body.batchcomplete === undefined ) {
  31. return console.log( '- ' + response.statusCode + ': Error while getting the search results: ' + body?.error?.info );
  32. }
  33. if ( body.query.search.length < limit ) {
  34. return got.get( wiki + 'api.php?action=query&titles=Special:Search&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 => {
  35. var tbody = tresponse.body;
  36. if ( tbody?.warnings ) log_warn(tbody.warnings);
  37. if ( tresponse.statusCode !== 200 || !tbody?.query?.search || tbody.batchcomplete === undefined ) {
  38. return console.log( '- ' + tresponse.statusCode + ': Error while getting the text search results: ' + tbody?.error?.info );
  39. }
  40. body.query.search.push(...tbody.query.search.filter( tresult => {
  41. return !body.query.search.some( result => result.pageid === tresult.pageid );
  42. } ).slice(0, limit - body.query.search.length));
  43. if ( body.query.searchinfo && tbody.query.searchinfo ) body.query.searchinfo.totalhits += tbody.query.searchinfo.totalhits;
  44. }, error => {
  45. console.log( '- Error while getting the text search results: ' + error );
  46. } ).then( () => {
  47. return body;
  48. } );
  49. }
  50. return body;
  51. } ).then( body => {
  52. if ( !body?.query?.search ) return;
  53. if ( body.query.pages?.['-1']?.title ) {
  54. if ( searchterm.trim() ) {
  55. pagelink = wiki.toLink(body.query.pages['-1'].title, {search:searchterm,fulltext:1});
  56. embed.setURL( pagelink );
  57. }
  58. else {
  59. pagelink = wiki.toLink(body.query.pages['-1'].title);
  60. embed.setTitle( body.query.pages['-1'].title ).setURL( pagelink );
  61. }
  62. }
  63. if ( searchterm.trim() ) {
  64. var hasExactMatch = false;
  65. body.query.search.forEach( result => {
  66. let text = '• ';
  67. let bold = '';
  68. if ( result.title.replace( /[_-]/g, ' ' ).toLowerCase() === querypage.title.replace( /-/g, ' ' ).toLowerCase() ) {
  69. bold = '**';
  70. hasExactMatch = true;
  71. if ( query.redirects?.[0] ) {
  72. if ( query.redirects[0].tofragment && !result.sectiontitle ) {
  73. result.sectiontitle = query.redirects[0].tofragment;
  74. }
  75. if ( !result.redirecttitle ) result.redirecttitle = query.redirects[0].from;
  76. }
  77. }
  78. text += bold;
  79. text += '[' + result.title + '](' + wiki.toLink(result.title, '', '', true) + ')';
  80. if ( result.sectiontitle ) {
  81. text += ' § [' + result.sectiontitle + '](' + wiki.toLink(result.title, '', result.sectiontitle, true) + ')';
  82. }
  83. if ( result.redirecttitle ) {
  84. text += ' (⤷ [' + result.redirecttitle + '](' + wiki.toLink(result.redirecttitle, 'redirect=no', '', true) + '))';
  85. }
  86. text += bold;
  87. description.push( text );
  88. } );
  89. if ( !hasExactMatch ) {
  90. if ( query.interwiki?.[0] ) {
  91. let text = '• **⤷ ';
  92. text += '__[' + query.interwiki[0].title + '](' + query.interwiki[0].url.replace( /[()]/g, '\\$&' ) + ')__';
  93. if ( query.redirects?.[0] ) {
  94. text += ' (⤷ [' + query.redirects[0].from + '](' + wiki.toLink(query.redirects[0].from, 'redirect=no', '', true) + '))';
  95. }
  96. text += '**';
  97. description.unshift( text );
  98. }
  99. else if ( querypage.invalid === undefined && ( querypage.missing === undefined || querypage.known !== undefined ) ) {
  100. let text = '• **';
  101. text += '[' + querypage.title + '](' + wiki.toLink(querypage.title, '', '', true) + ')';
  102. if ( query.redirects?.[0] ) {
  103. if ( query.redirects[0].tofragment ) {
  104. text += ' § [' + query.redirects[0].tofragment + '](' + wiki.toLink(querypage.title, '', query.redirects[0].tofragment, true) + ')';
  105. }
  106. text += ' (⤷ [' + query.redirects[0].from + '](' + wiki.toLink(query.redirects[0].from, 'redirect=no', '', true) + '))';
  107. }
  108. text += '**';
  109. description.unshift( text );
  110. }
  111. }
  112. if ( body.query.searchinfo ) {
  113. embed.setFooter( lang.get('search.results', body.query.searchinfo.totalhits.toLocaleString(lang.get('dateformat')), body.query.searchinfo.totalhits) );
  114. }
  115. }
  116. }, error => {
  117. console.log( '- Error while getting the search results.' + error );
  118. } ).then( () => {
  119. embed.setDescription( Util.splitMessage( description.join('\n') )[0] );
  120. msg.sendChannel( spoiler + '<' + pagelink + '>' + spoiler, {embed} );
  121. if ( reaction ) reaction.removeEmoji();
  122. } );
  123. }
  124. module.exports = {
  125. name: 'search',
  126. run: gamepedia_search
  127. };