I'm trying to do a Purchase command with mongoose, but apparently it's getting this TypeError error: cardPack.purchase is not a function I'm using discord.js, discord.js-commando, and Mongoose.
The command has to get cardPackSchema.methods.purchase
in my Schema, and use the function, but it is not working properly.
My Command:
const { Command } = require('discord.js-commando');
const { MessageEmbed } = require('discord.js');
const mongoose = require('mongoose');
const Fuse = require('fuse.js');
const Profile = mongoose.model('Profile');
const CardPack = mongoose.model('CardPack');
module.exports = class PurchaseCommand extends Command {
constructor(client) {
super(client, {
name: 'purchase',
guildOnly: true,
aliases: [],
group: 'misc',
memberName: 'puchase',
description: 'Purchase a card pack',
examples: ['purchase'],
args: [
{
key: 'packName',
prompt: 'Qual é o nome do CardPack que você quer comprar?',
type: 'string'
}
]
});
}
async run(msg, { packName, }) {
const profile = await Profile.findOne({
memberID: msg.member.id
}).exec();
const cardPacks = await CardPack.find({}).exec();
if (!profile){
return msg.embed(
new MessageEmbed()
.setTitle('Perfil não registrado')
.setDescription("O seu perfil não foi encontrado. Antes de utilizar este comando, usa o comando `register` para se registrar!")
.setColor('#f44336')
);
};
const fuse = new Fuse(cardPacks, {
keys: ['name'],
threshold: 0.1
});
const results = fuse.search(packName);
if(results.length > 1){
return msg.embed(
new MessageEmbed()
.setTitle('Seja específico')
.setDescription('Seja mais especifico no que você quer comprar')
.setColor('#f44336')
);
};
if (results.length === 0){
return msg.embed(
new MessageEmbed()
.setTitle('Nenhum CardPack encontrando')
.setDescription('Não foi encontrado nenhum Cardpack com este nome')
.setColor('#f44336')
);
};
const cardPack = results[0];
const response = cardPack.purchase(msg.member.id);
if(response === 'err'){
return msg.embed(
new MessageEmbed()
.setTitle(response.title)
.setDescription(response.desc)
.setColor('#f44336')
);
};
msg.embed(
new MessageEmbed()
.setTitle('Abrindo o CardPack')
.setDescription('CardPack está sendo aberto...')
.setColor('#f44336')
);
setTimeout(() => {
response.cards.forEach(async card => {
if(card.type === 'character'){
const embeda = new MessageEmbed()
.setTitle(card.name)
.setDescription(card.description)
.addField('Código da Carta:', card.codC)
.addField('Atributos:', card.attributes)
.addField('Status:', `ATK: ${card.attack} \\ DEF: ${card.defense}`)
.setThumbnail(card.pictureUrl)
return msg.embed(embeda);
}
})
}, 3000);
}
};
My Schema:
const { model, Schema } = require('mongoose');
const Probability = require('probability-node');
const _ = require('lodash');
const cardPackSchema = new Schema({
name: {
type: String,
unique: true
},
description: String,
cards: Number, //Número de cartas dentro desse pack
type: String, //Se é um Personagem, Feitiço, Item, Todos
tier: Number,
probability: {
//Probabilidade de pegar cartas de especifico tier
1: Number,
2: Number,
3: Number,
4: Number,
5: Number,
6: Number,
7: Number
},
price: Number,
discount: Number, //Desconto em porcentagem %
stock: Number, // -1 é infinito no estoque
guaranteedTier: Number //Se refere ao tier da descriçao do pack
});
cardPackSchema.methods.purchase = async function(memberID){
const profile = await this.model('Profile')
.findOne({ memberID })
.exec();
if (this.stock === 0){
return {
res: 'err',
title: "Não está disponível",
desc: 'O CardPack que você está tentando comprar está esgotado'
}
};
if(profile.coins < this.price - this.price * this.discount){
return {
res: 'err',
title: 'Dinheiro insuficiente',
desc: 'Você não tem dinheiro o suficiente para comprar este pacote!'
}
};
//Comando
const cards = [];
//Add a carta garantida do tier
if (this.guaranteedTier > 1) {
addCard.call(this, this.guaranteedTier);
this.cards--;
};
const addRandomCard = new Probability(
{
p: this.probability['1'],
f: () => addCard.call(this, 1)
},
{
p: this.probability['2'],
f: () => addCard.call(this, 2)
},
{
p: this.probability['3'],
f: () => addCard.call(this, 3)
},
{
p: this.probability['4'],
f: () => addCard.call(this, 4)
},
{
p: this.probability['5'],
f: () => addCard.call(this, 5)
},
{
p: this.probability['6'],
f: () => addCard.call(this, 6)
},
{
p: this.probability['7'],
f: () => addCard.call(this, 7)
}
);
//Adicionando o resto das cartas
for (var i = 1 + cards.length; 1 <= this.cards; i++){
await addRandomCard();
}
//Adicionando as cartas no inventario
const deck = await this.model('Deck')
.findOne({ memberID })
.exec();
profile.deductCoins(this.price - this.price * this.discount);
profile.addExp(this.tier ** this.tier + this.price / 20);
await deck.addCards(cards);
//Voltando com os nomes da carta
return {
res: 'Sucesso',
cards,
coins: profile.coins - (this.price - this.price * this.discount)
};
//função de adicionar a carta
async function addCard(tier){
const randomTypeCard = Math.floor(Math.random() * 1) * 1;
//Adicionando a carta do Personagem
if (
(randomTypeCard === 1 && this.type === 'all') || this.type === 'character'
) {
const cardToAdd = _.sample(await model('Character').find({ tier }));
cardToAdd.type = 'character';
if (
!_.includes(cards.map(card => card.name), cardToAdd.name) ||
cardToAdd.sold >= cardToAdd.stock
) {
await cardToAdd.sell();
cards.push(cardToAdd);
} else addCard.call(this, tier);
}
}
};
model('CardPack', cardPackSchema);
It seems, results[0]
is not an instance of cardPack
. It seems you're using fuse.js to search, and according to its examples it returns an array of objects that have the following keys: item
, refIndex
, and score
.
It seems, item
is the instance you're looking for, so try to modify cardPack
to:
const cardPack = results[0].item
Or if it doesn't work, you could use the refIndex
that returns the result's index in the original list:
const cardPack = cardPacks[results[0].refIndex]