Discord.js currency to command handler

非 Y 不嫁゛ 提交于 2021-01-29 17:39:54

问题


I am trying to move all of my currency/shop commands/ Sequelize database into the command handler from index.js (works perfectly in index.js file) but I am running into issues transferring data from the index.js file into the individual command files. Any help on how to properly integrate the index.js commands into the command handler would be greatly appreciated. I realize this is a lot to go through but it would really mean a lot to me if anyone was able to help me out

index.js:

Reflect.defineProperty(currency, 'add', {
    value: async function add(id, amount) {
        const user = currency.get(id);
        if (user) {
            user.balance += Number(amount);
            return user.save();
        }
        const newUser = await Users.create({ user_id: id, balance: amount });
        currency.set(id, newUser);
        return newUser;
    },
});

Reflect.defineProperty(currency, 'getBalance', {
    value: function getBalance(id) {
        const user = currency.get(id);
        return user ? user.balance : 0;
    },
});

client.once('ready', async () => {
    const storedBalances = await Users.findAll();
    storedBalances.forEach(b => currency.set(b.user_id, b));
    console.log(`Logged in as ${client.user.tag}!`);
});

client.on('message', async message => {
    if (message.author.bot) return;
    currency.add(message.author.id, 1);

    if (!message.content.startsWith(prefix)) return;
    const input = message.content.slice(prefix.length).trim();
    if (!input.length) return;
    const [, command, commandArgs] = input.match(/(\w+)\s*([\s\S]*)/);
    if (command === 'balance') {
        const target = message.mentions.users.first() || message.author;
        return message.channel.send(`${target.tag} has ${currency.getBalance(target.id)}💰`);
    } else if (command === 'buy') {
        const item = await CurrencyShop.findOne({ where: { name: { [Op.like]: commandArgs } } });
        if (!item) return message.channel.send('That item doesn\'t exist.');
        if (item.cost > currency.getBalance(message.author.id)) {
            return message.channel.send(`You don't have enough currency, ${message.author}`);
        }
        const user = await Users.findOne({ where: { user_id: message.author.id } });
        currency.add(message.author.id, -item.cost);
        await user.addItem(item);

        message.channel.send(`You've bought a ${item.name}`);
    } else if (command === 'shop') { 
        const items = await CurrencyShop.findAll();
        return message.channel.send(items.map(i => `${i.name}: ${i.cost}💰`).join('\n'), { code: true });
    } else if (command === 'leaderboard') {
        return message.channel.send(
            currency.sort((a, b) => b.balance - a.balance)
                .filter(user => client.users.cache.has(user.user_id))
                .first(10)
                .map((user, position) => `(${position + 1}) ${(client.users.cache.get(user.user_id).tag)}: ${user.balance}💰`)
                .join('\n'),
            { code: true }
        );
    }
});

converting balance command to balance.js

balance.js:

const { currency, getBalance, id, tag } = require('../index.js');

module.exports = {
    name: "balance",
    description: "checks balance",
    execute(message) {

        const target = message.mentions.users.first() || message.author;
        message.channel.send(`${target.tag} has ${currency.getBalance(target.id)}💰`);
    },
};

error: TypeError: Cannot read property 'getBalance' of undefined

Command Handler

client.on('message', message => {
    if (!message.content.startsWith(prefix) || message.author.bot) return;

    const args = message.content.slice(prefix.length).split(/ +/);
    const commandName = args.shift().toLowerCase();

    const command = client.commands.get(commandName)
        || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));

    if (!command) return;

    if (command.guildOnly && message.channel.type !== 'text') {
        return message.reply('I can\'t execute that command inside DMs!');
    }

    if (command.args && !args.length) {
        let reply = `You didn't provide any arguments, ${message.author}!`;

        if (command.usage) {
            reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
        }

        return message.channel.send(reply);
    }

    if (!cooldowns.has(command.name)) {
        cooldowns.set(command.name, new Discord.Collection());
    }

    const now = Date.now();
    const timestamps = cooldowns.get(command.name);
    const cooldownAmount = (command.cooldown || 3) * 1000;

    if (timestamps.has(message.author.id)) {
        const expirationTime = timestamps.get(message.author.id) + cooldownAmount;

        if (now < expirationTime) {
            const timeLeft = (expirationTime - now) / 1000;
            return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`);
        }
    }

    timestamps.set(message.author.id, now);
    setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);

    try {
        command.execute(message, args);
    } catch (error) {
        console.error(error);
        message.reply('there was an error trying to execute that command!');
    }
});

the bot sends an error from the command handler as seen above

EDIT: Cherryblossom's post seems to work. i have 1 more issue with immigrating the buy command though I dont know how to make the async work as async doesnt work in command handler. here is what i tried

const { currency, CurrencyShop} = require('../index.js');

const item = await CurrencyShop.findOne({ where: { name: { [Op.like]: commandArgs } } });
        if (!item) return message.channel.send('That item doesn\'t exist.');
        if (item.cost > currency.getBalance(message.author.id)) {
            return message.channel.send(`You don't have enough currency, ${message.author}`);
        }
        const user = await Users.findOne({ where: { user_id: message.author.id } });
        currency.add(message.author.id, -item.cost);
        await user.addItem(item);

        message.channel.send(`You've bought a ${item.name}`);```

回答1:


What's happening is that in balance.js, currency is undefined. You need to export currency from index.js:

module.exports = { currency }

Also, in balance.js, you don't need to (and actually can't) import/require properties of other objects (getBalance, tag, id). Sorry if that doesn't make sense but basically you only need to require currency:

const { currency } = require('../index.js')

Edit

await can only be used in an async function. Edit the execute function so it is like this:

async execute(message) {
    // your code here
}

When calling execute, use await. You'll need to make the message handler async as well:

client.on('message', async message => {
    // code...
    try {
        await command.execute(message, args);
    } catch (error) {
        console.error(error);
        message.reply('there was an error trying to execute that command!');
    }
}


来源:https://stackoverflow.com/questions/60537931/discord-js-currency-to-command-handler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!