javascriptdiscord.jsbetter-sqlite3

Why is better-sqlite3 not writing my data when existent data already exists?


Whenever I set sqlite data for data that already exists, it won't set it. So if user '9' doesn't exist, it creates the row in the sqlite table with no problem. If data does exist, it does nothing.

E.g. trying to write to user '9'

BEFORE

{user: '9', timestamp: 10}

END RESULT (when trying to run):

this._client.setCooldown[this.name].run({user: '9', timestamp: 20})
//this.name = command name
//this.client = discord.js client | setCooldown is an array. the [this.name] represents the command name that i want to cooldown for a certain user
this._client.getCooldown[this.name].get('9')
//doesn't return {user: '9', timestamp: 20} which is expected
//instead returns {user: '9', timestamp: 10} which is the actual result

No error is displayed in console. Here are snippets from the important files that are ran in order

index.js (for creating client and calling another file.)

var djs = require('discord.js');
var client = new djs.client();

// code

require('./sqlitecreator.js')(client);

// code

sqlitecreator.js (this file basically creates some other sqlite files not related to this question, and creates a client collection with command names and their respective directories for another file to read, and creates file for cooldowns)

var sqlite3 = require('better-sqlite3');
var CooldownsSqlite = sqlite(`./src/util/essentials/util-cache/Cooldowns.sqlite`)
//verifiednames is an array of names where every string is unique.
//bot is the client from index.js
    bot.getCooldown = [];
    bot.setCooldown = [];

    for(var verifiedname of verifiednames) {
      var cooldownsqlitetable = CooldownsSqlite.prepare(`SELECT count(*) FROM sqlite_master WHERE type='table' AND name = '${verifiedname}';`).get();
      if (!cooldownsqlitetable['count(*)']) {
          console.log('Command Cooldowns Not Prepared!')
          CooldownsSqlite.prepare(`CREATE TABLE ${verifiedname} (user TEXT, timestamp INTEGER);`).run();
          CooldownsSqlite.prepare(`CREATE UNIQUE INDEX idx_${verifiedname}_user ON ${verifiedname} (user, timestamp);`).run();
          CooldownsSqlite.pragma("synchronous = 1");
          CooldownsSqlite.pragma("journal_mode = wal");
      }
      bot.getCooldown[verifiedname] = CooldownsSqlite.prepare(`SELECT * FROM ${verifiedname} WHERE user = ?`);
      bot.setCooldown[verifiedname] = CooldownsSqlite.prepare(`INSERT OR REPLACE INTO ${verifiedname} (user, timestamp) VALUES (@user, @timestamp);`);
    }


  } catch (e) {
    console.error(e);
    process.exit(1);
  }

message.js (fires up when client recieves a message event, takes directories from collection from above, also calls a function from the Command.js (a class file))

//file basically checks if message begins with prefix
//...
    command.executable(message); // checks if the command can run (checks permissions, uses bot.getCooldown function from the previous file.
    if(command.executable(message) !== 'finished') return;
    command.throttle(message.author); // is supposed to run the bot.setCooldown function

command.js (this file uses the set/getCooldown functions, this is also a class file)


    //occurances of get/setCooldown
    executable(...) {
//...
        if(this._client.getCooldown[this.name.toLowerCase()].get(msg.author.id)) {
        //.. executes another function
        }
//..
    }
   //...

    /**
     * Cooldown a user.
     * @param {Discord.User} user 
     * @param {Date} now 
     * @returns {void}
     */
    async throttle(user, now = Date.now()) {
        if(this._client.getCooldown[this.name.toLowerCase()]) return;
        var cd = {user: user.id,timestamp: now} ;
        //i thought it was a problem with the setCooldown function running before the object was created, but this didn't work.
        await this._client.setCooldown[this.name.toLowerCase()].run(cd);
        return;
    } 

During the message.js file, I console.log() the cooldown that I get, and it always returns the same value.

D.JS Documentation


Solution

  • When I was preparing my Cooldowns.sqlite file, I saw this snippet of code:

    CooldownsSqlite.prepare(`CREATE UNIQUE INDEX idx_${verifiedname}_user ON ${verifiedname} (user, timestamp);`).run();
    

    So I started changing around my code so it would look something like this when I would want to get a user:

    {
    id: '9-command',
    user: '9',
    command: 'command',
    timestamp: 20
    }
    

    So all cooldowns would be in one file, in one table. I changed the unique index part to this:

    CooldownsSqlite.prepare(`CREATE UNIQUE INDEX idx_cooldowns_id ON cooldowns (id);`).run();