mirror of
https://github.com/arthur-pbty/xiao.git
synced 2026-06-22 01:57:54 +02:00
Split Single and Multi Player Games
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { shuffle, verify } = require('../../util/Util');
|
||||
const suits = ['♣', '♥', '♦', '♠'];
|
||||
const faces = ['Jack', 'Queen', 'King'];
|
||||
|
||||
module.exports = class BlackjackCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'blackjack',
|
||||
aliases: ['twenty-one', '21', 'bj'],
|
||||
group: 'sp-games',
|
||||
memberName: 'blackjack',
|
||||
description: 'Play a game of blackjack.',
|
||||
args: [
|
||||
{
|
||||
key: 'deckCount',
|
||||
label: 'amount of decks',
|
||||
prompt: 'How many decks do you want to use?',
|
||||
type: 'integer',
|
||||
default: 1,
|
||||
max: 8,
|
||||
min: 1
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { deckCount }) { // eslint-disable-line complexity
|
||||
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 {
|
||||
this.client.games.set(msg.channel.id, { name: this.name, data: this.generateDeck(deckCount) });
|
||||
const dealerHand = [];
|
||||
this.draw(msg.channel, dealerHand);
|
||||
this.draw(msg.channel, dealerHand);
|
||||
const playerHand = [];
|
||||
this.draw(msg.channel, playerHand);
|
||||
this.draw(msg.channel, playerHand);
|
||||
const dealerInitialTotal = this.calculate(dealerHand);
|
||||
const playerInitialTotal = this.calculate(playerHand);
|
||||
if (dealerInitialTotal === 21 && playerInitialTotal === 21) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.say('Well, both of you just hit blackjack. Right away. Rigged.');
|
||||
} else if (dealerInitialTotal === 21) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.say('Ouch, the dealer hit blackjack right away! Try again!');
|
||||
} else if (playerInitialTotal === 21) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.say('Wow, you hit blackjack right away! Lucky you!');
|
||||
}
|
||||
let playerTurn = true;
|
||||
let win = false;
|
||||
let reason;
|
||||
while (!win) {
|
||||
if (playerTurn) {
|
||||
await msg.say(stripIndents`
|
||||
**First Dealer Card:** ${dealerHand[0].display}
|
||||
|
||||
**You (${this.calculate(playerHand)}):**
|
||||
${playerHand.map(card => card.display).join('\n')}
|
||||
|
||||
_Hit?_
|
||||
`);
|
||||
const hit = await verify(msg.channel, msg.author);
|
||||
if (hit) {
|
||||
const card = this.draw(msg.channel, playerHand);
|
||||
const total = this.calculate(playerHand);
|
||||
if (total > 21) {
|
||||
reason = `You drew ${card.display}, total of ${total}! Bust`;
|
||||
break;
|
||||
} else if (total === 21) {
|
||||
reason = `You drew ${card.display} and hit 21`;
|
||||
win = true;
|
||||
}
|
||||
} else {
|
||||
const dealerTotal = this.calculate(dealerHand);
|
||||
await msg.say(`Second dealer card is ${dealerHand[1].display}, total of ${dealerTotal}.`);
|
||||
playerTurn = false;
|
||||
}
|
||||
} else {
|
||||
const inital = this.calculate(dealerHand);
|
||||
let card;
|
||||
if (inital < 17) card = this.draw(msg.channel, dealerHand);
|
||||
const total = this.calculate(dealerHand);
|
||||
if (total > 21) {
|
||||
reason = `Dealer drew ${card.display}, total of ${total}! Dealer bust`;
|
||||
win = true;
|
||||
} else if (total >= 17) {
|
||||
const playerTotal = this.calculate(playerHand);
|
||||
if (total === playerTotal) {
|
||||
reason = `${card ? `Dealer drew ${card.display}, making it ` : ''}${playerTotal}-${total}`;
|
||||
break;
|
||||
} else if (total > playerTotal) {
|
||||
reason = `${card ? `Dealer drew ${card.display}, making it ` : ''}${playerTotal}-**${total}**`;
|
||||
break;
|
||||
} else {
|
||||
reason = `${card ? `Dealer drew ${card.display}, making it ` : ''}**${playerTotal}**-${total}`;
|
||||
win = true;
|
||||
}
|
||||
} else {
|
||||
await msg.say(`Dealer drew ${card.display}, total of ${total}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.client.games.delete(msg.channel.id);
|
||||
if (win) return msg.say(`${reason}! You won!`);
|
||||
return msg.say(`${reason}! Too bad.`);
|
||||
} catch (err) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
generateDeck(deckCount) {
|
||||
const deck = [];
|
||||
for (let i = 0; i < deckCount; i++) {
|
||||
for (const suit of suits) {
|
||||
deck.push({
|
||||
value: 11,
|
||||
display: `${suit} Ace`
|
||||
});
|
||||
for (let j = 2; j <= 10; j++) {
|
||||
deck.push({
|
||||
value: j,
|
||||
display: `${suit} ${j}`
|
||||
});
|
||||
}
|
||||
for (const face of faces) {
|
||||
deck.push({
|
||||
value: 10,
|
||||
display: `${suit} ${face}`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return shuffle(deck);
|
||||
}
|
||||
|
||||
draw(channel, hand) {
|
||||
const deck = this.client.games.get(channel.id).data;
|
||||
const card = deck[0];
|
||||
deck.shift();
|
||||
hand.push(card);
|
||||
return card;
|
||||
}
|
||||
|
||||
calculate(hand) {
|
||||
return hand.sort((a, b) => a.value - b.value).reduce((a, b) => {
|
||||
let { value } = b;
|
||||
if (value === 11 && a + value > 21) value = 1;
|
||||
return a + value;
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { verify } = require('../../util/Util');
|
||||
const script = require('../../assets/json/box-choosing');
|
||||
|
||||
module.exports = class BoxChoosingCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'box-choosing',
|
||||
aliases: ['box-choose'],
|
||||
group: 'sp-games',
|
||||
memberName: 'box-choosing',
|
||||
description: 'Do you believe that there are choices in life? Taken from Higurashi Chapter 4.',
|
||||
credit: [
|
||||
{
|
||||
name: '07th Expansion',
|
||||
url: 'http://07th-expansion.net/'
|
||||
},
|
||||
{
|
||||
name: 'MangaGamer.com',
|
||||
url: 'https://www.mangagamer.com/'
|
||||
},
|
||||
{
|
||||
name: 'Higurashi When They Cry Hou - Ch.4 Himatsubushi',
|
||||
url: 'https://store.steampowered.com/app/526490/'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
this.blue = new Set();
|
||||
this.red = new Set();
|
||||
}
|
||||
|
||||
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.`);
|
||||
this.client.games.set(msg.channel.id, { name: this.name });
|
||||
try {
|
||||
let i = 0;
|
||||
let path = 'before';
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const line = script[path][i];
|
||||
if (line.end) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.say(line.text);
|
||||
} else {
|
||||
await msg.say(typeof line === 'object' ? line.text : stripIndents`
|
||||
${line}
|
||||
|
||||
_Proceed?_
|
||||
`);
|
||||
}
|
||||
if (line.options) {
|
||||
const filter = res => res.author.id === msg.author.id && line.options.includes(res.content.toLowerCase());
|
||||
const choose = await msg.channel.awaitMessages(filter, {
|
||||
max: 1,
|
||||
time: 120000
|
||||
});
|
||||
if (!choose.size) break;
|
||||
path = '';
|
||||
const pick = line.paths[line.options.indexOf(choose.first().content.toLowerCase())];
|
||||
if ((this.red.has(msg.author.id) && pick !== 'red') || (this.blue.has(msg.author.id) && pick !== 'blue')) {
|
||||
path += 'both';
|
||||
if (this.red.has(msg.author.id)) this.red.delete(msg.author.id);
|
||||
if (this.blue.has(msg.author.id)) this.blue.delete(msg.author.id);
|
||||
} else {
|
||||
this[pick].add(msg.author.id);
|
||||
setTimeout(() => { if (this[pick].has(msg.author.id)) this[pick].delete(msg.author.id); }, 600000);
|
||||
}
|
||||
path += pick;
|
||||
i = 0;
|
||||
} else {
|
||||
const verification = await verify(msg.channel, msg.author, 120000);
|
||||
if (!verification) break;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.say('See you soon!');
|
||||
} catch (err) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, registerFont } = require('canvas');
|
||||
const path = require('path');
|
||||
const pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ23456789'.split('');
|
||||
registerFont(path.join(__dirname, '..', '..', 'assets', 'fonts', 'Captcha.ttf'), { family: 'Captcha' });
|
||||
|
||||
module.exports = class CaptchaCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'captcha',
|
||||
aliases: ['captcha-quiz'],
|
||||
group: 'sp-games',
|
||||
memberName: 'captcha',
|
||||
description: 'Try to guess what the captcha says.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Moms Typewriter Font',
|
||||
url: 'https://www.fontsquirrel.com/fonts/MomsTypewriter'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg) {
|
||||
const canvas = createCanvas(125, 32);
|
||||
const ctx = canvas.getContext('2d');
|
||||
const text = this.randomText(5);
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = '#0088cc';
|
||||
ctx.font = '26px Captcha';
|
||||
ctx.rotate(-0.05);
|
||||
ctx.strokeText(text, 15, 26);
|
||||
await msg.reply(
|
||||
'**You have 15 seconds, what does the captcha say?**',
|
||||
{ files: [{ attachment: canvas.toBuffer(), name: 'captcha-quiz.png' }] }
|
||||
);
|
||||
const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, {
|
||||
max: 1,
|
||||
time: 15000
|
||||
});
|
||||
if (!msgs.size) return msg.reply(`Sorry, time is up! It was ${text}.`);
|
||||
if (msgs.first().content !== text) return msg.reply(`Nope, sorry, it's ${text}.`);
|
||||
return msg.reply('Nice job! 10/10! You deserve some cake!');
|
||||
}
|
||||
|
||||
randomText(len) {
|
||||
const result = [];
|
||||
for (let i = 0; i < len; i++) result.push(pool[Math.floor(Math.random() * pool.length)]);
|
||||
return result.join('');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
const Command = require('../../structures/Command');
|
||||
|
||||
module.exports = class ChanceCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'chance',
|
||||
aliases: ['1-in', 'one-in'],
|
||||
group: 'sp-games',
|
||||
memberName: 'chance',
|
||||
description: 'Attempt to win with a 1 in 1000 (or your choice) chance of winning.',
|
||||
args: [
|
||||
{
|
||||
key: 'chance',
|
||||
prompt: 'What is the chance of winning? 1 in what?',
|
||||
type: 'string',
|
||||
default: 1000
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
run(msg, { chance }) {
|
||||
const loss = Math.floor(Math.random() * chance);
|
||||
if (!loss) return msg.reply('Nice job! 10/10! You deserve some cake!');
|
||||
return msg.reply('Nope, sorry, you lost.');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { verify } = require('../../util/Util');
|
||||
const doors = [1, 2, 3];
|
||||
|
||||
module.exports = class DoorsCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'doors',
|
||||
aliases: ['door', 'door-opening', 'open-door', 'monty-hall'],
|
||||
group: 'sp-games',
|
||||
memberName: 'doors',
|
||||
description: 'Open the right door, and you win the money! Make the wrong choice, and you get the fire!',
|
||||
args: [
|
||||
{
|
||||
key: 'door',
|
||||
prompt: 'Which door number do you want to pick? A number from 1-3.',
|
||||
type: 'integer',
|
||||
min: 1,
|
||||
max: 3
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { door }) {
|
||||
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.`);
|
||||
this.client.games.set(msg.channel.id, { name: this.name });
|
||||
try {
|
||||
const win = doors[Math.floor(Math.random() * doors.length)];
|
||||
const noWin = doors.filter(thisDoor => thisDoor !== win && door !== thisDoor)[0];
|
||||
await msg.reply(stripIndents`
|
||||
Well, there's nothing behind door number **${noWin}**. Do you want to stick with door ${door}?
|
||||
${this.emoji(1, noWin)} ${this.emoji(2, noWin)} ${this.emoji(3, noWin)}
|
||||
`);
|
||||
const stick = await verify(msg.channel, msg.author);
|
||||
if (!stick) door = doors.filter(thisDoor => door !== thisDoor && thisDoor !== noWin)[0];
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.reply(stripIndents`
|
||||
${door === win ? 'You chose wisely.' : 'Hmm... Try again.'}
|
||||
${this.emoji(1, noWin, win, door)} ${this.emoji(2, noWin, win, door)} ${this.emoji(3, noWin, win, door)}
|
||||
`);
|
||||
} catch (err) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
emoji(door, noWin, win, chosen) {
|
||||
return door === win && chosen === win ? '💰' : door === noWin ? '🔥' : door === chosen ? '🔥' : '🚪';
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { randomRange } = require('../../util/Util');
|
||||
const fishes = require('../../assets/json/fishy');
|
||||
|
||||
module.exports = class FishyCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'fishy',
|
||||
aliases: ['fishing'],
|
||||
group: 'sp-games',
|
||||
memberName: 'fishy',
|
||||
description: 'Go fishing.'
|
||||
});
|
||||
}
|
||||
|
||||
run(msg) {
|
||||
const fishID = Math.floor(Math.random() * 10) + 1;
|
||||
let rarity;
|
||||
if (fishID < 5) rarity = 'junk';
|
||||
else if (fishID < 8) rarity = 'common';
|
||||
else if (fishID < 10) rarity = 'uncommon';
|
||||
else rarity = 'rare';
|
||||
const fish = fishes[rarity];
|
||||
const worth = randomRange(fish.min, fish.max);
|
||||
return msg.reply(`You caught a ${fish.symbol}. I bet it'd sell for around $${worth}.`);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
const { MessageEmbed } = require('discord.js');
|
||||
const questions = require('../../assets/json/google-feud');
|
||||
|
||||
module.exports = class GoogleFeudCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'google-feud',
|
||||
group: 'sp-games',
|
||||
memberName: 'google-feud',
|
||||
description: 'Attempt to determine the top suggestions for a Google search.',
|
||||
credit: [
|
||||
{
|
||||
name: 'Google Feud',
|
||||
url: 'http://www.googlefeud.com/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'question',
|
||||
prompt: 'What question do you want to use for the game?',
|
||||
type: 'string',
|
||||
default: () => questions[Math.floor(Math.random() * questions.length)]
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { question }) {
|
||||
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.`);
|
||||
this.client.games.set(msg.channel.id, { name: this.name });
|
||||
try {
|
||||
const suggestions = await this.fetchSuggestions(question);
|
||||
if (!suggestions) return msg.say('Could not find any results.');
|
||||
const display = new Array(suggestions.length).fill('???');
|
||||
let tries = 3;
|
||||
while (display.includes('???') && tries) {
|
||||
const embed = new MessageEmbed()
|
||||
.setColor(0x005AF0)
|
||||
.setTitle(`${question}...?`)
|
||||
.setDescription('Type the choice you think is a suggestion _without_ the question.')
|
||||
.setFooter(`${tries} ${tries === 1 ? 'try' : 'tries'} remaining!`);
|
||||
for (let i = 0; i < suggestions.length; i++) embed.addField(`❯ ${10000 - (i * 1000)}`, display[i], true);
|
||||
await msg.embed(embed);
|
||||
const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, {
|
||||
max: 1,
|
||||
time: 30000
|
||||
});
|
||||
if (!msgs.size) {
|
||||
await msg.say('Time is up!');
|
||||
break;
|
||||
}
|
||||
const choice = msgs.first().content.toLowerCase();
|
||||
if (suggestions.includes(choice)) display[suggestions.indexOf(choice)] = choice;
|
||||
else --tries;
|
||||
}
|
||||
this.client.games.delete(msg.channel.id);
|
||||
if (!display.includes('???')) return msg.say('You win! Nice job, master of Google!');
|
||||
return msg.say('Better luck next time!');
|
||||
} catch (err) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
|
||||
async fetchSuggestions(question) {
|
||||
const { text } = await request
|
||||
.get('https://suggestqueries.google.com/complete/search')
|
||||
.query({
|
||||
client: 'firefox',
|
||||
q: question
|
||||
});
|
||||
const suggestions = JSON.parse(text)[1]
|
||||
.filter(suggestion => suggestion.toLowerCase() !== question.toLowerCase());
|
||||
if (!suggestions.length) return null;
|
||||
return suggestions.map(suggestion => suggestion.toLowerCase().replace(question.toLowerCase(), '').trim());
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const words = require('../../assets/json/word-list');
|
||||
|
||||
module.exports = class HangmanCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'hangman',
|
||||
group: 'sp-games',
|
||||
memberName: 'hangman',
|
||||
description: 'Prevent a man from being hanged by guessing a word as fast as you can.',
|
||||
credit: [
|
||||
{
|
||||
name: 'Moby Word Lists by Grady Ward',
|
||||
url: 'http://www.gutenberg.org/ebooks/3201'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg) { // eslint-disable-line complexity
|
||||
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.`);
|
||||
this.client.games.set(msg.channel.id, { name: this.name });
|
||||
try {
|
||||
const word = words[Math.floor(Math.random() * words.length)].toLowerCase();
|
||||
let points = 0;
|
||||
let displayText = null;
|
||||
let guessed = false;
|
||||
const confirmation = [];
|
||||
const incorrect = [];
|
||||
const display = new Array(word.length).fill('_');
|
||||
while (word.length !== confirmation.length && points < 6) {
|
||||
await msg.say(stripIndents`
|
||||
${displayText === null ? 'Here we go!' : displayText ? 'Good job!' : 'Nope!'}
|
||||
\`${display.join(' ')}\`. Which letter do you choose?
|
||||
Incorrect Tries: ${incorrect.join(', ') || 'None'}
|
||||
\`\`\`
|
||||
___________
|
||||
| |
|
||||
| ${points > 0 ? 'O' : ''}
|
||||
| ${points > 2 ? '—' : ' '}${points > 1 ? '|' : ''}${points > 3 ? '—' : ''}
|
||||
| ${points > 4 ? '/' : ''} ${points > 5 ? '\\' : ''}
|
||||
===========
|
||||
\`\`\`
|
||||
`);
|
||||
const filter = res => {
|
||||
const choice = res.content.toLowerCase();
|
||||
return res.author.id === msg.author.id && !confirmation.includes(choice) && !incorrect.includes(choice);
|
||||
};
|
||||
const guess = await msg.channel.awaitMessages(filter, {
|
||||
max: 1,
|
||||
time: 30000
|
||||
});
|
||||
if (!guess.size) {
|
||||
await msg.say('Sorry, time is up!');
|
||||
break;
|
||||
}
|
||||
const choice = guess.first().content.toLowerCase();
|
||||
if (choice === 'end') break;
|
||||
if (choice.length > 1 && choice === word) {
|
||||
guessed = true;
|
||||
break;
|
||||
} else if (word.includes(choice)) {
|
||||
displayText = true;
|
||||
for (let i = 0; i < word.length; i++) {
|
||||
if (word.charAt(i) !== choice) continue; // eslint-disable-line max-depth
|
||||
confirmation.push(word.charAt(i));
|
||||
display[i] = word.charAt(i);
|
||||
}
|
||||
} else {
|
||||
displayText = false;
|
||||
if (choice.length === 1) incorrect.push(choice);
|
||||
points++;
|
||||
}
|
||||
}
|
||||
this.client.games.delete(msg.channel.id);
|
||||
if (word.length === confirmation.length || guessed) return msg.say(`You won, it was ${word}!`);
|
||||
return msg.say(`Too bad... It was ${word}...`);
|
||||
} catch (err) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { shuffle, verify } = require('../../util/Util');
|
||||
const events = require('../../assets/json/hunger-games');
|
||||
|
||||
module.exports = class HungerGamesCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'hunger-games',
|
||||
aliases: ['hunger-games-simulator', 'hunger-games-sim'],
|
||||
group: 'sp-games',
|
||||
memberName: 'hunger-games',
|
||||
description: 'Simulate a Hunger Games match with up to 24 tributes.',
|
||||
credit: [
|
||||
{
|
||||
name: 'BrantSteele Hunger Games Simulator',
|
||||
url: 'http://brantsteele.net/hungergames/reaping.php'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'tributes',
|
||||
prompt: 'Who should compete in the games? Up to 24 tributes can participate.',
|
||||
type: 'string',
|
||||
infinite: true,
|
||||
max: 20
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { tributes }) {
|
||||
if (tributes.length < 2) return msg.say(`...${tributes[0]} wins, as they were the only tribute.`);
|
||||
if (tributes.length > 24) return msg.reply('Please do not enter more than 24 tributes.');
|
||||
if (new Set(tributes).size !== tributes.length) return msg.reply('Please do not enter the same tribute twice.');
|
||||
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.`);
|
||||
this.client.games.set(msg.channel.id, { name: this.name });
|
||||
try {
|
||||
let sun = true;
|
||||
let turn = 0;
|
||||
let bloodbath = true;
|
||||
const remaining = new Set(shuffle(tributes));
|
||||
while (remaining.size > 1) {
|
||||
if (!bloodbath && sun) ++turn;
|
||||
const sunEvents = bloodbath ? events.bloodbath : sun ? events.day : events.night;
|
||||
const results = [];
|
||||
const deaths = [];
|
||||
this.makeEvents(remaining, sunEvents, deaths, results);
|
||||
let text = stripIndents`
|
||||
__**${bloodbath ? 'Bloodbath' : sun ? `Day ${turn}` : `Night ${turn}`}:**__
|
||||
${results.join('\n')}
|
||||
`;
|
||||
if (deaths.length) {
|
||||
text += '\n\n';
|
||||
text += stripIndents`
|
||||
**${deaths.length} cannon shot${deaths.length === 1 ? '' : 's'} can be heard in the distance.**
|
||||
${deaths.join('\n')}
|
||||
`;
|
||||
}
|
||||
text += `\n\n_Proceed?_`;
|
||||
await msg.say(text);
|
||||
const verification = await verify(msg.channel, msg.author, 120000);
|
||||
if (!verification) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.say('See you next time!');
|
||||
}
|
||||
if (!bloodbath) sun = !sun;
|
||||
if (bloodbath) bloodbath = false;
|
||||
}
|
||||
this.client.games.delete(msg.channel.id);
|
||||
const remainingArr = Array.from(remaining);
|
||||
return msg.say(`And the winner is... ${remainingArr[0]}!`);
|
||||
} catch (err) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
parseEvent(event, tributes) {
|
||||
return event
|
||||
.replace(/\(Player1\)/gi, `**${tributes[0]}**`)
|
||||
.replace(/\(Player2\)/gi, `**${tributes[1]}**`)
|
||||
.replace(/\(Player3\)/gi, `**${tributes[2]}**`)
|
||||
.replace(/\(Player4\)/gi, `**${tributes[3]}**`)
|
||||
.replace(/\(Player5\)/gi, `**${tributes[4]}**`)
|
||||
.replace(/\(Player6\)/gi, `**${tributes[5]}**`);
|
||||
}
|
||||
|
||||
makeEvents(tributes, eventsArr, deaths, results) {
|
||||
const turn = new Set(tributes);
|
||||
for (const tribute of tributes) {
|
||||
if (!turn.has(tribute)) continue;
|
||||
const valid = eventsArr.filter(event => event.tributes <= turn.size && event.deaths < turn.size);
|
||||
const event = valid[Math.floor(Math.random() * valid.length)];
|
||||
turn.delete(tribute);
|
||||
if (event.tributes === 1) {
|
||||
if (event.deaths.length === 1) {
|
||||
deaths.push(tribute);
|
||||
tributes.delete(tribute);
|
||||
}
|
||||
results.push(this.parseEvent(event.text, [tribute]));
|
||||
} else {
|
||||
const current = [tribute];
|
||||
if (event.deaths.includes(1)) {
|
||||
deaths.push(tribute);
|
||||
tributes.delete(tribute);
|
||||
}
|
||||
for (let i = 2; i <= event.tributes; i++) {
|
||||
const turnArr = Array.from(turn);
|
||||
const tribu = turnArr[Math.floor(Math.random() * turnArr.length)];
|
||||
if (event.deaths.includes(i)) {
|
||||
deaths.push(tribu);
|
||||
tributes.delete(tribu);
|
||||
}
|
||||
current.push(tribu);
|
||||
turn.delete(tribu);
|
||||
}
|
||||
results.push(this.parseEvent(event.text, current));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const prizes = ['$0', '$2', '$4', '$10', '$500', '$1,000,000', 'the Jackpot'];
|
||||
|
||||
module.exports = class LotteryCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'lottery',
|
||||
aliases: ['lotto'],
|
||||
group: 'sp-games',
|
||||
memberName: 'lottery',
|
||||
description: 'Attempt to win the lottery with 6 numbers.',
|
||||
args: [
|
||||
{
|
||||
key: 'choices',
|
||||
prompt: 'What numbers do you choose? Only the first six will be counted.',
|
||||
type: 'integer',
|
||||
infinite: true,
|
||||
max: 70,
|
||||
min: 1
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
run(msg, { choices }) {
|
||||
const lotto = Array.from({ length: 6 }, () => Math.floor(Math.random() * 70) + 1);
|
||||
const similarities = lotto.filter((num, i) => choices[i] === num).length;
|
||||
return msg.reply(stripIndents`
|
||||
${lotto.join(', ')}
|
||||
You matched **${similarities}** numbers, which gives you **${prizes[similarities]}**! Congrats!
|
||||
`);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { list } = require('../../util/Util');
|
||||
const difficulties = ['easy', 'medium', 'hard', 'extreme', 'impossible'];
|
||||
const operations = ['+', '-', '*'];
|
||||
const maxValues = {
|
||||
easy: 10,
|
||||
medium: 100,
|
||||
hard: 500,
|
||||
extreme: 1000,
|
||||
impossible: Number.MAX_SAFE_INTEGER
|
||||
};
|
||||
|
||||
module.exports = class MathQuizCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'math-quiz',
|
||||
group: 'sp-games',
|
||||
memberName: 'math-quiz',
|
||||
description: 'See how fast you can answer a math problem in a given time limit.',
|
||||
details: `**Difficulties:** ${difficulties.join(', ')}`,
|
||||
args: [
|
||||
{
|
||||
key: 'difficulty',
|
||||
prompt: `What should the difficulty of the game be? Either ${list(difficulties, 'or')}.`,
|
||||
type: 'string',
|
||||
oneOf: difficulties,
|
||||
parse: difficulty => difficulty.toLowerCase()
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { difficulty }) {
|
||||
const value1 = Math.floor(Math.random() * maxValues[difficulty]) + 1;
|
||||
const value2 = Math.floor(Math.random() * maxValues[difficulty]) + 1;
|
||||
const operation = operations[Math.floor(Math.random() * operations.length)];
|
||||
let answer;
|
||||
switch (operation) {
|
||||
case '+': answer = value1 + value2; break;
|
||||
case '-': answer = value1 - value2; break;
|
||||
case '*': answer = value1 * value2; break;
|
||||
}
|
||||
await msg.reply(stripIndents`
|
||||
**You have 10 seconds to answer this question.**
|
||||
${value1} ${operation} ${value2}
|
||||
`);
|
||||
const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, {
|
||||
max: 1,
|
||||
time: 10000
|
||||
});
|
||||
if (!msgs.size) return msg.reply(`Sorry, time is up! It was ${answer}.`);
|
||||
if (msgs.first().content !== answer.toString()) return msg.reply(`Nope, sorry, it's ${answer}.`);
|
||||
return msg.reply('Nice job! 10/10! You deserve some cake!');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const request = require('node-superfetch');
|
||||
const { shuffle, list } = require('../../util/Util');
|
||||
const types = ['multiple', 'boolean'];
|
||||
const difficulties = ['easy', 'medium', 'hard'];
|
||||
const choices = ['A', 'B', 'C', 'D'];
|
||||
|
||||
module.exports = class QuizCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'quiz',
|
||||
aliases: ['trivia'],
|
||||
group: 'sp-games',
|
||||
memberName: 'quiz',
|
||||
description: 'Answer a quiz question.',
|
||||
details: stripIndents`
|
||||
**Types:** ${types.join(', ')}
|
||||
**Difficulties:** ${difficulties.join(', ')}
|
||||
`,
|
||||
credit: [
|
||||
{
|
||||
name: 'Open Trivia DB',
|
||||
url: 'https://opentdb.com/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'type',
|
||||
prompt: `Which type of question would you like to have? Either ${list(types, 'or')}.`,
|
||||
type: 'string',
|
||||
default: 'multiple',
|
||||
oneOf: types,
|
||||
parse: type => type.toLowerCase()
|
||||
},
|
||||
{
|
||||
key: 'difficulty',
|
||||
prompt: `What should the difficulty of the game be? Either ${list(difficulties, 'or')}.`,
|
||||
type: 'string',
|
||||
default: '',
|
||||
oneOf: difficulties,
|
||||
parse: difficulty => difficulty.toLowerCase()
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { type, difficulty }) {
|
||||
try {
|
||||
const { body } = await request
|
||||
.get('https://opentdb.com/api.php')
|
||||
.query({
|
||||
amount: 1,
|
||||
type,
|
||||
encode: 'url3986',
|
||||
difficulty
|
||||
});
|
||||
if (!body.results) return msg.reply('Oh no, a question could not be fetched. Try again later!');
|
||||
const answers = body.results[0].incorrect_answers.map(answer => decodeURIComponent(answer.toLowerCase()));
|
||||
const correct = decodeURIComponent(body.results[0].correct_answer.toLowerCase());
|
||||
answers.push(correct);
|
||||
const shuffled = shuffle(answers);
|
||||
await msg.reply(stripIndents`
|
||||
**You have 15 seconds to answer this question.**
|
||||
${decodeURIComponent(body.results[0].question)}
|
||||
${shuffled.map((answer, i) => `**${choices[i]}.** ${answer}`).join('\n')}
|
||||
`);
|
||||
const filter = res => res.author.id === msg.author.id && choices.includes(res.content.toUpperCase());
|
||||
const msgs = await msg.channel.awaitMessages(filter, {
|
||||
max: 1,
|
||||
time: 15000
|
||||
});
|
||||
if (!msgs.size) return msg.reply(`Sorry, time is up! It was ${correct}.`);
|
||||
const win = shuffled[choices.indexOf(msgs.first().content.toUpperCase())] === correct;
|
||||
if (!win) return msg.reply(`Nope, sorry, it's ${correct}.`);
|
||||
return msg.reply('Nice job! 10/10! You deserve some cake!');
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const choices = ['rock', 'paper', 'scissors'];
|
||||
|
||||
module.exports = class RockPaperScissorsCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'rock-paper-scissors',
|
||||
aliases: ['rps'],
|
||||
group: 'sp-games',
|
||||
memberName: 'rock-paper-scissors',
|
||||
description: 'Play Rock-Paper-Scissors.',
|
||||
args: [
|
||||
{
|
||||
key: 'choice',
|
||||
prompt: 'Rock, Paper, or Scissors?',
|
||||
type: 'string',
|
||||
parse: choice => choice.toLowerCase()
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
run(msg, { choice }) {
|
||||
const response = choices[Math.floor(Math.random() * choices.length)];
|
||||
if (choice === 'rock') {
|
||||
if (response === 'rock') return msg.reply('Rock! Aw... A tie...');
|
||||
if (response === 'paper') return msg.reply('Paper! Yes! I win!');
|
||||
if (response === 'scissors') return msg.reply('Scissors! Aw... I lose...');
|
||||
}
|
||||
if (choice === 'paper') {
|
||||
if (response === 'rock') return msg.reply('Rock! Aw... I lose...');
|
||||
if (response === 'paper') return msg.reply('Paper! Aw... A tie...');
|
||||
if (response === 'scissors') return msg.reply('Scissors! Yes! I win!');
|
||||
}
|
||||
if (choice === 'scissors') {
|
||||
if (response === 'rock') return msg.reply('Rock! Yes! I win!');
|
||||
if (response === 'paper') return msg.reply('Paper! Aw... I lose...');
|
||||
if (response === 'scissors') return msg.reply('Scissors! Aw... A tie...');
|
||||
}
|
||||
return msg.reply('I win by default, you little cheater.');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { oneLine } = require('common-tags');
|
||||
const red = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];
|
||||
const black = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35];
|
||||
const numbers = [0].concat(red, black);
|
||||
const dozens = ['1-12', '13-24', '25-36'];
|
||||
const halves = ['1-18', '19-36'];
|
||||
const columns = ['1st', '2nd', '3rd'];
|
||||
const parity = ['even', 'odd'];
|
||||
const colors = ['red', 'black'];
|
||||
|
||||
module.exports = class RouletteCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'roulette',
|
||||
group: 'sp-games',
|
||||
memberName: 'roulette',
|
||||
description: 'Play a game of roulette.',
|
||||
args: [
|
||||
{
|
||||
key: 'space',
|
||||
prompt: 'What space do you want to bet on?',
|
||||
type: 'string',
|
||||
validate: space => {
|
||||
if (numbers.includes(Number.parseInt(space, 10))) return true;
|
||||
if (dozens.includes(space)) return true;
|
||||
if (halves.includes(space)) return true;
|
||||
if (columns.includes(space.toLowerCase())) return true;
|
||||
if (parity.includes(space.toLowerCase())) return true;
|
||||
if (colors.includes(space.toLowerCase())) return true;
|
||||
return oneLine`
|
||||
Invalid space, please enter either a specific number from 0-36, a range of dozens (e.g. 1-12), a range of
|
||||
halves (e.g. 1-18), a column (e.g. 1st), a color (e.g. black), or a parity (e.g. even).
|
||||
`;
|
||||
},
|
||||
parse: space => space.toLowerCase()
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
run(msg, { space }) {
|
||||
const number = Math.floor(Math.random() * 37);
|
||||
const color = number ? red.includes(number) ? 'RED' : 'BLACK' : null;
|
||||
const win = this.verifyWin(space, number);
|
||||
return msg.reply(`The result is **${number}${color ? ` ${color}` : ''}**. ${win ? 'You win!' : 'You lose...'}`);
|
||||
}
|
||||
|
||||
verifyWin(choice, result) {
|
||||
if (dozens.includes(choice) || halves.includes(choice)) {
|
||||
const range = choice.split('-');
|
||||
return result >= range[0] && range[1] >= result;
|
||||
}
|
||||
if (colors.includes(choice)) {
|
||||
if (choice === 'black') return black.includes(result);
|
||||
if (choice === 'red') return red.includes(result);
|
||||
}
|
||||
if (parity.includes(choice)) return parity[result % 2] === choice;
|
||||
if (columns.includes(choice)) return columns[(result - 1) % 3] === choice;
|
||||
const number = Number.parseInt(choice, 10);
|
||||
if (numbers.includes(number)) return result === number;
|
||||
if (!result) return false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const slots = ['🍇', '🍊', '🍐', '🍒', '🍋'];
|
||||
|
||||
module.exports = class SlotsCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'slots',
|
||||
group: 'sp-games',
|
||||
memberName: 'slots',
|
||||
description: 'Play a game of slots.'
|
||||
});
|
||||
}
|
||||
|
||||
run(msg) {
|
||||
const slotOne = slots[Math.floor(Math.random() * slots.length)];
|
||||
const slotTwo = slots[Math.floor(Math.random() * slots.length)];
|
||||
const slotThree = slots[Math.floor(Math.random() * slots.length)];
|
||||
if (slotOne === slotTwo && slotOne === slotThree) {
|
||||
return msg.reply(stripIndents`
|
||||
${slotOne}|${slotTwo}|${slotThree}
|
||||
Wow! You won! Great job... er... luck!
|
||||
`);
|
||||
}
|
||||
return msg.reply(stripIndents`
|
||||
${slotOne}|${slotTwo}|${slotThree}
|
||||
Aww... You lost... Guess it's just bad luck, huh?
|
||||
`);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { shuffle } = require('../../util/Util');
|
||||
const { questions, houses, descriptions } = require('../../assets/json/sorting-hat');
|
||||
const choices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'];
|
||||
|
||||
module.exports = class SortingHatCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'sorting-hat',
|
||||
aliases: ['sorting-hat-quiz', 'hogwarts', 'hogwarts-house'],
|
||||
group: 'sp-games',
|
||||
memberName: 'sorting-hat',
|
||||
description: 'Take a quiz to determine your Hogwarts house.',
|
||||
credit: [
|
||||
{
|
||||
name: 'Pottermore',
|
||||
url: 'https://my.pottermore.com/sorting'
|
||||
},
|
||||
{
|
||||
name: 'Pottermore Sorting Hat Quiz analysis by u/N1ffler',
|
||||
url: 'https://www.reddit.com/r/Pottermore/comments/44os14/pottermore_sorting_hat_quiz_analysis/'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
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.`);
|
||||
this.client.games.set(msg.channel.id, { name: this.name });
|
||||
try {
|
||||
const points = {
|
||||
g: 0,
|
||||
s: 0,
|
||||
h: 0,
|
||||
r: 0
|
||||
};
|
||||
const blacklist = [];
|
||||
const questionNums = ['2', '3', '4', '5', '6', '7'];
|
||||
let turn = 1;
|
||||
while (turn < 9) {
|
||||
let question;
|
||||
if (turn === 1) {
|
||||
question = questions.first[Math.floor(Math.random() * questions.first.length)];
|
||||
} else if (turn === 8) {
|
||||
question = questions.last[Math.floor(Math.random() * questions.last.length)];
|
||||
} else {
|
||||
const possible = questionNums.filter(num => !blacklist.includes(num));
|
||||
const value = possible[Math.floor(Math.random() * possible.length)];
|
||||
const group = questions[value];
|
||||
blacklist.push(value);
|
||||
question = group[Math.floor(Math.random() * group.length)];
|
||||
}
|
||||
const answers = shuffle(question.answers);
|
||||
await msg.say(stripIndents`
|
||||
**${turn}.** ${question.text}
|
||||
${answers.map((answer, i) => `- **${choices[i]}.** ${answer.text}`).join('\n')}
|
||||
`);
|
||||
const filter = res =>
|
||||
res.author.id === msg.author.id && choices.slice(0, answers.length).includes(res.content.toUpperCase());
|
||||
const choice = await msg.channel.awaitMessages(filter, {
|
||||
max: 1,
|
||||
time: 120000
|
||||
});
|
||||
if (!choice.size) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
return msg.say('Oh no, you ran out of time! Too bad.');
|
||||
}
|
||||
const answer = answers[choices.indexOf(choice.first().content.toUpperCase())];
|
||||
for (const [house, amount] of Object.entries(answer.points)) points[house] += amount;
|
||||
++turn;
|
||||
}
|
||||
const houseResult = Object.keys(points).filter(h => points[h] > 0).sort((a, b) => points[b] - points[a]);
|
||||
this.client.games.delete(msg.channel.id);
|
||||
const totalPoints = houseResult.reduce((a, b) => a + points[b], 0);
|
||||
return msg.say(stripIndents`
|
||||
You are a member of... **${houses[houseResult[0]]}**!
|
||||
_${descriptions[houseResult[0]]}_
|
||||
|
||||
${houseResult.map(house => `${houses[house]}: ${Math.round((points[house] / totalPoints) * 100)}%`).join('\n')}
|
||||
`);
|
||||
} catch (err) {
|
||||
this.client.games.delete(msg.channel.id);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { list } = require('../../util/Util');
|
||||
const sentences = require('../../assets/json/typing-test');
|
||||
const difficulties = ['easy', 'medium', 'hard', 'extreme', 'impossible'];
|
||||
const times = {
|
||||
easy: 25000,
|
||||
medium: 20000,
|
||||
hard: 15000,
|
||||
extreme: 10000,
|
||||
impossible: 5000
|
||||
};
|
||||
|
||||
module.exports = class TypingTestCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'typing-test',
|
||||
group: 'sp-games',
|
||||
memberName: 'typing-test',
|
||||
description: 'See how fast you can type a sentence in a given time limit.',
|
||||
details: `**Difficulties:** ${difficulties.join(', ')}`,
|
||||
args: [
|
||||
{
|
||||
key: 'difficulty',
|
||||
prompt: `What should the difficulty of the game be? Either ${list(difficulties, 'or')}.`,
|
||||
type: 'string',
|
||||
oneOf: difficulties,
|
||||
parse: difficulty => difficulty.toLowerCase()
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { difficulty }) {
|
||||
const sentence = sentences[Math.floor(Math.random() * sentences.length)];
|
||||
const time = times[difficulty];
|
||||
await msg.reply(stripIndents`
|
||||
**You have ${time / 1000} seconds to type this sentence.**
|
||||
${sentence}
|
||||
`);
|
||||
const now = Date.now();
|
||||
const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, {
|
||||
max: 1,
|
||||
time
|
||||
});
|
||||
if (!msgs.size || msgs.first().content !== sentence) return msg.reply('Sorry! You lose!');
|
||||
return msg.reply(`Nice job! 10/10! You deserve some cake! (Took ${(Date.now() - now) / 1000} seconds)`);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { createCanvas, loadImage } = require('canvas');
|
||||
const request = require('node-superfetch');
|
||||
const { silhouette } = require('../../util/Canvas');
|
||||
|
||||
module.exports = class WhosThatPokemonCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'whos-that-pokemon',
|
||||
aliases: ['who-pokemon', 'whos-that-pokémon', 'who-pokémon'],
|
||||
group: 'sp-games',
|
||||
memberName: 'whos-that-pokemon',
|
||||
description: 'Guess who that Pokémon is.',
|
||||
throttling: {
|
||||
usages: 1,
|
||||
duration: 10
|
||||
},
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Pokémon',
|
||||
url: 'https://www.pokemon.com/us/'
|
||||
},
|
||||
{
|
||||
name: 'PokéAPI',
|
||||
url: 'https://pokeapi.co/'
|
||||
},
|
||||
{
|
||||
name: 'Serebii.net',
|
||||
url: 'https://www.serebii.net/index2.shtml'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'hide',
|
||||
prompt: 'Do you want to silhouette the Pokémon\'s image?',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { hide }) {
|
||||
const pokemon = Math.floor(Math.random() * 802) + 1;
|
||||
try {
|
||||
const data = await this.client.pokemon.fetch(pokemon.toString());
|
||||
const names = data.names.map(name => name.name.toLowerCase());
|
||||
const attachment = await this.fetchImage(data, hide);
|
||||
await msg.reply('**You have 15 seconds, who\'s that Pokémon?**', { files: [attachment] });
|
||||
const msgs = await msg.channel.awaitMessages(res => res.author.id === msg.author.id, {
|
||||
max: 1,
|
||||
time: 15000
|
||||
});
|
||||
if (!msgs.size) return msg.reply(`Sorry, time is up! It was ${data.name}.`);
|
||||
if (!names.includes(msgs.first().content.toLowerCase())) return msg.reply(`Nope, sorry, it's ${data.name}.`);
|
||||
return msg.reply('Nice job! 10/10! You deserve some cake!');
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
|
||||
async fetchImage(pokemon, hide = false) {
|
||||
const name = `${pokemon.id}.png`;
|
||||
const image = await request.get(pokemon.spriteImageURL);
|
||||
if (!hide) return { attachment: image.body, name };
|
||||
const base = await loadImage(image.body);
|
||||
const canvas = createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(base, 0, 0);
|
||||
silhouette(ctx, 0, 0, base.width, base.height);
|
||||
return { attachment: canvas.toBuffer(), name };
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user