From b9fd1a4b4ce51ebc682994f42416fd88b011bb68 Mon Sep 17 00:00:00 2001 From: Dragon Fire Date: Sat, 17 Apr 2021 10:06:44 -0400 Subject: [PATCH] 20 Questions Command --- commands/games-sp/20-questions.js | 139 ++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 commands/games-sp/20-questions.js diff --git a/commands/games-sp/20-questions.js b/commands/games-sp/20-questions.js new file mode 100644 index 00000000..c7feaf6a --- /dev/null +++ b/commands/games-sp/20-questions.js @@ -0,0 +1,139 @@ +const Command = require('../../structures/Command'); +const request = require('node-superfetch'); +const cheerio = require('cheerio'); +const { stripIndents } = require('common-tags'); +const baseURI = 'http://y.20q.net'; + +module.exports = class TwentyQuestionsCommand extends Command { + constructor(client) { + super(client, { + name: '20-questions', + aliases: ['twenty-questions', '20-q', 'twenty-q'], + group: 'games-sp', + memberName: '20-questions', + description: 'Think of something and 20Q will read your mind by asking a few simple questions.', + credit: [ + { + name: '20Q.net', + url: 'http://20q.net/', + reason: 'API' + } + ] + }); + } + + async run(msg) { + const current = this.client.games.get(msg.channel.id); + if (current) return msg.reply(`Please wait until the current game of \`${current.name}\` is finished.`); + try { + const startURL = await this.initialize(); + let question = await this.startGame(startURL); + let referer = question.url; + let win = null; + this.client.games.set(msg.channel.id, { name: this.name }); + while (win === null) { + const answers = question.answers.map(answer => answer.text.toLowerCase()); + answers.push('end'); + await msg.say(stripIndents` + **${question.question}** + ${question.answers.map(answer => answer.text).join(' | ')} | End + `); + const filter = res => res.author.id === msg.author.id && answers.includes(res.content.toLowerCase()); + const msgs = await msg.channel.awaitMessages(filter, { + max: 1, + time: 30000 + }); + if (!msgs.size) { + await msg.say('Sorry, time is up!'); + win = 'time'; + break; + } + const choice = msgs.first().content.toLowerCase(); + if (choice === 'end') { + win = 'time'; + break; + } + const answer = question.answers[answers.indexOf(choice)]; + question = await this.nextQuestion(answer.href, question.url); + if (question.win) { + win = question.win; + break; + } + } + this.client.games.delete(msg.channel.id); + if (win === 'time') return msg.say('Game ended due to forfeit.'); + return msg.say(stripIndents` + **${question.win ? 'You won!' : '20Q won!'}** + ${question.result} + `); + } catch (err) { + this.client.games.delete(msg.channel.id); + return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`); + } + } + + async initialize() { + const { text } = await request + .get(`${baseURI}/gsq-en`) + .set({ Referer: 'http://www.20q.net/' }); + const $ = cheerio.load(text); + return $('form').first().attr('action'); + } + + async startGame(startURL) { + const { text } = await request + .post(`${baseURI}${startURL}`) + .set({ + Origin: `${baseURI}/`, + Referer: `${baseURI}/gsq-en` + }) + .attach({ + submit: ' Play ', + age: '', + cctkr: 'US,AR,VI,GB,AF,PL' + }); + const $ = cheerio.load(text); + const text = $('big').eq(2).children().first(); + const answers = []; + $(text).find('a').each((i, elem) => { + const href = `${baseURI}${$(elem).attr('href')}`; + answers.push({ href, text: $(elem).text().trim() }) + }); + return { + question: text.text().split('\n')[0], + answers, + url: `${baseURI}${startURL}` + } + } + + async nextQuestion(url, referer) { + const { text } = await request + .get(url) + .set({ Referer: referer }); + const $ = cheerio.load(text); + const win = $('h2').first().text(); + if (win === '20Q won!') { + return { + win: false, + result: $('big').first().children().first().text() + }; + } + if (win === 'You won!') { + return { + win: true, + result: 'I was unable to guess what you were thinking. Nice job!' + }; + } + const text = $('big').first().children().first(); + const answers = []; + $(text).find('a').each((i, elem) => { + const href = `${baseURI}${$(elem).attr('href')}`; + answers.push({ href, text: $(elem).text().trim() }) + }); + return { + question: text.text().split('\n')[0], + answers, + url: `${baseURI}${startURL}` + } + } +}; diff --git a/package.json b/package.json index 8cb1bd39..617be305 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiao", - "version": "134.15.0", + "version": "134.16.0", "description": "Your personal server companion.", "main": "Xiao.js", "private": true,