Trying to learn module.exports but having some problem - node.js

I'm using discord.js from some week and now I would like to do that when someone enter in a vocal chat, the bot will send a message in the console. I tried using this code in the main file of the bot and perfectly worked but when I try to put it in another file and export it in the main file it doesn't work. Someone that can help me and maybe explain it?
main.js:
const Discord = require('discord.js');
const fs = require("fs");
const client = new Discord.Client();
const { prefix, token } = require("../config.json");
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
const a = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return a
}
test1.js:
const Discord = require('discord.js');
const fs = require("fs");
const client = new Discord.Client();
const { prefix, token } = require("../config.json");
module.exports = {
execute() {
client.on('voiceStateUpdate', (oldState, newState) => {
if (newState.channelID === null) console.log('Inside channel', oldState.channelID);
else if (oldState.channelID === null) console.log('Outside channel', newState.channelID);
else console.log('user moved channels', oldState.channelID, newState.channelID);
})}}

In this part in your main.js file:
const a = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return a
}
The a variable contains an object like { execute: function(){...} }. You not calling the execute function.
Try this:
const { execute } = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return execute();
}

Can you try adding the keyword function before the word execute()?
Alternatively, you could do:
// \/ you can put arguments here
module.exports.execute = () => {
// function here
}
and then in your index file..
const a = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return a.execute(this is where you would put your arguments)
}
Happy coding!

Related

onValue triggering multiple times

I'm using Node.js v18.12.1 and Discord.js v14. for developing the Discord bot. I need to read some data from Firebase. I'm confused because I'm used to how Java with Hibernate fetches data differently. Here, I need to use onValue() listener.
My onValue() acts strange. Instead of just reading the data from Firebase, it skips entirely, then it triggers multiple times, each time skipping the body block of its code, and then it actually does the code after.
I've read somewhere on this forum that this can happen because there are more onValue() listeners that are subscribed and they are all fired up. Someone mentioned I need to use the off() function somewhere "before" the onValue(). This confuses me because I'm using this listener in many locations. I need it in each command file, in execute(interaction) functions. You know, when you need to execute slash commands in Discord. I have it something like this:
async execute(interaction) {
const infographicRef = ref(db, '/infographics/arena/' + interaction.options.getString("arena-team"));
var imageUrl = null;
var postUrl = null;
onValue(infographicRef, (snapshot) => {
imageUrl = snapshot.child("image-url").val();
interaction.reply(imageUrl);
})
},
And I planned for each command, in each command.js file to have onValue(). I'm not sure exactly what to do.
Also, I tried to work around this with once() method, I see it in Firebase documentation, but I got the error: ref.once() is not a function.
It seems that after first triggering of onValue method when the body is not executed, my code in interactionCreate.js is triggered as well, it points for a command to be executed again:
const { Events } = require('discord.js');
module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(`Error executing ${interaction.commandName}`);
console.error(error);
}
},
};
my bot.js (which is in my case an index file)
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection, Events, GatewayIntentBits } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
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) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
client.commands = new Collection();
const commandsPath = path.join(__dirname, 'commands');
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);
client.commands.set(command.data.name, command);
}
client.once(Events.ClientReady, () => {
console.log('Ready!');
});
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
});
client.login(token);
The onValue function registers a realtime listener, that continues to monitor the value on the database.
If you want to read a value once, that'd be done with get() function in v9 (which is the equivalent of the once method in earlier SDK versions). Have a look at the code sample in the documentation on reading data once.

So, I got a question. Is it possible to have a embed welcome message in a Discord bot that gets deleted after a few seconds?

var TOKEN = ""
const client = ("TOKEN");
const { Client, MessageEmbed } = require('discord.js');
const channel = ("CHANNELID");
const embed = new MessageEmbed()
('guildMemberAdd', member => {
const embed = new Discord.RichEmbed()
.setColor('#0099ff')
.setDescription(`Welcome ${member}! You are the ${membercount}th member!`)
.setImage(member.user.avatarURL)
})
That is my current code for this but, I'm unsure because there are some errors to it.
Yes it is possible.
Please don't use this code, it will not work based on how you have it coded now
var TOKEN = ""
const client = ("TOKEN");
const { Client, MessageEmbed } = require('discord.js');
const channel = ("CHANNELID");
const embed = new MessageEmbed()
('guildMemberAdd', member => {
const embed = new Discord.RichEmbed()
.setColor('#0099ff')
.setDescription(`Welcome ${member}! You are the ${membercount}th member!`)
.setImage(member.user.avatarURL)
})
Please use the code below:
// var TOKEN = "" //token is never a variable
// const client = ("TOKEN"); //please find a different way to code this as this will cause confusion later on
const TOKEN = ""
const { Client, MessageEmbed } = require('discord.js');
const client = new Client({
intents: [], // pick the intents you need here https://discord.com/developers/docs/topics/gateway#list-of-intents
})
client.login(TOKEN)
client.on('guildMemberAdd', member => {
const welcomeChannel = client.channels.cache.get("channel_id")
const membercount = member.guild.members.cache.filter(member => !member.user.bot).size
const timeout = 30 * 1000 //30 being how many seconds till the message is deleted.
const embed = new MessageEmbed()
.setColor('#0099ff')
.setTitle(`${member.displayName} has joined us!`)
.setDescription(`Welcome ${member}!\nYou are member number ${membercount}!`)
.setThumbnail(member.displayAvatarURL())
welcomeChannel.send({
embeds: [embed]
}).then((message) => {
setTimeout(() => {
message.delete()
}, timeout);
})
})
Yes, you can!
just use
.then(msg => {
setTimeout(() => {
msg.delete().catch(() => null)
}, 5000)
})

Discord.js/Firestore .where() is not a function

I am trying to integrate my discord bot with firestore. Whenever I try to run a query I get .where is not a function and I don't understand why because everything else seems to work. Here is the relevant code. I have tried the require of firebase at the top of Remove.js and that doesn't seem to do anything.
Here is my thought to how I believe it should be working right now.
I run node . and it then runs my index.js file.
On an interaction create (i.e. a slash command is created) it checks the command file and in this case it is the remove command
It calls execute(interaction, db) where interaction is the interaction slash command and db is the admin.Firestore() db reference from index.js. I am fully able to use get commands (i.e. that first chunk of code works before I try to delete)
Because this is a reference I should be able to call .where() based on the Firestore documentation and yet I am hit with the error "TypeError: db.collection(...).doc(...).collection(...).doc(...).where is not a function"
// Index.js
// General Setup
const { Client, Collection, Intents } = require('discord.js')
const config = require('./config.json')
const fs = require('fs')
// Bot Setup
const myIntents = new Intents();
myIntents.add(Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MEMBERS)
const bot = new Client({intents: myIntents});
// Firebase Setup
const firebase = require('firebase/app')
const fieldValue = require('firebase-admin').firestore.FieldValue
const admin = require('firebase-admin')
const serviceAccount = require('./serviceAccount.json')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
})
let db = admin.firestore();
// Command Setup
bot.commands = new Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'))
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
bot.commands.set(command.data.name, command);
}
// Bot Login
bot.once('ready', async () => {
console.log('Wheatley is online!');
});
bot.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) {
return
}
const command = bot.commands.get(interaction.commandName)
if (!command) {
return
}
try {
await command.execute(interaction, db)
} catch (error) {
console.error(error)
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true})
}
});
bot.login(config.bot_token);
///Remove.js
const { SlashCommandBuilder } = require('#discordjs/builders');
require('#firebase/firestore');
module.exports = {
data: new SlashCommandBuilder()
.setName('remove')
.setDescription('Removes object from collection')
.addStringOption(option =>
option.setName('item')
.setDescription('Enter an item in the collection to remove')
.setRequired(true)
),
async execute(interaction, db) {
const itemName = await interaction.options.getString('item')
const itemToDelete = db.collection('items').doc(interaction.guildId).collection('items').doc(itemName);
const doc = await itemToDelete.get();
if(!doc.exists) {
return interaction.reply({
content: `${itemName} does not exist in the collection. Try using /list to check for the right name.`,
ephemeral: true
})
}
const ownerId = interaction.user.id
const snapshot = db.collection('items').doc(interaction.guildId).collection('items').doc(itemName).where("ownerId", "==", ownerId).get();
if(!snapshot.exists) {
return interaction.reply({
content: `You are not the owner of ${itemName}. Please contact owner to delete this from the collection`,
ephemeral: true
})
}
itemToDelete.delete();
return await interaction.reply(`${itemName} was removed from the collection!`)
},
};
You are using where on a document, as where is a query function that is only available to collections.
Just be warned that the snapshot will return an array of snapshots as it is a query, not a single document.
Try this instead:
const snapshot = db.collection('items').doc(interaction.guildId).collection('items').where("ownerId", "==", ownerId).get();

Making .env file and modifty codes on discord.js

Anybody help me on creating .env file and modify the codes!
this is discord.js v12
i cant modify the .env codes on this codes!
but it didnot working
pls help me in this system! and it is yarn installed method!
js file => RushGamerzClient.js
const { Client } = require('discord.js');
module.exports = class RushGamerzClient extends Client {
constructor(options = {}) {
super({
disableMentions: 'everyone'
});
this.validate(options);
this.once('ready', () => {
console.log(`Logged in as ${this.user.username}!`);
});
this.on('message', async (message) => {
const mentionRegex = RegExp(`^<#!${this.user.id}>$`);
const mentionRegexPrefix = RegExp(`^<#!${this.user.id}> `);
if (!message.guild || message.author.bot) return;
if (message.content.match(mentionRegex)) message.channel.send(`My prefix for ${message.guild.name} is \`${this.prefix}\`.`);
const prefix = message.content.match(mentionRegexPrefix) ?
message.content.match(mentionRegexPrefix)[0] : this.prefix;
if (!message.content.startsWith(prefix)) return;
// eslint-disable-next-line no-unused-vars
const [cmd, ...args] = message.content.slice(prefix.length).trim().split(/ +/g);
if (cmd.toLowerCase() === 'hello') {
message.channel.send('Hello!');
}
});
}
validate(options) {
if (typeof options !== 'object') throw new TypeError('Options should be a type of Object.');
if (!options.token) throw new Error('You must pass the token for the client.');
this.token = options.token;
if (!options.prefix) throw new Error('You must pass a prefix for the client.');
if (typeof options.prefix !== 'string') throw new TypeError('Prefix should be a type of String.');
this.prefix = options.prefix;
}
async login(token = this.token) {
super.login(token);
}
};
js file => index.js codes on here
const RushGamerzClient = require('./Structures/RushGamerzClient');
const config = require('../config.json');
const client = new RushGamerzClient(config);
client.login();
You have few options to fix the problem:
Use .env file that has
DISCORD_TOKEN="<your-token>"
then use dotenv (install using npm i -G dotenv) on the top of your file, and login with environment variable
require('dotenv').config();
...
client.login(process.env.DISCORD_TOKEN);

TypeError: Cannot read property 'set' of undefined

I'm creating a discord bot using the discord.js v12.2.0 library. In my file Command.js, I have this code:
const { readdirSync } = require("fs")
module.exports = (Bot) => {
const load = dirs => {
const Commands = readdirSync(`./SRC/Commands/${dirs}/`).filter(d => d.endsWith('.js'));
for (let file of Commands) {
let pull = require(`../Commands/${dirs}/${file}`);
Bot.Commands.set(pull.config.name, pull);
if (pull.config.aliases) pull.config.aliases.forEach(a => Bot.aliases.set(a, pull.config.name));
};
};
["Miscellaneous", "Moderation", "Owner"].forEach(x => load(x));
};
This is my Index.js file:
const { Client, Collection } = require("discord.js");
const { Token } = require("./Config.json");
const Bot = new Client();
["aliases", "commands"].forEach(x => Bot[x] = new Collection());
["console", "command", "event"].forEach(x => require(`./SRC/Handlers/${x}`)(Bot));
Bot.login(Token);
The error I get from running this code is TypeError: Cannot read property 'set' of undefined
This is my Project Structure
Have you initialized Bot.Commands to a Discord.Collection() ?
index.js or whatever main file
const Discord = require("discord.js");
const Bot = new Discord.Client();
Bot.Commands = new Discord.Collection();
//or
const { Client, Collection } = require("discord.js");
const Bot = new Client();
Bot.Commands = new Collection();
I would suggest you make Bot and commands lowercase as that's the convention in js, and helps others understand better.

Resources