const htmlparser = require('htmlparser2');
const {MessageEmbed} = require('discord.js');
const extract_desc = require('../../../util/extract_desc.js');
/**
* Sends a random Gamepedia page.
* @param {import('../../../util/i18n.js')} lang - The user language.
* @param {import('discord.js').Message} msg - The Discord message.
* @param {String} wiki - The wiki for the page.
* @param {import('discord.js').MessageReaction} reaction - The reaction on the message.
* @param {String} spoiler - If the response is in a spoiler.
*/
function gamepedia_random(lang, msg, wiki, reaction, spoiler) {
got.get( wiki + 'api.php?action=query&meta=siteinfo&siprop=general&prop=pageimages|pageprops|extracts&piprop=original|name&ppprop=description|displaytitle&explaintext=true&exsectionformat=raw&exlimit=1&generator=random&grnnamespace=0&format=json', {
responseType: 'json'
} ).then( response => {
var body = response.body;
if ( body && body.warnings ) log_warn(body.warnings);
if ( response.statusCode !== 200 || !body || body.batchcomplete === undefined || !body.query || !body.query.pages ) {
if ( wiki.noWiki(response.url) || response.statusCode === 410 ) {
console.log( '- This wiki doesn\'t exist!' );
msg.reactEmoji('nowiki');
}
else {
console.log( '- ' + response.statusCode + ': Error while getting the search results: ' + ( body && body.error && body.error.info ) );
msg.sendChannelError( spoiler + '<' + wiki.toLink('Special:Random') + '>' + spoiler );
}
}
else {
var querypage = Object.values(body.query.pages)[0];
var pagelink = wiki.toLink(querypage.title, '', '', body.query.general);
var embed = new MessageEmbed().setAuthor( body.query.general.sitename ).setTitle( querypage.title.escapeFormatting() ).setURL( pagelink );
if ( querypage.pageprops && querypage.pageprops.displaytitle ) {
var displaytitle = htmlToDiscord( querypage.pageprops.displaytitle );
if ( displaytitle.length > 250 ) displaytitle = displaytitle.substring(0, 250) + '\u2026';
embed.setTitle( displaytitle );
}
if ( querypage.pageprops && querypage.pageprops.description ) {
var description = htmlToPlain( querypage.pageprops.description );
if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
embed.setDescription( description );
}
else if ( querypage.extract ) {
var extract = extract_desc(querypage.extract);
embed.setDescription( extract[0] );
}
if ( querypage.pageimage && querypage.original && querypage.title !== body.query.general.mainpage ) {
embed.setThumbnail( querypage.original.source );
}
else embed.setThumbnail( ( /^(?:https?:)?\/\//.test(body.query.general.logo) ? body.query.general.logo.replace( /^(?:https?:)?\/\//, 'https://' ) : body.query.general.server + ( body.query.general.logo.startsWith( '/' ) ? '' : '/' ) + body.query.general.logo ) );
msg.sendChannel( '🎲 ' + spoiler + '<' + pagelink + '>' + spoiler, {embed} );
}
}, error => {
if ( wiki.noWiki(error.message) ) {
console.log( '- This wiki doesn\'t exist!' );
msg.reactEmoji('nowiki');
}
else {
console.log( '- Error while getting the search results: ' + error );
msg.sendChannelError( spoiler + '<' + wiki.toLink('Special:Random') + '>' + spoiler );
}
} ).finally( () => {
if ( reaction ) reaction.removeEmoji();
} );
}
/**
* Change HTML text to plain text.
* @param {String} html - The text in HTML.
* @returns {String}
*/
function htmlToPlain(html) {
var text = '';
var parser = new htmlparser.Parser( {
ontext: (htmltext) => {
text += htmltext.escapeFormatting();
}
}, {decodeEntities:true} );
parser.write( html );
parser.end();
return text;
};
/**
* Change HTML text to markdown text.
* @param {String} html - The text in HTML.
* @returns {String}
*/
function htmlToDiscord(html) {
var text = '';
var parser = new htmlparser.Parser( {
onopentag: (tagname, attribs) => {
switch (tagname) {
case 'b':
text += '**';
break;
case 'i':
text += '*';
break;
case 's':
text += '~~';
break;
case 'u':
text += '__';
break;
}
},
ontext: (htmltext) => {
text += htmltext.escapeFormatting();
},
onclosetag: (tagname) => {
switch (tagname) {
case 'b':
text += '**';
break;
case 'i':
text += '*';
break;
case 's':
text += '~~';
break;
case 'u':
text += '__';
break;
}
}
}, {decodeEntities:true} );
parser.write( html );
parser.end();
return text;
};
module.exports = {
name: 'random',
run: gamepedia_random
};