I have never coded a Discord Bot before but am familiar with Javascript so I figured I would give it a shot. I used the beginner files from this site Digital Trends but am running into some issues.
I have the bot running in my server and the basic command swapped from "!" to "?" and the included command "?ping" does return the expected response "Pong!"
I run a server where we start a video game each month and play through while discussing it along the way, similar to a book club. So I'm trying to create a channel where people can suggest a game using a bot command since I don't trust they could handle following simple rules on their own.
What I'm trying to figure out is how to go about taking a user command of:
?gs "Video Game Title" "Platform"
And having the bot delete the command and repost as:
#user suggested Video Game Title for Platform
While also adding reaction emojis "👍" and "👎" to allow other users to vote.
I'm not asking for anyone to do this for me, but to simply help point me in the right direction of how to code this with Discord in mind using JS (if possible)
Here is my current "bot.js" code:
var Discord = require('discord.io');
var logger = require('winston');
var auth = require('./auth.json');
// Configure logger settings
logger.remove(logger.transports.Console);
logger.add(new logger.transports.Console, {
colorize: true
});
logger.level = 'debug';
// Initialize Discord Bot
var bot = new Discord.Client({
token: auth.token,
autorun: true
});
bot.on('ready', function (evt) {
logger.info('Connected');
logger.info('Logged in as: ');
logger.info(bot.username + ' - (' + bot.id + ')');
});
bot.on('message', function (user, userID, channelID, message, evt) {
// Our bot needs to know if it will execute a command
// It will listen for messages that will start with `!`
if (message.substring(0, 1) == '?') {
var args = message.substring(1).split(' ');
var cmd = args[0];
args = args.splice(1);
switch(cmd) {
// !ping
case 'ping':
bot.sendMessage({
to: channelID,
message: 'Pong!'
});
break;
// Just add any case commands if you want to..
}
}
});
args = args.splice(1);
This line is incorrect, args (being a string) has no .splice() method. (I often get .slice() and .split() confused, so this happens to me a lot too!)
Instead, use:
args = args.split(" ").slice(1);
Related
Attempting to implement texas hold em poker in discord with a bot using node js.
Currently have a problem try to nest
client.on('message', message => {
calls. The idea behind these is that the first one looks for the !poker command, and subsequent ones listen for joining players, player bets etc.
code:
const Discord = require('discord.js');
const dotenv = require('dotenv').config();
const Game = require("./classes.js").Game
const Player = require("./classes.js").Player
// create a new Discord client
const client = new Discord.Client();
// when the client is ready, run this code
// this event will only trigger one time after logging in
client.once('ready', () => {
console.log('Ready!');
});
let prefix = '!';
client.on('message', message => {
//prevent feedback loops
if (!message.content.startsWith(prefix) || message.author.bot) return;
if (message.content.startsWith(`${prefix}poker`)){
//getting args
const args = message.content.slice(prefix.length).trim().split(' ');
const command = args.shift().toLowerCase();
//converting to relevant data type
let no_players = parseInt(args[0]);
let money = parseInt(args[1])
//initialising game object and card deck
let game = new Game();
game.deck = game.createDeck();
//list to contain players (will be objects from the Player class)
let players = [];
//list to contain player usernames, will be used to identify if someone has already joined
let player_users = [];
// loop until we have enough players, as specified by the first input arguemnt
while (players.length <= no_players){
//now wait for a join message
client.on('message', message => {
//if message == join, and the player has not already joined
if (message.content.startsWith('join')){
if (!players.includes(message.author.username)){
let newPlayer = new Player(message.author.username,money);
players.push(newPlayer);
player_users.push(message.author.username);
}
}
});
}
//debugging purposes
console.log(players)
}
if (message.content.startsWith(`${prefix}hands`)){
message.channel.send("Here are the poker hands", {files: ["poker-hand-rankings-mobile.png"]});
}
});
client.login(process.env.TOKEN);
The command syntax in discord will look like !poker {number of players} {betting money for each player}
Other functionality in create decks etc works fine.
When I run in the debugger it doesnt seem to enter the second client.on code block, and I recieve this error upon running FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
Not sure if my overall approach is flawed here, i.e. discord.js cant have two processes waiting for messages running at the same time. Or if there is variable overlap between defining message.
Considering scrapping and moving to python so any help would be greatly appreciated.
Revoking A Ban Using Code
So, I am making a moderation discord bot using VS Code and I have already set up a ban command. I want to make a unban command (revoking a ban) too so that the user can easily unban a user and not have to go into Server Settings to do it.
I know you can do it because I have been using another bot, GAwesomeBot, that is able to do it.
Link to GAwesomeBot: https://gawesomebot.com
I am a little new to Stack Overflow and this is my first question so pardon me if I am doing anything wrong.
Consider using GuildMemberManager#unban
https://discord.js.org/#/docs/main/stable/class/GuildMemberManager?scrollTo=unban
let guildMemberManager, toUnbanSnowflake;
guildMemberManager.unban(toUnbanSnowflake); // Takes UserResolveable as argument
First you want to define the user that you are unbanning.
Because the user is already banned you will have to mention the user by their ID and then unbanning them.
let args = message.content.split(/ +/g); //Split the message by every space
let user = message.guild.members.cache.get(args[1]); //getting the user
user.unban({ reason: args[2].length > 0 ? args[2] : 'No reason provided.' }); //Unbanning the user
The full example:
//Define your variables
const Discord = require('discord.js');
const client = new Discord.Client();
var prefix = 'your-prefix-here';
//Add a message event listener
client.on('message', () => {
let args = message.content.split(/ +/g); //Split the message by every space
if (message.content.toLowerCase() === prefix + 'unban') {
let user = message.guild.members.cache.get(args[1]); //getting the user
if (!user) return message.channel.send('Please specify a user ID');
user.unban({ reason: args[2].length > 0 ? args[2] : 'No reason provided.' }).then(() => message.channel.send('Success');
}
});
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
};
});
I have a few pictures, all on imgur with direct image link (format: https://i.imgur.com/XXXXXX.jpg), and a Discord bot made with NodeJS.
I send messages like this:
bot.sendMessage({
to: channelID,
message: "My Bot's message"
});
I have tried this:
bot.sendMessage({
to: channelID,
message: "My Bot's message",
file: "https://i.imgur.com/XxxXxXX.jpg"
});
but I only get the text. I have looked it up, and this question was the only one to even come close to saying what I need to do, and it didn't work.
So how am I supposed to do this?
Here is how the bot is created:
var bot = new Discord.Client({
token: auth.token,
autorun: true
});
bot.on('ready', function (evt) {
logger.info('Connected');
logger.info('Logged in as: ');
logger.info(bot.username + ' - (' + bot.id + ')');
});
bot.on('message', function (user, userID, channelID, message, evt) {
// My code
}
ClientUser.sendMessage is deprecated, as is the file parameter in its options. You should be using Channel.send(message, options), with files as an array of strings or FileOptions.
bot.on('messageCreate' message => {
message.channel.send("My Bot's message", {files: ["https://i.imgur.com/XxxXxXX.jpg"]});
});
If you want to stick to your deprecated methods, ClientUser.sendFile might be something of interest to you, though I do recommend you move over to the stuff that's more current.
You can send local files in v11.2 like this:
var Discord = require('discord.js');
var bot = new Discord.Client();
bot.on('message', message => {
var prefix = '!'
var msg = message.content;
if (msg === prefix + 'image') {
message.channel.send('Message that goes above image', {
files: [
"./image-to-send.png"
]
});
}
});
bot.login('TOKEN');
Since this is one of the top results on google in 2019, I'm adding the new method of how to upload files with discord.io
First thing that's different is the on() function takes some additional parameters.
Next is that there's a new method called uploadFile that takes an uploadFileOpts object. the file can take a string that is a local path from your bot file to the image.
uploadFileOpts = {
to: string,
file: string|Buffer,
filename?: string,
message?: string
}
So, if you place your image next to your bot script, your code should look like this
bot.on('message', function (user, userID, channelID, message, evt) {
bot.uploadFile({
to: channelID,
file: 'myImage.jpg'
});
}
If you still want to snag that image from the internet, you'll need to convert it into a Buffer object. However, storing the file locally is simpler.
If you're using discord.io instead of Discord.js, refer to this syntax:
https://izy521.gitbooks.io/discord-io/content/Methods/Channels.html
I'm still trying to get it to work.