123ang
123ang

Reputation: 35

fs.write & read not updating

Basically, my code here is saying that if a user sends a message !submit ___ then the file leaderboard.json will up their count by one.
This all works perfectly however say for example their count goes from 0 to 1, the next time that same person sends !submit, their count should go from 1 to 2 without me having to restart the script every time. This isn't happening unfortunately... I send !submit and my count goes from 0 to 1, but then I send it again and it stays going from 0 to 1.

Leaderboard.json:

{
    "usercount<@386679122614681600>": 0
}

index.js:

client.on('message', msg => {
   if (msg.content.startsWith("!submit ")){
      var shoe = msg.content.substr("!submit ".length);

      var fs = require('fs')
      fs.readFile('leaderboard.json', 'utf8', function (err,data) {
        if (err) {
          return console.log(err);
        }
        var user = msg.member;
        var usercount = 'usercount'+user
        var username = 'usercount'+user

        var LEADERBOARD = require('./leaderboard.json');
        var countvalue = LEADERBOARD[username]
        var countvalue2 = countvalue+1
        var replacetext = ('"'+usercount+'": '+countvalue).toString()
        var newtext = ('"'+usercount+'": '+(countvalue2)).toString()

        fs.writeFile('leaderboard.json', data.replace(replacetext, newtext), 
        'utf8', function () {
            if (err) return console.log(err);
        });
        console.log('NEW SUBMISSION: '+replacetext+' >>>> '+newtext)

     });
   }

Here is what my console looks like after sending !submit twice:

Image

When technically the second line should go from 1 to 2, without me having to close and restart the script.

I know this may seem a bit complicated but any help would be appreciated!

Upvotes: 1

Views: 1445

Answers (1)

jfriend00
jfriend00

Reputation: 707318

This is what I'd suggest:

const fs = require('fs')

client.on('message', msg => {
    if (msg.content.startsWith("!submit ")) {
        let shoe = msg.content.substr("!submit ".length);

        // read leaderboard file and parse the JSON into a Javascript object
        fs.readFile('leaderboard.json', 'utf8', function(err, data) {
            if (err) {
                console.log("Error reading leaderboard.json", err);
                return;
            }

            let leaderboard;
            try {
                leaderboard = JSON.parse(data);
            } catch(err) {
                console.log("Error parsing leaderboard JSON", err);
                return;
            }

            const user = msg.member;
            const username = 'usercount' + user;

            // make sure there's a count for this username
            let cnt = leaderboard[username];
            if (!cnt) {
                cnt = 0;
            }
            // increment the cnt
            ++cnt;

            // set the new count
            leaderboard[username] = cnt;

            // now write the data back to the file
            fs.writeFile('leaderboard.json', JSON.stringify(leaderboard), 'utf8', function() {
                if (err) {
                    console.log(err);
                    return;
                }
                console.log(`New Submission for ${username}, cnt = ${cnt}`);
            });
        });
    }
});

Summary of changes:

  1. Reads leaderboard.json only once using fs.readFile()
  2. After reading the data, it converts it to JSON using JSON.parse().
  3. Initializes user cnt if not already in the file
  4. Updates cnt in the Javsacript object directly
  5. Writes out the changed object using JSON.stringify() to convert the object back to JSON
  6. Puts new submission console message in fs.writeFile() success handler
  7. Switch to const and let from var

Issues not yet incorporated:

  1. Concurrency issues if multiple message events can be "in-flight" at once and conflict.
  2. More complete error handling besides just stopping processing when there's an error (I'm not sure what your application should be doing in that case as that is application-specific).
  3. Your shoe variable is not being used anywhere, not sure what it's doing there.

Upvotes: 3

Related Questions