Search code examples
node.jsdiscord.js

Node.js terminal not usable after running main file


I just started making a Discord bot using Node.js in Visual Studio Code, but I've stumbled upon an issue that I haven't been able to fix.

When I run, for example node deploy-commands.js, the terminal writes a message, and it is usable right after. But, when I try to run the main file, node index.js, the terminal writes a message that I expected, but is not usable until I make a new terminal or close VS Code and open it again.

Here is my code in index.js:

const Discord = require("discord.js");
 
const client = new Discord.Client({
    intents: ["GUILDS", "GUILD_MESSAGES", "GUILD_MEMBERS", "MESSAGE_CONTENT"],
    partials: ["CHANNEL", "MESSAGE"]
});
 
const token = ("my-token") // your bot token here
 
client.on('ready', async () => {
    console.log(`Client has been initiated! ${client.user.username}`)
});
 
client.login(token)

client.on('messageCreate', async (message) => {
    if (message.content.toLowerCase() === "test") { // if someone says 'test'
        console.log("Test had been said")
        message.channel.send("Test reply, but not to your message :)")

        let role = message.guild.roles.cache.find(role => role.name === "python");
        if (role) message.guild.members.cache.get(message.author.id).roles.add(role);

        message.reply("I gave you the role!")
        console.log("Role given!")
    }
});

// ----------------------------- 

client.on('interactionCreate', async interaction => {
    if (!interaction.isCommand()) return;

    const { commandName } = interaction;

    if (commandName === 'ping') {
        await interaction.reply('Pong!');
    } else if (commandName === 'server') {
        await interaction.reply('`Server name: ${interaction.guild.name}\nTotal members: ${interaction.guild.memberCount}`');
    } else if (commandName === 'user') {
        await interaction.reply('Your tag: ${interaction.user.tag}\nYour id: ${interaction.user.id}');
    }
});

client.on('guildMemberAdd', (guildMember) => {
    // commands here
 });

Contents of deploy-commands.js:

const { SlashCommandBuilder } = require('@discordjs/builders');
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const { clientId, guildId, token } = require('./config.json');

const commands = [
    new SlashCommandBuilder().setName('ping').setDescription('Replies with pong!'),
    new SlashCommandBuilder().setName('server').setDescription('Replies with server info!'),
    new SlashCommandBuilder().setName('user').setDescription('Replies with user info!'),
    new SlashCommandBuilder().setName('schedule').setDescription('Replies with stream schedule!'),
]
    .map(command => command.toJSON());

const rest = new REST({ version: '9' }).setToken(token);

rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: commands })
    .then(() => console.log('Successfully registered application commands.'))
    .catch(console.error);

I wanted to run more commands after running index.js (I run everything by saying node filename.js), but I can't because it does not allow me to type.


Solution

  • When you run a program in Node.js, Node.js will not exit until the program terminates. You cannot run another command in the same terminal until control is returned to the CLI. [1]

    In your case, the program does not terminate because the Discord.Client instance keeps the program alive. This instance has the ability to reconnect even when it disconnects.

    Discord.Client [discord.js.org]

    The main hub for interacting with the Discord API, and the starting point for any bot.

    That is essentially the core of your program so why would you want it to exit so that you can run other commands?

    The best solutions are:

    • Either run all other commands first before starting your bot. [2]
    • Or run these other commands in another terminal.

    [1] This is general with all CLI executables.

    [2] This is your bot; it has to run without exiting and without any disturbance.