discord-mini-games-es.js
Version:
Un paquete para implementar minijuegos usando discord.js-v14 en español
161 lines (159 loc) • 7.09 kB
JavaScript
const discord = require('discord.js');
const {createCanvas,registerFont} = require('canvas')
const words = require('./assets/words.json').words
registerFont(__dirname+'/assets/Roboto-Medium.ttf', {family:'Roboto'})
class Wordle{
/**
* Initialises a new instance of Wordle Game.
* @param {`Message/Interaction`} message The Message object.
* @param {`GameOptions-Object`} gameOptions The game Options Object.
* @returns {Wordle} Game instance.
*/
constructor(message,gameOptions) {
if(!message) throw new Error("no se proporciono el mensaje");
this.message = message;
if(gameOptions && typeof gameOptions !== 'object') throw new TypeError("gameOptions debe de ser un Objeto");
this.isSlash = gameOptions?.isSlash ?? false;
if(this.isSlash == true){
if(!(this.message instanceof discord.CommandInteraction)){
throw new TypeError("message debe ser una instancia de Command Interaction")
} } else {
if(!(this.message instanceof discord.Message)) {
throw new TypeError("message debe ser una instancia de Discord Message")
}
}
this.player = this.isSlash == true ? this.message?.user : this.message?.author;
this.time = gameOptions?.time ?? 180000;
this.replied = false;
this.randomN = (min,max) => {return Math.floor(Math.random()*max)+min;}
this.edit = async (messageOptions,replyMessage) => {
messageOptions.fetchReply = true;
if(this.replied == false) {
this.replied=true;
if(this.isSlash == true) return await replyMessage.editReply(messageOptions)
return await this.message.reply(messageOptions);}
else return await replyMessage.edit(messageOptions)
}
this.word = words[this.randomN(0,words.length)]
this.options = gameOptions;
this.onWin = gameOptions?.onWin ?? null;
this.onLose = gameOptions?.onLose ?? null;
this.onTimeUp = gameOptions?.onTimeUp ?? null;
if(this.onWin && typeof this.onWin !== 'function') throw new TypeError('onWin debe de ser una Función');
if(this.onLose && typeof this.onLose !== 'function') throw new TypeError('onLose debe de ser una Función');
if(this.onTimeUp && typeof this.onTimeUp !== 'function') throw new TypeError('onTimeUp debe de ser una Función');
if(typeof this.isSlash !== 'boolean') throw new TypeError('isSlash debe de ser Boolean');
if(typeof this.time !== 'number') throw new TypeError('time debe de ser un Número');
if(this.time < 5000) throw new RangeError('time debe de ser mayor que 5000');
if(this.options?.title && typeof this.options?.title !== 'string') throw new TypeError('title debe de ser un string');
if(this.options?.startDes && typeof this.options?.startDes !== 'string') throw new TypeError('startDes debe de ser un string');
if(this.options?.winDes && typeof this.options?.winDes !== 'string') throw new TypeError('winDes debe de ser un string');
if(this.options?.loseDes && typeof this.options?.loseDes !== 'string') throw new TypeError('loseDes debe de ser un string');
if(this.options?.timeUpDes && typeof this.options?.timeUpDes !== 'string') throw new TypeError('timeUpDes debe de ser un string');
}
/**
* Starts The Game.
*/
async run() {
if(this.isSlash == true) {
await this.message.deferReply().catch(() => {});
}
const canvas = createCanvas(300,300);
const context = canvas.getContext('2d');
context.fillStyle ='#7d7c78'
context.fillRect(1,1,canvas.width -1,canvas.height-1)
const gridSize = 60;
const gridColor = '#000000';
context.strokeStyle = gridColor;
context.lineWidth = 2;
for (let x = 0; x <= canvas.width; x += gridSize) {
context.beginPath();
context.moveTo(x, 0);
context.lineTo(x, canvas.height);
context.stroke();
}
for (let y = 0; y <= canvas.height; y += gridSize) {
context.beginPath();
context.moveTo(0, y);
context.lineTo(canvas.width, y);
context.stroke();
}
function drawLetter(letter, color,xGrid, yGrid) {
const colors = {'red':"#fa5c43",'lime':"#03fc0b",'yellow':"#f5d72f"}
context.fillStyle = colors[color]
context.fillRect(xGrid * gridSize + 1, yGrid * gridSize + 1, gridSize - 2, gridSize - 2)
context.font = '60px Roboto';
context.fillStyle = 'black';
const x = xGrid * gridSize + (gridSize - context.measureText(letter).width) / 2;
const y = (yGrid * gridSize + gridSize / 2 + 60 / 2) -5;
context.fillText(letter, x, y);
}
function drawAndVerifyWord(word,newWord,chance) {
const wordLetters = word.toUpperCase().split("")
const newWordLetters = newWord.toUpperCase().split("")
let correctLetters = 0;
newWordLetters.forEach((l,i) => {
if(l == wordLetters[i]) {
correctLetters++
drawLetter(l,"lime",i,chance)
}
else {
if(wordLetters.includes(l)) {
drawLetter(l,"yellow",i,chance)
}
else {
drawLetter(l,"red",i,chance)
}
}
})
if(correctLetters == wordLetters.length) return "win";
else return "lose";
}
let chance = 0,played =false;
const game = this;
function wordEmbed(canvas,color,des) {
const image = new discord.AttachmentBuilder().setFile(canvas.toBuffer()).setName('wordle.png')
const embed = new discord.EmbedBuilder()
.setColor(color)
.setThumbnail(game.player.avatarURL())
.setTimestamp()
.setFooter({text:`Pedido por ${game.player.username}`})
.setTitle(game.options?.title ?? "Wordle")
.setImage("attachment://wordle.png")
if(des) embed.setDescription(des)
return {embeds:[embed],files:[image] };
}
const msg = await this.edit(wordEmbed(canvas,"Yellow",this.options?.startDes ?? 'Adivina la palabra de 5 letras en la que estoy pensando'),this.message)
const filter = m => m.author.id == this.player.id && m.content.length == 5 && /^[a-zA-Z]+$/.test(m.content);
const collector = this.message.channel.createMessageCollector({filter:filter,idle:this.time,max:5})
collector.on('collect', async m => {
const attempt = m.content;
const result = drawAndVerifyWord(this.word,attempt,chance)
m.delete().catch((e) => null)
if(result == "win") {
played = true;
collector.stop()
await this.edit(wordEmbed(canvas,"Green",this.options?.winDes?.replace(/{word}/g,this.word) ?? "¡Has ganado!"),msg);
if(this.onWin) await this.onWin();
}
else {
chance++
if(chance == 5) {
played = true;
await this.edit(wordEmbed(canvas,"Red",this.options?.loseDes?.replace(/{word}/g,this.word) ?? "¡Perdiste!, la Palabra era "+this.word),msg)
if(this.onLose) await this.onLose();
}
else {
await this.edit(wordEmbed(canvas,"Red"),msg)
}
}
})
collector.on('end', async () => {
if(played == false) {
await this.edit(wordEmbed(canvas,'Red',this.options?.timeUpDes?.replace(/{word}/g,this.word) ?? 'Game Over: ¡Se acabó el tiempo!, era ' + this.word),msg)
if(this.onTimeUp) await this.onTimeUp();
}
})
}
}
module.exports = Wordle;