Now, before you say that this has been posted before, I have a different situation.
With that out of the way, let's get on with the question.
I am making a Discord bot for a friend that does duties for the group and things like that.
Quick note too, I am using the Sitepoint version of Discord.JS because I'm a beginner.
I want the bot to send a message to a certain channel when the show gets canceled for a reason. For example, they would send something like this:
afv!cancel Roblox went down.
or something similar.
But every time it sends a message, every space turns into a comma like this:
:x: The show has been cancelled because: "Roblox,went,down.". Sorry for that!
Here's the index.js code that handles executing commands:
bot.on('message', msg => {
const args = msg.content.split(/ +/);
const command = args.shift().toLowerCase();
const prefix = command.startsWith("afv!");
if (prefix == true) {
console.info(`Called command: ${command}`);
if (!bot.commands.has(command)) return;
msg.delete(1);
try {
bot.commands.get(command).execute(msg, args, bot);
} catch (error) {
console.error(error);
msg.reply('there was an error trying to execute that command!');
};
And the cancelled.js file:
module.exports = {
name: 'afv!cancel',
description: "in-case the show gets cancelled",
execute(msg, args, bot) {
if (msg.member.roles.find(r => r.name === "Bot Perms")) {
const reason = args.replace(/,/g, " ");
bot.channels.get('696135370987012240').send(':x: **The show has been cancelled** because: "' + args + '". *Sorry for that!*');
bot.user.setActivity("AFV! | afv!help", { type: 'PLAYING' });
} else {
msg.reply('you are missing the role: Bot Perms!');
}
},
};
By the way, upon executing the command, it prints this:
TypeError: args.replace is not a function
Thanks for reading! :)
From what I can see, here
const reason = args.replace(/,/g, " ");
bot.channels.get('696135370987012240').send(':x: **The show has been cancelled** because: "' + args + '". *Sorry for that!*');
you are making a const reason, wherein you try to handle that as a string and replace all commas with spaces. Unfortunately, even though it can be displayed in a string and looks to be one, in reality it is an array, so replace() won't work on it. To be able to use replace() you need to first transform your array to an actual string:
const reason = args.join().replace(/,/g, " ");
With that done you won't be seeing this pesky "not a function" error, and you can easily use reason to display your message:
bot.channels.get('696135370987012240').send(':x: **The show has been cancelled** because: "' + reason + '". *Sorry for that!*');
Related
so i am creating a bot with a kick command and would like to be able to add a reason for said action, i've heard from somewhere that i may have to do string manipulation. currently i have a standalone reason as shown in the code below:
client.on("message", (message) => {
// Ignore messages that aren't from a guild
if (!message.guild) return;
// If the message starts with ".kick"
if (message.content.startsWith(".kick")) {
// Assuming we mention someone in the message, this will return the user
const user = message.mentions.users.first();
// If we have a user mentioned
if (user) {
// Now we get the member from the user
const member = message.guild.member(user);
// If the member is in the server
if (member) {
member
.kick("Optional reason that will display in the audit logs")
.then(() => {
// lets the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
.catch((err) => {
// An error happened
// This is generally due to the bot not being able to kick the member,
// either due to missing permissions or role hierarchy
message.reply(
"I was unable to kick the member (this could be due to missing permissions or role hierarchy"
);
// Log the error
console.error(err);
});
} else {
// The mentioned user isn't in this server
message.reply("That user isn't in this server!");
}
// Otherwise, if no user was mentioned
} else {
message.reply("You didn't mention the user to kick!");
}
}
});
Split message.content and slice the first 2 array elements, this will leave you with the elements that make up the reason. Join the remaining elements back to a string.
const user = message.mentions.users.first();
const reason = message.content.split(' ').slice(2).join(' ');
Here is something that could help:
const args = message.content.slice(1).split(" "); //1 is the prefix length
const command = args.shift();
//that works as a pretty good command structure
if(command === 'kick') {
const user = message.mentions.users.first();
args.shift();
const reason = args.join(" ");
user.kick(reason);
//really close to Elitezen's answer but you might have a very terrible problem
//if you mention a user inside the reason, depending on the users' id, the bot could kick
//the user in the reason instead!
}
Here's how you can take away that problem (with regex)
const userMention = message.content.match(/<#!?[0-9]+>/);
//you may have to do some more "escapes"
//this works since regex stops at the first one, unless you make it global
var userId = userMention.slice(2, userMention.length-1);
if(userId.startsWith("!")) userId = userId.slice(1);
const user = message.guild.members.cache.get(userId);
args.shift();
args.shift();
user.kick(args.join(" "))
.then(user => message.reply(user.username + " was kicked successfully"))
.catch(err => message.reply("An error occured: " + err.message))
I assume you want your full command to look something like
.kick #user Being hostile to other members
If you want to assume that everything in the command that isn't a mention or the ".kick" command is the reason, then to get the reason from that string, you can do some simple string manipulation to extract the command and mentions from the string, and leave everything else.
Never used the Discord API, but from what I've pieced from the documentation, this should work.
let reason = message.content.replaceAll(".kick", "")
message.mentions.forEach((mentionedUser) => reason.replaceAll("#" + mentionedUser.username, "")
// assume everything else left in `reason` is the sentence given by the user as a reason
if (member) {
member
.kick(reason)
.then(() => {
// lets the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
}
I want to create a verify Command with discord.js v12 which gives you a verified Role which is defined in a Configfile.
Configfile:
{
"token": "my-token",
"status": "a game",
"statusurl": "",
"statustype": 0,
"botmanager": ["285470267549941761", "743136148293025864"],
"prefix": "m!",
"server": {
"343308714423484416": {
"active": true,
"hasBeta": true,
"adminroles": ["533646738813353984"],
"modroles": ["744589796361502774"],
"premiumtoken": "",
"welcomechannel": "653290718248435732",
"welcomemessage": "Hey Hey %user% at %server%",
"welcomemsgenabled": true,
"leavechannel": "653290718248435732",
"leavemessage": "Bye %user% at %server%",
"leavemsgenabled": true,
"verifiedrole": "533646700712296448",
"ruleschannel": "382197929605201920"
}
}
}
My Code:
const Discord = require('discord.js')
const client = new Discord.Client()
const config = require('./config.json')
client.on('ready', () => {
client.user.setStatus('online')
client.user.setActivity("m!help")
console.log(`Bot started successfully in ${client.guilds.cache.size} Guilds with ${client.users.cache.size} Users and ${client.channels.cache.size} Channels`)
})
client.on("message", async message => {
if(message.author.bot) return;
if(!message.content.startsWith(config.prefix)) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if(command === "verify") {
if(args.length == 0) {
let member = message.mentions.members.first();
if(message.member.roles.cache.some(r=>[config.server[(message.guild.id)].modroles].includes(r.id))) {
if(!member) {
return message.channel.send(new Discord.MessageEmbed().setColor(0xd35400).setTitle("Invalid User").setDescription("Please use the following Syntax:\n `m!verify <Nutzer>`"))
} else {
var role = message.guild.roles.find(role => role.id === config.server[(message.guild.id)].verifiedrole);
member.roles.cache.add(config.guild[(message.guild.id)].verifiedrole)
}
} else {
message.channel.send(new Discord.MessageEmbed().setTitle("Missing Perms!").setDescription("You're missing the permission to execute this command!").setColor(0xe74c3c))
}
}
}
console.log("Command used: " + command + " " + args + " | User: " + message.author.id + " | Guild: " + message.guild.id)
}
}
})
client.login(config.token)
I removed the most Code so only this command is left. Important is, that this Bot have to be able to use at multiple Servers at the time.
What is wrong here?
OK, so lets make this a multi part answer. First "What is wrong here?" Well, for the most part your current code does not work because you don't use the brackets correctly. You are trying to close brackets that you don't open anywhere. You also use a few too many "if" statements in places where you don't need them.
Next is your concern about multiple servers. This is really not a problem if you write the code to be dynamic. The execution of the command is quick enough that you don't need to worry about two people trying to use the command and the roles getting mixed up.
What I would really advise you to do is take a look at this https://discordjs.guide/ and this https://discord.js.org/#/docs/main/stable/general/welcome
Now to the topic of this question, this is how you could do such a "verify" command. I also added a few notations into the code to explain what we're doing 🙂
client.on("message", message => { // You don't need the async here
// This is all working correctly
if (message.author.bot) return;
if (!message.content.startsWith(config.prefix)) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === "verify") {
// We define the server constant as the part of the JSON that deals with the server the message came from
// This makes accessing those values easier
const server = config.server[message.guild.id];
// Your code here was also working
let member = message.mentions.members.first();
// Here we first define the moderator role
// Technicaly this is not needed but it makes the whole code a little easier to understand
// We need modrole[0] here because the modrole entry in your JSON is an array
let modrole = message.guild.roles.cache.find(r => r.id === server.modroles[0]);
// Here we check if the member who calls this command has the needed role
// We need to use the ID of the role to check
if (!message.member.roles.cache.has(modrole.id)) {
// If the user does not have the required role we return here
// That way you don't need to use the 'else' statement
// Creating the embed object in multiple lines improves readability
return message.channel.send(new Discord.MessageEmbed()
.setTitle("Missing Perms!")
.setDescription("You're missing the permission to execute this command!")
.setColor(0xe74c3c)
);
}
if (!member) {
// Here we check if a member was tagged in the command and if that user exists
// Same reasons as above
return message.channel.send(new Discord.MessageEmbed()
.setColor(0xd35400)
.setTitle("Invalid User")
.setDescription(`Please use the following Syntax:\n '${config.prefix}verify <Nutzer>'`)
);
}
// Now we define the role that we want the bot to give
// Here we also don't need to do this but it improves readability and makes working with the role a little easier
var role = message.guild.roles.cache.find(role => role.id === server.verifiedrole);
// Here we add the role to the specified member
// We don't need to use the .cache here
member.roles.add(role.id);
// We can use something called "template strings" here so we don't need to combine multiple strings
// They allow us to put predefined values into the string
console.log(`Command used: ${command} ${args} | User: ${message.author.id} | Guild: ${message.guild.id}`)
}
})
If you want, that the command can be executed at multiple servers at the time you need to write the code in async/await. If you want to learn more about async you can get very good help especially for discord.js v12 here: Understanding async/await
you can get a command for a specifiq channel and give a role for acces to the server
I relatively new to javascript (.js) and would like some help with me latest discord bot.
Here is an example of the code i use:
if (command === "ping") {
msg.channel.send(`Pong! <#${msg.author.id}> my Ping is ` + bot.ping + `ms`);
}
Thank you for reading this and i hope you can answer my question 😁
Edit:
My question depends on if you know discord.js well and if you know how to setup a .say command where it says the message i type in
Edit:
Also, to prevent people abusing, i would like to know if i can say you have to have a permission level of 8 to use this command and it will not work if it is below 8
Try something like this:
if(command === "say"){
msg.channel.send(msg.content.substr(4));
}
Result
This only works if your prefix is 1 character long.
Your prefix is "." so it should work.
Please be aware that java and javascript are not the same language. You can read more about this here: Differences between java and javascript
Anyway, discord bots normally require a prefix to work properly and be aware when the message is directed to them or not, elsewhere they will send messages when they are not supposed to.
const PREFIX = "." // set the prefix
client.on('ready', () => {
console.log('Bot is on');
}); // this will log a message when the event 'ready' is triggered
client.on('message', message => {
let args = message.content.substring(PREFIX.lenght).split(" ");
switch (args[0]){
case PREFIX+'ping':
message.channel.send(`Pong! <#${msg.author.id}> my Ping is ${bot.ping}ms`);
break;
Command Ping
client.on('message', async message =>{
const prefix = "!";
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if(message.content === '!ping'){
const msg = await message.channel.send("Checking for ping...") // Checking a message
var ping = Date.now() - message.createdTimestamp + " ms";
msg.edit("Pong ! " + message.member.user.tag + " my Ping is "`${Date.now() - message.createdTimestamp}` + " ms`");
// edit message from checking message to ping message
};
});
When im coding the part of the discord bot that gives a role when activated i keep getting this error and im not sure if there is a bug i dont see but if you see it pls help me correct it!
Error message.
if(mesage.content.startsWith(prefix + "prune")){
^
ReferenceError: mesage is not defined
Section of script with problem.
if(mesage.content.startsWith(prefix + "prune")){
let args = Message.content.split(" ").slice(1);
let author = Message.member;
let role = message.guilds.roles.find('name', "Moderator");
if(author.roles.has(role.id)){
if(!args[0]){
Message.delete();
Message.author.send("No arguments given.");
return;
}
}
}
Full Script
const Discord = require('discord.js')
const Client = new Discord.Client
const prefix = "/";
Client.on('ready', ()=>{
console.log('Bot is online.');
})
Client.on('message', (Message)=>{
if(!Message.content.startsWith(prefix)) return;
if(Message.content.startsWith(prefix + "hello")){
Message.channel.send("Hello.");
}
if(Message.content.startsWith(prefix + "help")){
Message.channel.send("The only avaible command right now is /help and /hello.")
Message.author.send("This is only for test purposes!");
}
if(mesage.content.startsWith(prefix + "prune")){
let args = Message.content.split(" ").slice(1);
let author = Message.member;
let role = message.guilds.roles.find('name', "Moderator");
if(author.roles.has(role.id)){
if(!args[0]){
Message.delete();
Message.author.send("No arguments given.");
return;
}
}
}
})
Client.login("<Bot Token>");
All your code refers to Message, except this line which is mesage, not only mis-spelled, but incorrectly lower-case.
Making that consistent with the other things should fix the issue.
Note that JavaScript generally reserves capital letters for things like classes, lower-case for variables and arguments. As you can see here the syntax highlighter thinks this is a class and is colouring it accordingly. Lower-case message is the conventional argument name.
Change mesage (the typo) with message (not uppercase). Make sure to also change Message with message (again, no uppercase)
So I'm trying to make a bot that posts given data to hastebin.
But it doesn't really behave well. I'm using discord.js and hastebin-gen.
This is the code:
const hastebin = require('hastebin-gen');
exports.run = (client, msg, args) => {
let haste = args.slice(0).join(" ")
let type = args.slice(1).join(" ")
if (!args[0]) { return msg.channel.send("Usage: bin.haste yourmsghere.") }
hastebin(haste, type).then(r => {
msg.channel.send(":white_check_mark: Posted text to Hastebin at this URL: " + r);
}).catch(console.error);
}
When ran, for example bin.haste this code is awesome, it returns this:(https://a.pomf.cat/rkjqog.png) (Note: Can't post images yet, sorry.)
If I click on the link, it successfully uploads the text given to Hastebin: (https://a.pomf.cat/ovcpzb.png)
But there's just that annoying fact that it repeats the given text, as seen at the end of the link, and after the link.
What it's adding is the extension you're passing to hastebin-gen. Don't pass one and it will just respond with the link.
Hastebin-gen only adds the extension to the link at this line:
res("https://hastebin.com/" + body.body.key + ((extension) ? "." + extension : ""));
The extension doesn't matter at all, hastebin.com/beqojuzowe.jhffyjbfft will point to the same as hastebin.com/beqojuzowe.
TL;DR use this:
hastebin(haste).then(r => {