Importing variables from other files - javascript

I am trying to import a variable from one of my files (File 1) and use it in File 2. I have imported File 2 into File 1 but I am receiving error. My channel ID is correct, in this case you would have to choose the channel so the channel ID is not the issue here.
TypeError: setr.send is not a function
File 1
const Discord = require("discord.js");
const axios = require("axios");
let config = require("../config.json");
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
const perm = new Discord.MessageEmbed()
.setDescription(":x: You do not have permission to use this command.")
.setColor("#E74C3C");
if (!message.guild.me.hasPermission("ADMINISTRATOR"))
return message.channel.send(perm);
if (message.author.id !== "ID")
return message.channel.send(perm);
const channelx =
message.mentions.channels.first() ||
message.guild.channels.cache.find((c) => c.id === args[0]);
if (!channelx)
return message.channel.send(
`:x: Please specify the channel where server restarts will go!`
);
message.reply(`All server restart logs will now go to ${channelx}.`)
},
};
File 2
const Discord = require("discord.js");
const axios = require("axios");
let config = require("../config.json");
let setr = require("./setrestart"); // This is importing file 1
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
const perm = new Discord.MessageEmbed()
.setDescription(":x: You do not have permission to use this command.")
.setColor("#E74C3C");
if (!message.guild.me.hasPermission("ADMINISTRATOR"))
return message.channel.send(perm);
if (message.author.id !== "ID")
return message.channel.send(perm);
const restart = new Discord.MessageEmbed()
.setTitle(" Server Restarted! ")
.setDescription(`F8 connect to ${config.SERVER_URL} `)
.setColor("RANDOM")
.setTimestamp()
.setFooter(`${config.SERVER_LOGO}`);
setr.channelx.send(restart) // This does not work.
},
};
Help is much appreciated.
Edit: I left out the most crucial thing about what I am trying to import.
I am trying to import channelx which is in File 1 and I am trying to use the variable in File 2.
Output
User: /setrestart #channel
Bot: All server restart logs will now go to ${channelx}.
User: /restart
Bot: Embed sent in channelx

The variable channelx is accessible only in the function scope of execute(), you can't import it. Basically after the function goes out of scope the variable is lost. Use a global object, note that the object is destroyed when the program exits. So if you are trying to make some kind of bot's configuration, you want to save the object to a file.
Here is an example of how to properly implement what you are trying to do.
File 1 (file1.js):
// ... Load storage from a JSON file ...
const storage = {};
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
// ... Permission checking ...
const channelx = message.mentions.channels.first() ||
message.guild.channels.cache.find((c) => c.id === args[0]);
if (!channelx) {
return message.channel.send(
`:x: Please specify the channel where server restarts will go!`
);
}
// Store restart channel id per guild
storage[message.guild.id] = channelx.id;
message.reply(`All server restart logs will now go to ${channelx}.`);
// ... Write to the storage JSON file and update it with new data ...
},
};
module.exports.storage = storage;
File 2 (file2.js):
const Discord = require("discord.js");
const file1 = require("./file1.js");
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
// ... Permission checking ...
const restart = new Discord.MessageEmbed()
.setTitle(" Server Restarted! ")
.setColor("RANDOM")
.setTimestamp();
const channelId = file1.storage[message.guild.id];
// If there is no restart channel set, default to the system channel
if (!channelId) channelId = message.guild.systemChannelID;
const channel = await message.client.channels.fetch(channelId);
channel.send(restart);
},
};
Note that I have remove some parts of your code, to make it work on my machine.
Using discord.js ^12.5.3.

I am pretty sure you can't use the module.exports in that way. You should just add the channelx to the exports instead.
using this.channelx = channelx.

This is not how importing and exporting works. Your channelx variable is defined within the execution of a function, and you are not returning it.
I am not sure how the whole Discord API works and what are the shapes that get returned, but you should be able to do something like this:
File 1
module.exports = {
name: "setrestart",
description: "sets the restart channel",
async execute(message, args) {
// ... everything as per your file
message.reply(`All server restart logs will now go to ${channelx}.`);
return channelx;
},
};
File 2
module.exports = {
name: "restart",
description: "send a restart message in status channel",
async execute(message, args) {
// ... everything the same as per your file
const channelx = await setr.execute(message, args);
channelx.send(restart);
},
};
Basically, what is happening here is that the first module exposes a function that figures out your target channel and then returns it.
Once you return it, you can do whatever you want with that.
Please be aware that your first function might not need to be async as you don't have any await instruction.
Read more about scope: https://developer.mozilla.org/en-US/docs/Glossary/Scope

Related

JS Discord buttons error : 'Cannot send empty message'

Hi I'm making a Javascript based Discord bot, and I really wanted to implement the new Discord Buttons feature, the problem is, even using the documentation examples, I get the same error, again and again :
(node:6184) UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message
Here is the code (I am using module.exports with separated files for each commands) :
const { MessageButton } = require('discord-buttons')
module.exports = {
name: 'invite',
descritipion: 'test command',
async execute(client, message, args) {
let button = new MessageButton()
.setStyle('url')
.setURL('https://npmjs.com/discord-buttons')
.setLabel('Click me !')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons');
await message.channel.send(button);
}
}
You cannot just send a button on its own. Instead, try adding the button to the previous message so they both get sent in one message as shown below
The official documentation for this is here
// Replace these
const { MessageButton } = require('discord-buttons')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons');
await message.channel.send(button);
// With these
const { MessageButton, MessageActionRow } = require('discord-buttons')
await message.channel.send('Hey, I am powered by npm discord-buttons : https://npmjs.com/discord-buttons', {
component: new MessageActionRow().addComponent(button)
});
Also, did you forget to initialize DiscordButtons? Do it when you initialize your discord bot
// Where you initialized your discord bot
const bot = new Discord.Client()
// Add this line
require("discord-button")(bot)

How can I read config file again and update prefix for Discord bot?

I'm having some trouble coding prefix changing in my Discord bot. I've got all the basic functionality working:
The prefix is saved in a config file
The bot can write to the file and save it for later use
However, I can't seem to get the bot to use the new prefix after it's changed until I restart the bot. The config file shows that the prefix has been changed, but the bot doesn't respond to it.
So, my question is either, how can I refresh the memory so that the config is reloaded, or how can I get the bot to read my config again and use the new prefix?
Thanks!
prefix.js:
const fs = require('fs'); // node.js file system module
config = require('../config.json');
const Discord = require("discord.js");
module.exports = {
name: 'prefix', // command keyword
description: 'Changes the bot prefix', // info about command
group: 'settings', // command group (not displayed in !help [command name])
aliases: ['botprefix', 'newprefix'], // using these keywords also triggers command
usage: '[new prefix]', // how command is supposed to be used
cooldown: '1', // time command cannot be reused after it has been called
args: true, // are arguments required
execute(message, args) {
fs.exists("../config.json", function (error) {
if (error) {
console.log(error);
}
})
? fs
.readFile("../config.json", function (error) {
if (error) {
console.log(error);
}
})
.toString()
: config.prefix;
const newPrefix = args.shift().toString();
newConfig = {
token: config.token,
prefix: newPrefix,
};
fs.writeFile("config.json", JSON.stringify(newConfig, null, 2), function (
error
) {
if (error) {
console.log(error);
}
});
}
config.json:
{
"token": "token",
"prefix": "!"
}
If you want to access data via require, it won't be updated later as the function is run once at the beginnign of the project, even if you re-require it. This article can give you a bit more background on it. Basically: Always use fs.readFile and you're fine

Getting API latency inside of a commandhandler

Making a ping command for my bot,
want to show the api latency with Math.round(client.ws.ping), when I use it inside of my index.js, it works fine. When I use it inside of my ping command in my command handler, it won't work and returns to NaN.
Do I need to require something to use it?
Here is my code inside of ping.js
const Discord = require('discord.js');
const client = new Discord.Client();
const fs = require('fs');
module.exports = {
name: 'ping',
description: 'measures ping',
execute(message, args){
async function pingFunction(){
const embedPingtest = new Discord.MessageEmbed()
.setTitle('Pinging...')
.setColor(0xC1CCDE)
const msg = await message.channel.send(embedPingtest);
const embedPing = new Discord.MessageEmbed()
.setTitle('Pong!')
.setDescription("Bot Latency: ``" + Math.floor(msg.createdTimestamp - message.createdTimestamp) + " ms``\nAPI Latency: ``" + Math.round(client.ws.ping) + " ms``")
.setColor(0xC1CCDE)
console.log(apiLatency)
msg.edit(embedPing)
}
pingFunction()
}
}
This is because you create a new client instance. This one doesn't has a ping as it is not logged in so not online. I suggest you pass your old instance as function parameter, to make your code look something like:
const Discord = require('discord.js');
module.exports = {
name: 'ping',
description: 'measures ping',
execute(message, args, client) {
(async () => {
const embedPingtest = new Discord.MessageEmbed()
.setTitle('Pinging...')
.setColor(0xC1CCDE)
const msg = await message.channel.send(embedPingtest);
const embedPing = new Discord.MessageEmbed()
.setTitle('Pong!')
.setDescription("Bot Latency: ``" + Math.floor(msg.createdTimestamp - message.createdTimestamp) + " ms``\nAPI Latency: ``" + Math.round(client.ws.ping) + " ms``")
.setColor(0xC1CCDE)
console.log(apiLatency)
msg.edit(embedPing)
})();
}
}
I know most guides only make you using the structure of run(message, args) but in my bot I usually use message, args, client? (mine works different tho as I modified my module structure). This also won't throw an error in your code, as JS doesn't care how many arguments you pass or don't pass.
Instead of creating a new Discord.Client(), you could refer to Zer0's answer, or an even easier way would to just use the message object.
message has a client property, which will return the client that instantiated the message.
Instead of:
Math.round(client.ws.ping)
Use:
Math.round(message.client.ws.ping)

NodeJS - Accessing Array in Another Class File

I'm writing a NodeJS application that can do some queueing in Discord. My main includes an array called queuedPlayers and is defined in the following code:
// Define our required packages and our bot configuration
const fs = require('fs');
const config = require('./config.json');
const Discord = require('discord.js');
// Define our constant variables
const bot = new Discord.Client();
const token = config.Discord.Token;
const prefix = config.Discord.Prefix;
let queuedPlayers = [];
// This allows for us to do dynamic command creation
bot.commands = new Discord.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.name, command)
}
// Event Handler for when the Bot is ready and sees a message
bot.on('message', message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(' ');
const command = args.shift().toLowerCase();
if (!bot.commands.has(command)) return;
try {
bot.commands.get(command).execute(message, args);
} catch (error) {
console.error(error);
message.reply('There was an error trying to execute that command!');
}
});
// Start Bot Activities
bot.login(token);
I then create a command in a seperate JS file and I am trying to access the Queued Players array so that way I can add to them:
module.exports = {
name: "add",
description: "Adds a villager to the queue.",
execute(message, args, queuedPlayers) {
if (!args.length) {
return message.channel.send('No villager specified!');
}
queuedPlayers.push(args[0]);
},
};
However, it keeps telling me that it is undefined and can't read the attributes of the variable. So I'm assuming it isn't passing the array over properly. Do I have to use an exports in order to able to access it between different Javascript files? Or would it be best just to use a SQLite local instance to create and manipulate the queue as needed?
It's undefined because you aren't passing the array
Change
bot.commands.get(command).execute(message, args);
to
bot.commands.get(command).execute(message, args, queuedPlayers);

discord.js client.user.setPresence() breaks bot

My bot currently runs fine. I decided to add a 'playing ' status to it. This is the relevant code:
// Import the discord.js modules required
const Discord = require('discord.js');
// Create an instance of a Discord client
const client = new Discord.Client();
// Load config properties from 'config.json'
const config = require("./config.json");
const contest = config.contest;
// Set bots status to playing 'contest' defined in 'config.json'
client.user.setPresence({
game:{
name:contest
},
status:'online'
});
In 'config.json':
{
"contest": "Example Game"
}
When I add this, the bot no longer works, and appears offline. Any ideas?
EDIT:
Source of the information:
https://discord.js.org/#/docs/main/stable/class/ClientUser?scrollTo=setPresence
In the example section:
// Set the client user's presence
client.user.setPresence({ game: { name: 'with discord.js' }, status: 'idle' })
.then(console.log)
.catch(console.error);
You need to read the config, instead of
const config = require(...)
You need
const fs = require("fs");
const config = JSON.parse(fs.readFileSync("config.json"));
const contest = config.contest;
Then
game:{
name:contest
}
Figured it out - this needs to be placed inside an event, otherwise it's just floating code. For example, I placed this inside a
client.on('ready) event.

Categories

Resources