Search code examples
javascriptdiscorddiscord.js

Discord bot Command That changes Value of a different command


I'm looking for a way to change a text string or a value in one command by typing the new value in a different command. For example I have Discord js v12 and I'm using module commands with each command being in its own .js file.

module.exports = {
    name: 'calc',
    cooldown: 1000,
    run: async(client, message, args) => {
        if (!message.member.hasPermission("ADMINISTRATOR")) return await message.delete();
        await message.delete();

        var multiply = args[0] * (100 - percalc) / 100;
        var calculation = multiply.toFixed(2);
        
        if(!args[0]) return await message.channel.send('Specify a Value');

        await message.channel.send(changableValue);
        await message.channel.send(calculation < 5 ? 5 : calculation);
    }

and I have the consts in the config file like

const percalc = 50;
const changableValue = 'Text example';

Right now the command _calc {number} puts out a calculation in percentage based on the percalc const and a text that comes with it in the changableValue part. I'd like to make a command let's say _calcset {Value} that will save the provided value and will send it in place of the changableValue const.


Solution

  • First of all, note that the only reason the keyword const exists is because it stands for constant and constant variables can never be changed once initialized. So make sure you change the variable declaration keyword to just var or let.

    Method 1 - If you don't need data to persist

    Now, if you only want the variable to be changed per session, and you're fine with it going back to what you defined it as when you shut down the bot, you can just update the variable using functions exported from the js file. But to get the dynamic variable you'll also need to use a getter function that you export as well. Example:

    config.js

    var changeableValue = "foo";
    
    function getValue() {
        return changeableValue;
    }
    
    function updateValue(newValue) {
        changeableValue = newValue;
    }
    
    module.exports = {
        getValue,
        updateValue
    }
    

    command.js

    const { getValue, updateValue } = require("config.js");
    
    console.log(getValue()); // logs "foo"
    updateValue("bar");
    console.log(getValue()); // logs "bar"
    

    Unfortunately, as I mentioned, the changeableValue var will be reset back to "foo" every time you shut off the bot. If that's okay with you, then the above works fine.

    Method 2 - If you need data to persist through sessions

    If you want to persist the changeableValue variable through sessions, then it gets a little more complicated. Your two most likely options are either to write the value to a JSON file using the fs module (so it will be saved to your disk), or save the value in some other database, like MongoDB. I would recommend using another database provider because there are more problems you can run into when writing to your own disk, for example, if you make two write requests at the same time (like if two users use the command at the same time), you can corrupt the file when the requests try to write at the same time. However setting up an external database is outside of the scope of this question, so here's how you would set up writing to a JSON file:

    config.json

    {
        "changeableValue": "foo"
    }
    

    command.js

    const fs = require("fs");
    var { changeableValue } = require("config.json");
    console.log(changeableValue) // logs "foo"
    
    var updatedValueJSON = JSON.stringify({ changeableValue: "bar" }); // necessary because the JSON object must be converted to a string
    
    fs.writeFile("config.json", updatedValueJSON, "utf8", () => {
        // this is the callback function called when the file write completes
        let { changeableValue } = require("config.json");
    
        console.log(changeableValue); // logs "bar", and now if you restart the bot and import changeableValue, it will still be bar
    });