Javascript Discord Bot Error (Function Error) - javascript

I always get an error message after adding the reload command.
Without the Reload Command, the bot works with all commands without any problems
Without the Reload Command, the bot works with all commands without any problems
I just can't find the mistake
The error message:
undefined commands found.
/home/runner/Discord-BreakpointBot/index.js:19
delete require.cache[require.resolve(`./commands/${f}`)];
^
TypeError: require.resolve is not a function
Code:
function loadCmds () {
fs.readdir('./commands/', (err, files) => {
if(err) console.error(err);
var jsfiles = files.filter(f => f.split('.').pop() === 'js');
if (jsfiles.length <=0) {return console.log('No commands found...')}
else {console.log(jsfiles.lenght + ' commands found.')}
jsfiles.forEach((f,i) => {
delete require.cache[require.resolve(`./commands/${f}`)];
var cmds = require(`./commands/${f}`);
console.log(`Command ${f} loading...`);
bot.commands.set(cmds.config.command, cmds);
})
})
}
bot.on('message', message => {
var sender = message.author;
var msg = message.content.toUpperCase();
var prefix ='>'
var cont = message.content.slice(prefix.length).split(" ");
var args = cont.slice(1);
if (!message.content.startsWith(prefix)) return;
var cmd = bot.commands.get(cont[0])
if (cmd) cmd.run(bot, message, args);
if (msg === prefix + 'RELOAD') {
message.channel.send({embed:{description:"All Commands Reloaded"}})
message.channel.send('All Commands Reloaded')
loadCmds()
}
});
loadCmds();
// Bot Launched
bot.on('ready', () => {
console.log('Bot Launched...')
bot.user.setStatus('Online')
bot.user.setActivity('https://www.twitch.tv');
});
I hope someone can help, thanks

I'm not 100% sure what causes your error but I can offer you my method of retrieving comamnds, which works pretty well:
const fileArray = [];
function readCommands(dir) {
const __dirname = rootDir;
// Read out all command files
const files = fs.readdirSync(path.join(__dirname, dir));
// Loop through all the files in ./commands
for (const file of files) {
// Get the status of 'file' (is it a file or directory?)
const stat = fs.lstatSync(path.join(__dirname, dir, file));
// If the 'file' is a directory, call the 'readCommands' function
// again with the path of the subdirectory
if (stat.isDirectory()) {
readCommands(path.join(dir, file));
}
else {
const fileDir = dir.replace('\\', '/');
fileArray.push(fileDir + '/' + file);
// fs.readdirSync(dir).filter(cmdFile => cmdFile.endsWith('.js'));
}
}
}
readCommands('commands');
for(const file of fileArray) {
const command = require(`../${file}`);
if(command.name) {
client.commands.set(command.name, command);
}
else {
continue;
}
}
This will recursively search the folder you specify when calling the function and then store it in fileArray.
This solution is more an alternative than an exact solution to the error you are experiencing

Related

command handler only recognize the top-most folder instead of all the folders

i have a problem, my Command Handler only recognize the top Folder inside my Commands Directory. Its supposed to show all of the available Folder in Commands Directory but it only showed the 'test' category which is the top one. any help would be really appreciated.
Folder/Directory Construction:
console.log output:
Command Handler Code:
const {readdirSync} = require('fs');
const ascii = require('ascii-table');
let table = new ascii("Commands");
table.setHeading('Category', 'Command', ' Load status');
var logged = false;
const path = require('node:path')
module.exports = (client) => {
readdirSync('./Commands/').forEach(dir => {
var commands = readdirSync(`./Commands/${dir}/`).filter(file => file.endsWith('.js'));
for(let file of commands){
let pull = require(`../Commands/${dir}/${file}`);
if(pull.name){
client.commands.set(pull.name, pull);
table.addRow(dir,file,'✔️ -> Command Loaded')
} else {
table.addRow(dir,file,'❌ -> Command Error')
continue;
}
if(pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach(alias => client.aliases.set(alias, pull.name))
}
if(!logged) {
console.log(table.toString())
console.log(`[Command] Command Handler is Ready! | Total Commands: ${commands.length}`)
logged = true
}
});
}
I believe you are overwriting the commands variable after each folder has been looped through. Try this:
const {readdirSync} = require('fs');
const ascii = require('ascii-table');
let table = new ascii("Commands");
table.setHeading('Category', 'Command', ' Load status');
var logged = false;
const path = require('node:path')
module.exports = (client) => {
readdirSync('./Commands/').forEach(dir => {
var commands = []
commands.push(readdirSync(`./Commands/${dir}/`).filter(file => file.endsWith('.js')));
for(let file of commands){
let pull = require(`../Commands/${dir}/${file}`);
if(pull.name){
client.commands.set(pull.name, pull);
table.addRow(dir,file,'✔️ -> Command Loaded')
} else {
table.addRow(dir,file,'❌ -> Command Error')
continue;
}
if(pull.aliases && Array.isArray(pull.aliases)) pull.aliases.forEach(alias => client.aliases.set(alias, pull.name))
}
if(!logged) {
console.log(table.toString())
console.log(`[Command] Command Handler is Ready! | Total Commands: ${commands.length}`)
logged = true
}
});
}
If this doesn't help than it might still be that issue I referred to above but the edits I made might not be compatible with your code.

Reload main page after data changes

I have an app that, when it is starting, loads a bunch of files from a directory in the underlying OS, after this it presents a page (generated with PUG, if it makes any difference) that shows the the list of loaded files to the user and if one is clicked it shows the contents. One of the buttons on the page allows the user to create a new file (by spawning a system command based on the user's input).
My question is how do I reload the main page after the new file is created so that the web page now shows the new file that was added. In the future there will be a feature to delete a file as well, so I will also need to reload after this to show that the file has been deleted.
TIA for any assistance.
Code is short enough that I can include it here (please let me know if I am doing this the long difficult way, I am jut learning)
index.js
const express = require('express')
const app = express();
const port = 8000;
app.use(express.json());
app.use(express.static(__dirname + "/public"));
app.set('view engine', 'pug');
const { exec } = require('child_process');
// Read profile names
const profileFolder = '/home/pi/configs/';
const fs = require('fs');
var profiles = [];
function init() {
profiles = fs.readdirSync(profileFolder);
for (var i = 0; i < profiles.length; i++) {
try {
profile = fs.readFileSync(profileFolder + profiles[i], 'utf8');
profiles[i] = {
pname: profiles[i].split('.')[0],
profile: profile
};
}
catch (err) {
console.error(err);
}
};
}
app.get('/', function(req, res) {
init();
res.render(__dirname + '/views/index.pug', {vpnprofiles: profiles});
});
app.get('/addnew', function(req, res) {
let pname = req.query.newprofile;
console.log(`Adding new profile: ${pname}`);
exec("pivpn -a -n "+pname, (error, stdout, stderr) => {
if (error) {
console.log(`ERROR: ${error.message}`);
return;
}
if (stderr) {
console.log(`STDERR: ${stderr}`);
return;
}
console.log(`${stdout}`);
res.send("Done!");
});
return;
});
app.listen(port, () => {
console.log(`Server started on port ${port}!`)
});
/public/script.js
function genQRcode(p, n) {
const nl = '\n';
const rep = '<br>'
document.getElementById("qrcode").innerHTML = "";
document.getElementById("profile").innerHTML = "";
document.getElementById("title").innerHTML = "Profile Details (" + n + ")";
new QRCode(document.getElementById("qrcode"), p);
document.getElementById("profile").style.padding = "10px";
document.getElementById("profile").innerHTML = p.replaceAll(nl, rep);
}
// Create a new profile
function addn(pn) {
console.log(pn);
var newname = prompt("Enter profile name:", "");
if ((newname != null) && (newname != "")) {
var found = false;
for (var i = 0; i < pn.length; i++) {
if (pn[i]['pname'] == newname) {
found = true;
}
}
if (!found) {
fetch(`/addnew?newprofile=${newname}`).then((messages) => {console.log("messages");});
}
else { alert("profile already exists"); }
}
window.location = "http://192.168.1.3:8000/";
window.location.reload(true);
//return failse;
}
and finally the pug file
doctype html
html
head
meta(charset='utf-8')
title PiVPN Profiles
script !{addnew}
script(src='../scripts/qrcode.js')
script(src='../scripts/script.js')
link(rel="stylesheet", type="text/css", href="../styles/style.css")
body
.grid
.box.nav
a(href='/') Home
.btn(onclick=`addn(${JSON.stringify(vpnprofiles)});`) New Profile
.box.sidebar
h2 Profiles
ul
each prof in vpnprofiles
li(onclick=`genQRcode(${JSON.stringify(prof.profile)},${JSON.stringify(prof.pname)})`)=prof.pname
.box.content
h1#title Profile Details
p.qrcode#qrcode
p.profile#profile
.box.footer
p.small Version: 0.1a
Maybe I am reading this wrong, but can you make use of window.location = 'yourpage' (a client-side JS solution) or similar page refresh techniques?

I am getting an error Typerror Cannot read property 'execute' of undefined

My main code I am trying to make a discord bot i was getting this error Typerror Cannot read property of 'execute' undefined i have literally every solution but it still has some errors would be grateful if someone solved it. I am trying to make a simple discor bot but the code does not only work please hlep .
const client = new Discord.Client();
const prefix = '-';
const fs = require('fs');
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);
}
client.once('ready', () => {
console.log('yes its online');
});
client.on('message', message =>{
if(!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
client.on('guildMemberAdd', member =>{
const channel = member.guild.channels.cache.find(channel=> channel.name === "hlo");
if(!channel) return;
channel.send(`Welcome to our server , ${member}, please read the rules!`);
});
if(command === 'ping'){
message.channel.send('pong!');
}
if (command == 'kick'){
client.commands.get('kick').execute(message, args);
}
if (command === 'ban'){
client.commands.get('ban').execute(message, args);
}
}); ```
My ban code
```module.exports = {
name: 'ban',
description: "Uses ban hammer",
execute(messsage, args){
if (command === "ban"){
const userBan = message.mentions.users.first();
if(userBan){
var member = message.guild.member(userBan);
if(member) {
member.ban({
reason: 'you broke rules buddy.'
}).then(() => {
message.reply(`${userBan.tag} was banned from the server.`)
})
} else{
message.reply('that user is not in the server.');
}
}else {
message.reply('you need to state a user to ban')
}
}
}
my kick code
module.exports = {
name: 'kick',
description: 'kick people',
execute(messsage, args){
if (command === "kick"){
const userKick = message.mentions.users.first();
if(userBan){
var member = message.guild.member(userKick);
if(member) {
member.kick({
reason: 'you broke rules buddy.'
}).then(() => {
message.reply(`${userKick.tag} was kicked from the server.`)
})
} else{
message.reply('that user is not in the server.');
}
}else {
message.reply('you need to state a user to kick')
}
}
}```
To make this work you need to do two things.
First you need to separate your on('guildMemberAdd') from your on('message') event. Right now they are bungled together and that won't work.
So your index file should be
// your command reader above this
client.once('ready', () => {
console.log('yes its online');
});
client.on('guildMemberAdd', member => {
// your code
}
client.on('message', message => {
// here we will work in part two
}
Secondly, lets take a look at your command reader. That portion of your code looks good to me. Make sure that your commands folder is in the same directory as your index file. This is where I assume your problem lies.
Note: I say "index file" here. What I mean by that is the file you have the client.login() function in. It might be bot.js or something similar for you.
Your folder structure should looks something like this
-- Your bot folder
- index.js
- package.json
- package-lock.json
-- commands (this is a folder)
- kick.js
- ban.js
Note: Just to make sure, here is a command reader that definetly works with the above file structure.
// Read all files in the commands folder and that ends in .js
const commands = fs.readdirSync('./commands/').filter(file => file.endsWith('.js'));
// Loop over the commands, and add all of them to a collection
// If there's no name found, prevent it from returning an error
for (let file of commands) {
const command = require(`./commands/${file}`);
// Check if the command has both a name and a description
if (command.name && command.description) {
client.commands.set(command.name, command);
} else {
console.log("A file is missing something");
continue;
}
// check if there is an alias and if that alias is an array
if (command.aliases && Array.isArray(command.aliases))
command.aliases.forEach(alias => client.aliases.set(alias, command.name));
};
Your command handler inside your client.on('message' event works for me. So I assume you have your problem with the folder structure.
That being said, I would like to suggest you use a slightly different way of handling your commands. Currently you need to manually add a command to your if chain. Thats not really efficient.
Ideally you want to do that automatically. You already have your arguments and your command word sparated. All you need to do now is check if that command exists and if it does, execute it.
// check if there is a message after the prefix
if (command.length === 0) return;
// look for the specified command in the collection of commands
let cmd = client.commands.get(command);
// if there is no command we return with an error message
if (!cmd) return message.reply(`\`${prefix + command}\` doesn't exist!`);
// finally run the command
cmd.execute(message, args);
Your client.on('message' event should now look a little something like this.
client.on('message', message => {
// check if the author is a bot
if (message.author.bot) return;
// check if the message comes through a DM
if (message.guild === null) return;
// check if the message starts with the prefix
if (!message.content.startsWith(prefix)) return;
// slice off the prefix and convert the rest of the message into an array
const args = message.content.slice(prefix.length).trim().split(/ +/g);
// convert all arguments to lowercase
const command = args.shift().toLowerCase();
// check if there is a message after the prefix
if (command.length === 0) return;
// look for the specified command in the collection of commands
let cmd = client.commands.get(command);
// if there is no command we return with an error message
if (!cmd) return message.reply(`\`${prefix + command}\` doesn't exist!`);
// finally run the command
cmd.execute(message, args);
});
Note: I also noticed that you have some inconsistencies in your commands. But I assume that once you actually get to the commands you will be able to figure that out yourself 😉

Javascript - Moving Files between Directories

I have a folder called 'Received' and two more folders called 'Successful' and 'Error'.
All new files will be stored in the 'Received' Folder and upon being stored in the said folder, it will be processed by my system. Successfuly parsed files will be moved to the 'Successful' folder, while all files that had issues will be stored in the 'Error' folder.
My main concern is basically moving files between directories.
I have tried this:
// oldPath = Received Folder
// sucsPath = Successful Folder
// failPath = Error Folder
// Checks if Successful or fail. 1 = Success; 0 = Fail
if(STATUS == '1') { // 1 = Success;
fs.rename(oldPath, sucsPath, function (err) {
if (err) {
if (err.code === 'EXDEV') {
var readStream = fs.createReadStream(oldPath);
var writeStream = fs.createWriteStream(sucsPath);
readStream.on('error', callback);
writeStream.on('error', callback);
readStream.on('close', function () {
fs.unlink(oldPath, callback);
});
readStream.pipe(writeStream);
}
else {
callback(err);
}
return;
}
callback();
});
}
else { // 0 = Fail
fs.rename(oldPath, failPath, function (err) {
if (err) {
if (err.code === 'EXDEV') {
var readStream = fs.createReadStream(oldPath);
var writeStream = fs.createWriteStream(failPath);
readStream.on('error', callback);
writeStream.on('error', callback);
readStream.on('close', function () {
fs.unlink(oldPath, callback);
});
readStream.pipe(writeStream);
}
else {
callback(err);
}
return;
}
callback();
});
}
But my concern here is that it deletes the original folder and passes all files into the specified folder. I believe the logic in the code is that, it literally renames the file (directory included). I also came across 'await moveFile' but it basically does the same thing.
I just want to move files between directories by simply specifying the file name, the origin of the file, and its destination.
As mentioned by rufus1530, I used this:
fs.createReadStream(origin).pipe(fs.createWriteStream(destination));
Deleting the file would be the next step.
I used this:
fs.unlinkSync(file);
Starting with 8.5 you have fs.copyFile which the easiest way to copy files.
So you would create your own move function, that would first try a rename and then a copy.
const util = require('util')
const copyFile = util.promisify(fs.copyFile)
const rename = util.promisify(fs.rename)
const unlink = util.promisify(fs.unlink)
const path = require('path')
async function moveFileTo(file, dest) {
// get the file name of the path
const fileName = path.basename(file)
// combine the path of destination directory and the filename
const destPath = path.join(dest, fileName)
try {
await fs.rename(file, destPath)
} catch( err ) {
if (err.code === 'EXDEV') {
// we need to copy if the destination is on another parition
await copyFile(file, destPath)
// delete the old file if copying was successful
await unlink(file)
} else {
// re throw the error if it is another error
throw err
}
}
}
Then you could use it that way await moveFileTo('/path/to/file.txt', '/new/path') which will move /path/to/file.txt to /new/path/file.txt.

run multiple Jars in a given order with nodejs

I want to run two jars one after the other with nodejs but it seems like my program only stars the first jar :
The exec function :
execute a single shell command where "cmd" is a string
exports.exec = function(cmd, cb){
// this would be way easier on a shell/bash script :P
var child_process = require('child_process');
var parts = cmd.split(/\s+/g);
var p = child_process.spawn(parts[0], parts.slice(1), {stdio: 'inherit'});
p.on('exit', function(code){
var err = null;
if (code) {
err = new Error('command "'+ cmd +'" exited with wrong status code "'+ code +'"');
err.code = code;
err.cmd = cmd;
}
if (cb) cb(err);
});
};
Execute multiple commands in series this could be replaced by any flow control lib :
exports.series = function(cmds, cb){
var execNext = function(){
exports.exec(cmds.shift(), function(err){
if (err) {
cb(err);
} else {
if (cmds.length) execNext();
else cb(null);
}
});
};
execNext();
};
My use case :
shell.series([
`java -jar ${appDir}integration-tests/e2e-tests/tests/perf/uxcast-stub-0.27.0-jar-with-dependencies.jar`,
`java -jar ${appDir}integration-tests/e2e-tests/tests/perf/uxcast-app-0.27.0.jar`,
], err => {
if (err !== null) {
console.log('UXCAST ERROR -> ' + err);
return;
}
expect(startBrowser()).toBe('stuff');
done();
});
What I'm doing wrong ?

Categories