module.exports cannot find module - node.js

I wanted to make a help command for the bot which shows the prefix of the specific guild. Here is my help.js file :-
const Discord = require('discord.js');
module.exports = {
name: 'help',
description: 'Neptune Premium Commands',
execute(client, message, args){
const { guildPrefix } = require('../../main.js');
const embed = new Discord.MessageEmbed()
.setAuthor(`Prefix : ${guildPrefix}`, message.author.displayAvatarURL( {dynamic: true} ))
.setDescription(`Neptune Premium Commands List.`)
.addFields(
{name: `moderation`, value: '`kick` `ban` `lock` `unlock` `purge` `warn` `delwarn` `mute` `unmute`'},
{name: `utility`, value: '`prefix` `timedif` `greet` `userinfo` `serverinfo` `snipe`'},
{name: `misc`, value: '`help` `support` `vote` `invite`'}
)
.setFooter(message.guild.name, message.guild.iconURL( {dynamic: true} ))
message.channel.send(embed)
}
}
Once I use $help it shows Prefix as undefined
Here is my main.js file :-
const Discord = require('discord.js');
const client = new Discord.Client();
const fs = require('fs');
const config = require('./config.json');
const prefix = require('discord-prefix');
const defaultPrefix = config.prefix;
// .. ignoring some part of the code ...
client.on('message', message =>{
// prefix db part
if (!message.guild) return;
let guildPrefix = prefix.getPrefix(message.guild.id);
if (!guildPrefix) guildPrefix = defaultPrefix;
if(message.content === '<#!849854849351942144>'){
message.channel.send(`My Prefix is \`${guildPrefix}\`. Use \`${guildPrefix}help\` for my commands!`)
}
if(message.channel.type === 'dm') return;
// discord.js command handler
if(!message.content.startsWith(guildPrefix) || message.author.bot) return;
const args = message.content.slice(guildPrefix.length).split(/ +/);
const cmd = args.shift().toLowerCase();
const command = client.commands.get(cmd) || client.commands.find(command => command.aliases && command.aliases.includes(cmd));
// ...
I have ignored some part of the main code and only put the prefix part. I'm using a package called discord-prefix for this.

The reason why you're getting undefinded when requiring the prefix from your main.js is that you're never exporting a value.
If you'd want to get your prefix by using require you have to do this:
main.js
const serverPrefix = '!';
exports.prefix = serverPrefix;
// This would also work:
module.exports.prefix = serverPrefix;
help.js
const { prefix } = require('./main.js');
// Or:
const prefix = require('./main.js').prefix;
You can read more about exporting here
But you are using a npm package called discord-prefix and if you take a look at the examples you should notice that there are two interesting methods:
.setPrefix()
.getPrefix()
So if you want to get the prefix that you assigned in you main.js, in your help.js you have to use the .getPrefix() function. But before you can to this you have to set your prefix with .setPrefix() first:
main.js
const prefix = require('discord-prefix');
// This is optional, you could also use message.guild instead
const { guild } = message
if(!prefix.getPrefix(guild.id)) prefix.setPrefix('!', guild.id);
And after that you can get your prefix with the .getPrefix function:
help.js
const prefix = require('discord-require');
const { guild } = message;
const guildPrefix = prefix.getPrefix(guild.id);
Alternatively...
...you can use a .env file. This is much simpler (in my opinion) and I used it too, before moving all per-server-settings to a database. Therefore you have to install dotenv and create a file named .env
Now, if you want to set a prefix for your bot (not for specific servers) you want to set it like this:
Example
PREFIX = !
LOGINTOKEN = 1234567890
WELCOMECHANNEL = 3213213212321
// and so on...
Now that you have successfully created your .env file and defined some variables you have to require that new package in your main.js:
main.js
require ('dotenv').config()
Now you're ready to go and you can get your defined variables anywhere like this:
help.js
// You dont have to assign it to a variable
const prefix = process.env.PREFIX
// This schema will work for every variable you defined in .env:
process.env.LOGINTOKEN
process.env.WELCOMECHANNEL
// and so on...
Note
Please make sure you add the .env file to your .gitignore (if you're using git to store your code)

Related

Problem with node.js twitch bot shoutout command

When the !so command is used it works fine if you use "#" at the start of the username but if you just do !so without the # the username is deleted from the output.. here's my code.
client.on('message', (channel, tags, message, user, self) => {
if(self) return;
const badges = tags.badges || {};
const isBroadcaster = badges.broadcaster;
const isMod = badges.moderator;
const isModUp = isBroadcaster || isMod;
const args = message.slice(1).split(' ');
const command = args.shift().toLowerCase();
// so command
if(isModUp) {
if(command === 'so') {
const args = message.slice(1).split('#');
const command = args.shift().toLowerCase();
client.say(channel, `Go check out ${args.join(' ')}! www.twitch.tv/${args.join(' ')}`);
}
}
I tried changing "const args = message.slice(1).split('#');" to "const args = message.slice(1).split(' ');" but that method left the "#" in the output link.
I'm hoping to be able to use the command either by using !so "username" or !so "#username"
any help would be appreciated
The problem is that if you don't include the "#", the .split('#') is only converting your string into an array of one element. Then, the following .shift() is removing that unique element:
// message -> "!so user"
const args = message.slice(1).split('#');
// args -> ["so user"]
const command = args.shift().toLowerCase();
// args -> []
Just in case it can help you, I am removing the "#" if it is present. My "!so" command:
const commandArgs = message.split(' ');
const command = commandArgs.shift()?.toLowerCase?.();
// ...
const userName = commandArgs.shift();
if (userName[0] === '#') {
userName.shift(); // Here, userName is an string.
}
client.say(
channel,
`... #${userName}, ... -> https://twitch.tv/${userName}`
);

How to break a single node.js file into many?

Hi,
I have an app on node.js which consists of a single file app.js that looks like this:
//variables
app = require("express")();
//many more variables here
//functions
function dosomething {}
//many more functions here
but since its getting a little too long I would like to break it into several files, one for variables only (variables.js) and another one for functions only (functions.js) and load them from app.js like this like when you do it with php
//variables
include(variables.js);
//functions
include(functions.js);
is it even possible to do that? Or I have to include everything in one single file like I do now?
Thank you.
You can use Module.Export to export a separate file, and import it into another file using the require statement. Please check here for details:
https://www.geeksforgeeks.org/import-and-export-in-node-js/
Happy Learning :-)
Importing API Endpoints
You can do this by using app.use(...) and point each endpoint to a specific file like so:
const express = require("express");
const app = express();
// User Functions
app.use("/api/user", require("./routes/api/user"));
//Orders functions
app.use("/api/orders/", require("./routes/api/orders"));
/**
* Express Server Init
*/
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on ${PORT}`));
Then in /routes/api/user/user.js you would have something like:
const express = require("express");
const router = express.Router();
router.post("/create", (req, res) => {
try {
// Create user
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
module.exports = router;
Add and index.js inside /routes/api/user to point at the user file to keep things pretty when importing (otherwise you have to import it like /routes/api/user/user):
const user = require("./user");
module.exports = user;
Importing Single File
Not sure your use case but variables could be a bad naming convention since these values are more like constants than variables. Either way, you create it like this:
const variables = {
varibleOne: "valueOne",
varibleTwo: "valueTwo",
varibleThree: "valueThree",
};
module.exports = variables;
Then wherever you want to import it you can do:
const variables = require("./variables");
and access it like so variables.variableOneand so on.
Importing functions
You can also import different functions, say you need a file called helper.js where these are commonly functions needed all over you app, you could do something like this:
const twoDecimals = (number, decimal = ",") => {
let val = (Math.round(number * 100) / 100).toFixed(2);
return decimal === "." ? val : val.replace(".", decimal);
};
const getRandomInt = (max) => {
return Math.floor(Math.random() * Math.floor(max));
};
module.exports = { twoDecimals, getRandomInt };
Then wherever you needed you can import it by:
const { twoDecimals } = require("helper.js");
Now you have access to your helper functions anywhere.
You should get help from the JavaScript modular system (preferably COMMONJS).
For example, suppose we have two files:
1-module.js 2-app.js
So now let's create this files
module.js
let name = "hello world";
function printSomething(message) {
console.log(message)
}
//here export all function and variable
module.exports.name = name;
module.exports.printSomething = printSomething
ok so Well now it is enough that "require" this file in main file :
main.js
// we
const {name, printSomething} = require("./module.js");
printSomething(name);
for export all variable You need to create an object and specify your variables as a property:
let host = "localhost"
let dbname = "laravel_8"
let username = "root"
let password = "root"
function doSomething() {
console.log("hello");
}
module.exports = {host, dbname, username, password, doSomething}
so in main file :
const variables = require("./module.js")
//host
let host = variables.host
//dbname
let dbname = variables.dbname
//function doSomething
let doSomething = variables.doSomething;
doSomething()
// or directly
variables.doSomething()
In fact, in php we use the "->" symbol to access properties, and in JavaScript we use "."

How would I write a changed variable to my config.js file for a permanent change?

My Problem
I am currently writing a Discord bot to be used on one server at the moment. I have set up a command that will change the prefix of the bot's commands but as soon as I restart my repl, it resets to the original prefix. I would like to change the command so that it will write to my config.js file to stop this from happening.
What I've Tried So Far
To be honest, I haven't tried anything yet as I have no idea where to start
My code Files
config.js file:
var config={};
config.token = "My Bot Token";
config.prefix = "//";
config.statusMessage = "video games | (" + config.prefix + "help)";
config.dbltoken = undefined;
module.exports = config;
change-prefix.js file:
config = require('../config.js');
module.exports = (client, message, args) => {
config.prefix = args;
message.reply("Prefix has been changed to: " + config.prefix);
console.log("Command Used: Change-Prefix");
}
What Should Happen
The change-prefix.js file should successfully write the new prefix determined by the user to the config.js file. At this moment in time, I have no errors, but I would like to change this as it would vastly improve the user experience for my bot.
If you want to write the file, you can use fs module. The code below saves custom prefix to prefix.txt file and checks if it exists every time you start your repl. If not, it's using the default value.
Note: the code doesn't have any error handling or any other features, it's just a simple code to show you the idea. In real life scenario, you'll probably want to save your prefix to database, add per-server prefix setting, filter messages from other bots, include prefix in command invocation. Just one more thing - please put Discord token in .env, not in config file.
const Discord = require('discord.js');
const fs = require('fs');
const config = require('./config.js');
const client = new Discord.Client();
// If prefix.txt exist, use it. Otherwise, get data from config file
let prefix = fs.existsSync('prefix.txt') ? fs.readFileSync('prefix.txt').toString() : config.prefix;
client.on('message', (msg) => {
// 'set prefix XXX' to change your prefix to XXX
if (/^set prefix /i.exec(msg.content)) {
const newPrefix = msg.content.split(' ')[2];
fs.writeFile("./prefix.txt", newPrefix, function(err) {
if(err) {
return console.log(err);
}
prefix = newPrefix;
console.log(`Prefix changed to ${prefix}`);
});
}
// 'show prefix' to show current prefix
if (/^show prefix/i.exec(msg.content)) {
console.log(`Prefix is ${prefix}`);
};
});
client.on('ready', () => {
console.log(`I'm in`);
});
client.login(process.env.DISCORD_TOKEN);

How to pass a variable from one module to another?

I know there may be a duplicate question but I've been reading and really struggling to understand and figure out how to pass a variable from a command module into an event module shown below.
Command:
exports.run = async (client, message, args) => {
const embed = new Discord.RichEmbed()
.addField(':heart:', `${xb.toString()}`, true)
.addField(':black_heart:', `${ps.toString()}`, true)
.addField(':yellow_heart:', `${nin.toString()}`, true)
.addField(':purple_heart:', `${pcmr.toString()}`, true)
message.channel.send(embed).then(async msg => {
let embedid = msg.id;
module.exports.embedid = embedid;
await msg.react('❤');
await msg.react('🖤');
await msg.react('💛');
await msg.react('💜');
});
}
Event:
module.exports = async (client, messageReaction, user) => {
const message = messageReaction.message;
const channel = message.guild.channels.find(c => c.name === 'role-assignment');
const member = message.guild.members.get(user.id);
if(member.user.bot) return;
const xb = message.guild.roles.get('540281375106924555');
const ps = message.guild.roles.get('540296583632388115');
const nin = message.guild.roles.get('540296630260203520');
const pcmr = message.guild.roles.get('540296669733060618');
if(['❤', '🖤', '💛', '💜'].includes(messageReaction.emoji.name) && message.channel.id === channel.id && messageReaction.message.id === embedid) {};
I'm hoping to pass embedid, embed2id and so on to the event module so I can filter by the message ID that is generated when sending the RichEmbed()
Thanks in advance, I've been running in circles for days!
So I figured it out by looking into what exports actually do, which really, should have been the first thing I did, here :
What is the purpose of Node.js module.exports and how do you use it?
Using the info learned here, I made the following changes to my event:
const e1 = require('../commands/startroles'); // At the top of my messageReactionAdd.js file before module.exports[...]
messageReaction.message.id === e1.embedid // added the e1. to import the variable.

node.js require all files in a folder?

How do I require all files in a folder in node.js?
need something like:
files.forEach(function (v,k){
// require routes
require('./routes/'+v);
}};
When require is given the path of a folder, it'll look for an index.js file in that folder; if there is one, it uses that, and if there isn't, it fails.
It would probably make most sense (if you have control over the folder) to create an index.js file and then assign all the "modules" and then simply require that.
yourfile.js
var routes = require("./routes");
index.js
exports.something = require("./routes/something.js");
exports.others = require("./routes/others.js");
If you don't know the filenames you should write some kind of loader.
Working example of a loader:
var normalizedPath = require("path").join(__dirname, "routes");
require("fs").readdirSync(normalizedPath).forEach(function(file) {
require("./routes/" + file);
});
// Continue application logic here
I recommend using glob to accomplish that task.
var glob = require( 'glob' )
, path = require( 'path' );
glob.sync( './routes/**/*.js' ).forEach( function( file ) {
require( path.resolve( file ) );
});
Base on #tbranyen's solution, I create an index.js file that load arbitrary javascripts under current folder as part of the exports.
// Load `*.js` under current directory as properties
// i.e., `User.js` will become `exports['User']` or `exports.User`
require('fs').readdirSync(__dirname + '/').forEach(function(file) {
if (file.match(/\.js$/) !== null && file !== 'index.js') {
var name = file.replace('.js', '');
exports[name] = require('./' + file);
}
});
Then you can require this directory from any where else.
Another option is to use the package require-dir which let's you do the following. It supports recursion as well.
var requireDir = require('require-dir');
var dir = requireDir('./path/to/dir');
I have a folder /fields full of files with a single class each, ex:
fields/Text.js -> Test class
fields/Checkbox.js -> Checkbox class
Drop this in fields/index.js to export each class:
var collectExports, fs, path,
__hasProp = {}.hasOwnProperty;
fs = require('fs');
path = require('path');
collectExports = function(file) {
var func, include, _results;
if (path.extname(file) === '.js' && file !== 'index.js') {
include = require('./' + file);
_results = [];
for (func in include) {
if (!__hasProp.call(include, func)) continue;
_results.push(exports[func] = include[func]);
}
return _results;
}
};
fs.readdirSync('./fields/').forEach(collectExports);
This makes the modules act more like they would in Python:
var text = new Fields.Text()
var checkbox = new Fields.Checkbox()
One more option is require-dir-all combining features from most popular packages.
Most popular require-dir does not have options to filter the files/dirs and does not have map function (see below), but uses small trick to find module's current path.
Second by popularity require-all has regexp filtering and preprocessing, but lacks relative path, so you need to use __dirname (this has pros and contras) like:
var libs = require('require-all')(__dirname + '/lib');
Mentioned here require-index is quite minimalistic.
With map you may do some preprocessing, like create objects and pass config values (assuming modules below exports constructors):
// Store config for each module in config object properties
// with property names corresponding to module names
var config = {
module1: { value: 'config1' },
module2: { value: 'config2' }
};
// Require all files in modules subdirectory
var modules = require('require-dir-all')(
'modules', // Directory to require
{ // Options
// function to be post-processed over exported object for each require'd module
map: function(reqModule) {
// create new object with corresponding config passed to constructor
reqModule.exports = new reqModule.exports( config[reqModule.name] );
}
}
);
// Now `modules` object holds not exported constructors,
// but objects constructed using values provided in `config`.
I know this question is 5+ years old, and the given answers are good, but I wanted something a bit more powerful for express, so i created the express-map2 package for npm. I was going to name it simply express-map, however the people at yahoo already have a package with that name, so i had to rename my package.
1. basic usage:
app.js (or whatever you call it)
var app = require('express'); // 1. include express
app.set('controllers',__dirname+'/controllers/');// 2. set path to your controllers.
require('express-map2')(app); // 3. patch map() into express
app.map({
'GET /':'test',
'GET /foo':'middleware.foo,test',
'GET /bar':'middleware.bar,test'// seperate your handlers with a comma.
});
controller usage:
//single function
module.exports = function(req,res){
};
//export an object with multiple functions.
module.exports = {
foo: function(req,res){
},
bar: function(req,res){
}
};
2. advanced usage, with prefixes:
app.map('/api/v1/books',{
'GET /': 'books.list', // GET /api/v1/books
'GET /:id': 'books.loadOne', // GET /api/v1/books/5
'DELETE /:id': 'books.delete', // DELETE /api/v1/books/5
'PUT /:id': 'books.update', // PUT /api/v1/books/5
'POST /': 'books.create' // POST /api/v1/books
});
As you can see, this saves a ton of time and makes the routing of your application dead simple to write, maintain, and understand. it supports all of the http verbs that express supports, as well as the special .all() method.
npm package: https://www.npmjs.com/package/express-map2
github repo: https://github.com/r3wt/express-map
Expanding on this glob solution. Do this if you want to import all modules from a directory into index.js and then import that index.js in another part of the application. Note that template literals aren't supported by the highlighting engine used by stackoverflow so the code might look strange here.
const glob = require("glob");
let allOfThem = {};
glob.sync(`${__dirname}/*.js`).forEach((file) => {
/* see note about this in example below */
allOfThem = { ...allOfThem, ...require(file) };
});
module.exports = allOfThem;
Full Example
Directory structure
globExample/example.js
globExample/foobars/index.js
globExample/foobars/unexpected.js
globExample/foobars/barit.js
globExample/foobars/fooit.js
globExample/example.js
const { foo, bar, keepit } = require('./foobars/index');
const longStyle = require('./foobars/index');
console.log(foo()); // foo ran
console.log(bar()); // bar ran
console.log(keepit()); // keepit ran unexpected
console.log(longStyle.foo()); // foo ran
console.log(longStyle.bar()); // bar ran
console.log(longStyle.keepit()); // keepit ran unexpected
globExample/foobars/index.js
const glob = require("glob");
/*
Note the following style also works with multiple exports per file (barit.js example)
but will overwrite if you have 2 exports with the same
name (unexpected.js and barit.js have a keepit function) in the files being imported. As a result, this method is best used when
your exporting one module per file and use the filename to easily identify what is in it.
Also Note: This ignores itself (index.js) by default to prevent infinite loop.
*/
let allOfThem = {};
glob.sync(`${__dirname}/*.js`).forEach((file) => {
allOfThem = { ...allOfThem, ...require(file) };
});
module.exports = allOfThem;
globExample/foobars/unexpected.js
exports.keepit = () => 'keepit ran unexpected';
globExample/foobars/barit.js
exports.bar = () => 'bar run';
exports.keepit = () => 'keepit ran';
globExample/foobars/fooit.js
exports.foo = () => 'foo ran';
From inside project with glob installed, run node example.js
$ node example.js
foo ran
bar run
keepit ran unexpected
foo ran
bar run
keepit ran unexpected
One module that I have been using for this exact use case is require-all.
It recursively requires all files in a given directory and its sub directories as long they don't match the excludeDirs property.
It also allows specifying a file filter and how to derive the keys of the returned hash from the filenames.
Require all files from routes folder and apply as middleware. No external modules needed.
// require
const { readdirSync } = require("fs");
// apply as middleware
readdirSync("./routes").map((r) => app.use("/api", require("./routes/" + r)));
I'm using node modules copy-to module to create a single file to require all the files in our NodeJS-based system.
The code for our utility file looks like this:
/**
* Module dependencies.
*/
var copy = require('copy-to');
copy(require('./module1'))
.and(require('./module2'))
.and(require('./module3'))
.to(module.exports);
In all of the files, most functions are written as exports, like so:
exports.function1 = function () { // function contents };
exports.function2 = function () { // function contents };
exports.function3 = function () { // function contents };
So, then to use any function from a file, you just call:
var utility = require('./utility');
var response = utility.function2(); // or whatever the name of the function is
Can use : https://www.npmjs.com/package/require-file-directory
Require selected files with name only or all files.
No need of absoulute path.
Easy to understand and use.
Using this function you can require a whole dir.
const GetAllModules = ( dirname ) => {
if ( dirname ) {
let dirItems = require( "fs" ).readdirSync( dirname );
return dirItems.reduce( ( acc, value, index ) => {
if ( PATH.extname( value ) == ".js" && value.toLowerCase() != "index.js" ) {
let moduleName = value.replace( /.js/g, '' );
acc[ moduleName ] = require( `${dirname}/${moduleName}` );
}
return acc;
}, {} );
}
}
// calling this function.
let dirModules = GetAllModules(__dirname);
Create an index.js file in your folder with this code :
const fs = require('fs')
const files = fs.readdirSync('./routes')
for (const file of files) {
require('./'+file)
}
And after that you can simply load all the folder with require("./routes")
If you include all files of *.js in directory example ("app/lib/*.js"):
In directory app/lib
example.js:
module.exports = function (example) { }
example-2.js:
module.exports = function (example2) { }
In directory app create index.js
index.js:
module.exports = require('./app/lib');

Resources