0

I am making a Discord bot and I want to add JSON values like this

{
    "Server ID": {
        "01-Ticket": {
            User: "Some ID",
            Channel_ID: "Some ID"
        }
    }
}

I added one using fs but, when I add another, it deletes the first value ("01-Ticket")

This is my index.js:

channel.send(welcomeEmbed).then(async msg => {
     await msg.react("")
     let tickets = require('./tickets.json')[msg.guild.id];
     tickets[msg.guild.id]
     console.log(tickets)
     fs.writeFileSync('tickets.json', JSON.stringify(tickets, null, 5))
})
Kamafeather
  • 8,663
  • 14
  • 69
  • 99

1 Answers1

0

There are simply two things you need to do: create a new name for the ticket (if the previous one was "01-Ticket", then you need to name the new one "02-Ticket") and insert the ticket into the object using its new name.

A Solution

Here's a full example of how you could do such a thing:

let tickets = require('./tickets.json');
let newName = "01-Ticket";

if (msg.guild.id in tickets) {
    let guildTickets = tickets[msg.guild.id];

    let oldName = Object.keys(guildTickets).sort((a,b) => a.localeCompare(b)).pop();
    let newNumber = Number(oldName.split("-")[0]) + 1;
    let length = newNumber.toString().length;
    newName = ("0" + newNumber).slice(-((length - 1) + Math.ceil(2 / length))) + "-Ticket";
}
else {
    tickets[msg.guild.id] = {};
}

let ticket = {
    User: msg.author.id,
    Channel_ID: msg.channel.id
}

tickets[msg.guild.id][newName] = ticket;

fs.writeFileSync('tickets.json', JSON.stringify(tickets, null, 5))

Explanation

And below is the same code, but I've commented each new line to make it easier for you to understand the purpose of everything I am doing in this example:

let tickets = require('./tickets.json');
let newName = "01-Ticket";

//Check if the guild has any tickets
if (msg.guild.id in tickets) {
    //The guild does already have tickets

    //Get the tickets for this guild
    let guildTickets = tickets[msg.guild.id];

    //Take all of the ticket names ("01-Ticket", "02-Ticket", etc.) via Object.keys(),
    //sort them in ascending numerical order via .sort(),
    //and get the last one (the largest number, or the name of the latest ticket) via .pop()
    let oldName = Object.keys(guildTickets).sort((a,b) => a.localeCompare(b)).pop();

    //Take the old ticket's name ("01-Ticket"), get its number ("01"), and increment
    //it by one (so now it would be "2")
    let newNumber = Number(oldName.split("-")[0]) + 1;

    //The length of the new number (for "2", the length would be 1)
    let length = newNumber.toString().length;

    //Now add a single "0" to the start of the name (name so far: "0")
    //then add the new number (name so far: "02")
    //Then, from the end of the name go back as far as necessary to get the proper name (name so far: "02")
    //This works with all amounts of digits (ex: 2 -> "02"; 12 -> "12")
    newName = ("0" + newNumber).slice(-((length - 1) + Math.ceil(2 / length))) + "-Ticket";
}
else {
    //No tickets have been made in this guild yet

    //So set the guild's ticket list to an empty object
    tickets[msg.guild.id] = {};
}

//Create the new ticket to add to the guild's ticket list
let ticket = {
    User: msg.author.id,
    Channel_ID: msg.channel.id
}

//Add the ticket to the guild's ticket list
tickets[msg.guild.id][newName] = ticket;

//Update the tickets.json with your updated 'tickets' object
fs.writeFileSync('tickets.json', JSON.stringify(tickets, null, 5))

So first I am checking whether or not the guild's ID is already in tickets.json. If it isn't, we are adding it in as an empty object (and we add in the new ticket with the default name: "01-Ticket"). If the guild's ID is already in the file, then we need to create a new name for our new ticket. So first I get the object representing the guild's tickets. Then I get all of the keys in that object (which are the tickets' names: "01-Ticket", "02-Ticket", and so on). I sort those keys from least to greatest (since all of the ticket names begin with numbers, this is essentially sorting them numerically), and retrieve the last ticket name in the sorted list using .pop() (which is the ticket name starting with the largest number). I then take the number from that ticket name, and add one to it. Then I make sure to add a "0" at the beginning of the new ticket name if it is only one digit long; I am using a complex formula and .slice() to do so, but you could do this with a simple if statement. I then create the ticket itself, setting its user ID and channel ID properties. Finally, I add the ticket to the guild's ticket list by updating the tickets variable, and then update tickets.json with the new value of tickets.

The new name creation in this code is tested and works. The rest of the code is not tested, but works exactly the same as it does in some of my own bots' working code. If any part of this answer doesn't make sense or if you spot an error, feel free to comment it.

Cannicide
  • 4,360
  • 3
  • 22
  • 42