How can I take multiple words as one argument in Discord.Js - node.js

I want to make a command like !ban <mentioned_user> <reason>.
But I tried many ways to do but nothing suits for my code, I want to get the reason string as args[1].
I used this code to fetch all arguments and to store all argument in args variable...
let messageArray = message.content.split(" ");
let command = messageArray[0].toLowerCase();
let args = messageArray.slice(1);

Try something like that
const argument = msg.content.trim().split(/ +/g);
const comand = argument.shift().toLowerCase();
if(comand === `${prefix}ban`) {
const user = argument[0];
const reason = argument.slice(1).join(' ');
// ban user
}

If I understand well, message.content contains "<mentioned_user> <reason>"
If I'm correct, you can get each in a variable and then do what you want with it
const [mentionedUser, ...arrRreason] = message.content.split(" ");
const reason = arrReason.join(' ');
// or
const reason = message.content.substring(message.content.indexOf(' ') + 1);

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}`
);

Taking Words/Or Arguements from a string in discord.js

So what I want to do with my bot is basically take words from a user and pass it in the command as arguments when the arguments are seperated by a $ sign. For example, if the user types cat$dog$cute, the program should take 'cat' , 'dog' and 'cute' as the arguments.
const Discord = require('discord.js')
const settings = {
prefix:'suk!',
}
module.exports = {
name:'booru',
description:'this is a picture command',
execute(client,message){
const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
const Booru = require('booru')
const tags1 = args.slice(0, args.indexOf("$"));
const tags2 = args.slice(0, args.indexof("$"));
Booru.search('gelbooru', [`${tags1}`, `${tags2}`], { limit: 1, random: true })
.then(posts => {
for (let post of posts)
embed1 = new Discord.MessageEmbed()
.setTitle(`Aqua`)
.setColor("RED")
.setImage(post.fileUrl)
message.channel.send(embed1)
})
// or (using alias support and creating boorus)
}
}
``` this code is like a reference
Here is a simple way of doing that:
let tags = args.map(arg => arg.split("$")).flat()
Given, for example,
const args = ["cat$dog$cute", "hey$world"];
this will produce the result of
["cat", "dog", "cute", "hey", "world"]
If instead you only wanted to split a single one of the arguments into tags, simply use string.split
let arg = args[0];
let tags = arg.split("$");

module.exports cannot find module

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)

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.

Is there a module equivalent of Python's argparse for node.js?

argparse for python makes it quick and easy to handle command-line input, handling positional arguments, optional arguments, flags, input validation and much more. I've started writing applications in node.js and I'm finding it tedious and time consuming to write all that stuff manually.
Is there a node.js module for handling this?
There is one direct port, conveniently also called argparse.
There are a slew of various command line argument handlers at https://github.com/joyent/node/wiki/modules#wiki-parsers-commandline
The one I use in most projects is https://github.com/visionmedia/commander.js though I would take a look at all of them to see which one suits your specific needs.
In 18.3.0 nodejs has landed a core addition util.parseArgs([config])
Detailed documentation is available here: https://github.com/pkgjs/parseargs#faqs
There's yargs, which seems to be pretty complete and well documented.
Here is some simple boilerplate code which allows you to provide named args:
const parse_args = () => {
const argv = process.argv.slice(2);
let args = {};
for (const arg of argv){
const [key,value] = arg.split("=");
args[key] = value;
}
return args;
}
const main = () => {
const args = parse_args()
console.log(args.name);
}
Example usage:
# pass arg name equal to monkey
node arg_test.js name=monkey
# Output
>> monkey
You can also add a Set of accepted names and throw exception if an invalid name is provided:
const parse_args = (valid_args) => {
const argv = process.argv.slice(2);
let args = {};
let invalid_args = [];
for (const arg of argv){
const [key,value] = arg.split("=");
if(valid_args.has(key)){
args[key] = value;
} else {
invalid_args.push(key);
}
}
if(invalid_args.length > 0){
throw new Exception(`Invalid args ${invalid_args} provided`);
}
return args;
}
const main = () => {
const valid_args = new Set(["name"])
const args = parse_args(valid_args)
console.log(args.name);
}

Resources