Search code examples
javascriptdiscord.jssequelize.js

Discord.js and Sequelize - Referencing the database in another .js


I will preface this by saying I am new with Javascript, most of my experience is with C# and C++ but I am a bit rusty in general anyways. I am working on learning Javascript and Discord js to try and make a bot that can store and list stats for dinosaurs so they can be tracked for breeding, and those will either be inputted via slash commands or from an attachment if possible. (Little personal project for ARK Survival Ascended when/if it's released haha)

I am following along with https://discordjs.guide/sequelize/#syncing-the-model , and it explained it's good practice to move all of my events and commands into their own separate .js to keep my main index.js more organized. So I followed along with that. However, while working with Sequelize it is demonstrating all of this within the same index.js, not utilizing the modules or other .js files that I have setup now for each command and event.

If I follow along exactly and do this in the same index.js, it works. But if I try to integrate this into the other .js, it's not defined, and I am not certain what I need to include or require in order to get it to work.

This is my index.js

const fs = require('node:fs');
const Sequelize = require('sequelize');
const path = require('node:path');
const keep_alive = require("./keep_alive.js");

const { Client, Collection, Events, GatewayIntentBits, EmbedBuilder, PermissionsBitField, Permissions, SlashCommandBuilder} = require('discord.js');

const client = new Client({intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]});
client.cooldowns = new Collection();
client.commands = new Collection();

// Secret values
const token = process.env['token']
const CLIENT_ID = process.env['client_id']
const GUILD_ID = process.env['guild_id']

// Setting up database
const sequelize = new Sequelize('database', 'user', 'password', {
  host: 'localhost',
  dialect: 'sqlite',
  logging: false,
  // SQLite only
  storage: 'database.sqlite',
});

// Setting up tags in database
const Tags = sequelize.define('tags', {
  name: {
    type: Sequelize.STRING,
    unique: true,
  },
  ... (other tags) ...
});

// Reads the commands in the commands folder.
client.commands = new Collection();
const foldersPath = path.join(__dirname, 'commands');
const commandFolders = fs.readdirSync(foldersPath);

for (const folder of commandFolders) {
  const commandsPath = path.join(foldersPath, folder);
  const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
  for (const file of commandFiles) {
    const filePath = path.join(commandsPath, file);
    const command = require(filePath);
    // Set a new item in the Collection with the key as the command name and the value as the exported module
    if ('data' in command && 'execute' in command) {
      client.commands.set(command.data.name, command);
    } else {
      console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
    }
  }
}

// Reads the events in the events folder.
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));

for (const file of eventFiles) {
  const filePath = path.join(eventsPath, file);
  const event = require(filePath);
  if (event.once) {

    Tags.sync(); //This should be inside the ready.js event, not called here.

    client.once(event.name, (...args) => event.execute(...args));
  } else {
    client.on(event.name, (...args) => event.execute(...args));
  }
}


client.login(token);

And this is the ready.js, the event which should be called only once when the bot is ready.

const { Client, Events, GatewayIntentBits } = require('discord.js');
//What am I missing??

module.exports = {
  name: Events.ClientReady,
  once: true,
  execute(client) {
    
    Tags.sync(); //This is causing an error. This should be inside the ready.js event, but it keeps saying Tags is not defined.
    
    console.log(`Ready! Logged in as ${client.user.tag}`);
  },
};

And this is the error:

/home/runner/BreedBotjs/events/ready.js:10
    Tags.sync(); //This is causing an error. This should be inside the ready.js event, but it keeps saying Tags is undefined.
    ^

ReferenceError: Tags is not defined
    at Object.execute (/home/runner/BreedBotjs/events/ready.js:10:5)
    at Client.<anonymous> (/home/runner/BreedBotjs/index.js:93:48)
    at Object.onceWrapper (node:events:628:26)
    at Client.emit (node:events:513:28)
    at WebSocketManager.triggerClientReady (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketManager.js:388:17)
    at WebSocketManager.checkShardsReady (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketManager.js:371:10)
    at WebSocketShard.<anonymous> (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketManager.js:201:16)
    at WebSocketShard.emit (node:events:513:28)
    at WebSocketShard.checkReady (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketShard.js:181:12)
    at WebSocketShard.gotGuild (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketShard.js:155:10)

Node.js v18.16.1

I figure I'm missing something really simple. Some kind of import or require.

I've tried to do things like const { Tags } = require('index.js');

But I am met with another error:

/home/runner/BreedBotjs/events/ready.js:10
    this.Tags.sync(); //This is causing an error. This should be inside the ready.js event, but it keeps saying Tags is undefined.
              ^

TypeError: Cannot read properties of undefined (reading 'sync')
    at Object.execute (/home/runner/BreedBotjs/events/ready.js:10:15)
    at Client.<anonymous> (/home/runner/BreedBotjs/index.js:93:48)
    at Object.onceWrapper (node:events:628:26)
    at Client.emit (node:events:513:28)
    at WebSocketManager.triggerClientReady (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketManager.js:388:17)
    at WebSocketManager.checkShardsReady (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketManager.js:371:10)
    at WebSocketShard.<anonymous> (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketManager.js:201:16)
    at WebSocketShard.emit (node:events:513:28)
    at WebSocketShard.checkReady (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketShard.js:181:12)
    at WebSocketShard.gotGuild (/home/runner/BreedBotjs/node_modules/discord.js/src/client/websocket/WebSocketShard.js:155:10)

Node.js v18.16.1

Solution

  • You're trying to access Tags in a different file where it has not been declared or required.

    You will need to export it from your index.js so that you can use it in other files.

    There are a couple ways of solving this, such as adding it to your client.once in index.js:

    client.once(event.name, (...args) => event.execute(...args, Tags));
    
    // in ready.js add Tags to your execute()
    module.exports = {
      name: Events.ClientReady,
      once: true,
      execute(client, Tags) {
        // rest of your code
      }
    

    or by adding it to your client:

    // in your index.js
    client.Tags = Tags;
    
    
    // in your ready.js
    const Tags = client.Tags;
    

    or by exporting it:

    // in index.js
    module.exports = {
      Tags
    }
    
    
    // in ready.js
    module.exports = {
      name: Events.ClientReady,
      once: true,
      execute(client) {
    
        const tagsData = require("path_to_your_index.js");
        const Tags = tagsData.Tags;
        
        Tags.sync();
        
        console.log(`Ready! Logged in as ${client.user.tag}`);
      },
    };