bot.on('message', message => {
if (message.content === 'spam') {
message.channel.send('spam');
while (message.channel.send('spam')) {
if (message.content === 'stop spam') {
return message.channel.send('stopped');
}
}
}
});
im still fairly new to javascript so im not sure if this is even possible the way ive been trying to do it ive looked through w3schools developers.mozilla and even a few questions that are already on here; ive tried using do while, and for loops and ive tried multiple versions of the code i have up there
the ultimate goal is if a user sends the word 'spam' the bot should continuously send the word 'spam' and keep doing so till the bot is turned off or a user sends the words 'stop spam'
Here are some things you should know about the code you're working with:
message.channel.send returns a Promise, so you can't put that in a while loop, because you need to have something that is true or false (a Boolean).
Right now you're trying to check if a message's content is equal to 'stop spam' while you're inside the if-statement checking if the content is equal to 'spam' - So you'll never get inside the inner if-statement.
I would recommend practicing basic javascript a bit more, then moving to Node.js, then coming back to Discord.js - However, it might be cool for you to see a spammer work, so I wrote a some spam code you could use - check this out:
First, create a new file named spamCtrl.js that looks like this (see comments in code for descriptions of what's going on):
let spamming = false;
let spamChannel = undefined;
// spam function repeats until variable spamming is false
function spam() {
return new Promise((resolve, reject) => {
// add check to make sure discord channel exists
if (!spamChannel)
reject('Channel is undefined!');
// send message on spam channel
spamChannel.send('spam')
.then(msg => {
// wait 100 ms until sending next spam message
setTimeout(() => {
// continue spamming if spamming variable is true
if (spamming) {
spam()
.then(resolve) // not entirely necessary, but good practice
.catch(console.log); // log error to console in case one shows up
}
// otherwise, just resolve promise to end this looping
else {
resolve();
}
}, 100)
})
.catch(console.log);
});
}
// public functions that will be used in your index.js file
module.exports = {
// pass in discord.js channel for spam function
setChannel: function(channel) {
spamChannel = channel;
},
// set spam status (true = start spamming, false = stop spamming)
setStatus: function (statusFlag) {
// get current status
let currentStatus = spamming;
// update spamming flag
spamming = statusFlag;
// if spamming should start, and it hasn't started already, call spam()
if (statusFlag && currentStatus != statusFlag) {
spam();
}
},
// not used in my commands, but you may find this useful somewhere
getStatus: function() {
return spamming;
}
};
Next, import that file into your index.js file (Must be in the same directory as your spamCtrl.js file - unless you change the require statement below).
// in index.js file, get controller for spam messages
let spamCtrl = require('./spamCtrl');
Final step: In your index.js file (or wherever you're handling your spam commands) set up your commands (this can be renamed as you like):
// 2 commands together make spamming work :)
case '?SPAM':
spamCtrl.setChannel(message.channel);
spamCtrl.setStatus(true);
break;
case '?STOP-SPAM':
spamCtrl.setStatus(false);
break;
Let me know if you would like any additional explanations on anything, or if you want to see some tweaks here 'n there.
Try using a variable instead. You cannot use message.channel.send('spam') for the while loop.
var spam = false;
if (message.content === 'spam') {
if (message.author.id !== bot.user.id) { // Replace bot with the instance of your bot Client.
spam = true;
} else {
if(spam) {
message.channel.send('spam');
}
}
if (message.content === 'stop spam') {
if(spam) {
message.channel.send('stopped');
}
spam = false;
}
}
Related
I created a site (dashboard) with NextJs which allows a Discord user to connect with his account. So I was able to recover the different guilds of the user but I would like to sort them to keep only the one where he has (at least) the MANAGE_GUILD perm or if he is the owner of the guilds.
I started to create a function to sort the guilds but it doesn't seem to work
export function guildsperm(guilds) {
guilds.map((guilds) => {
if (guilds.owner === true) {
return guilds;
} else if (guilds.permissions <= 0x0000000020) {
return guilds;
} else {
return;
}
});
}
The doc : https://discord.com/developers/docs/topics/permissions#permissions
The way to check for the permissions is not to operate on them with "<.>,=" but rather with bitwise operators, as described in your docs!
For example, your specific case should be to change
else if (guilds.permissions <= 0x0000000020)
into
else if (guilds.permissions & 0x0000000020 == 0x0000000020)
Try it out and let us know if it works.
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'm trying to get my bot to automatically add someone to a role when they start a game, and remove it from that role when they leave the game.
I have already tried several things but without success :
Some other bot change activity but I do not want the other bots of my server to be added in the role so I did that (and it seems to work):
let roleid = "ROLE BOT ID"
if (newMember.roles.has(roleid)) {}
else {console.log("my code here")}
I have the impression that discord.js "gathers" people who play a game (on desktop) and people connected to mobile. So I try to separate them like that but the "! =" does not seem to work :
if (newMember.presence.clientStatus = 'desktop') {console.log("my code here")}
Then I have one last problem is that my bot adds me to the role when I leave my game
Here is my whole code
client.on('presenceUpdate', (oldMember, newMember) => {
let guildChannels = newMember.guild;
let roleid = "ROLE BOT ID"
if (newMember.roles.has(roleid)) {}
else {
if (newMember.presence.clientStatus = 'desktop') {
if (newMember.presence.ActivityType = 'PLAYING') {
newMember.addRole(newMember.guild.roles.find (x => x.id == 'PLAYING ROLE ID'))
console.log(newMember.user.tag + ' -> "ROLE PLAYING NAME"')
}
else {newMember.removeRole(newMember.guild.roles.find (x => x.id == 'PLAYING ROLE ID'))
console.log(newMember.user.tag + ' / "ROLE PLAYING NAME"')
}
}
}
});
I'd like my bot to add all the people playing a role, and delete them when they're done playing
I do not have an error message only that my bot is not doing exactly what I want and I do not have an explanation
if (newMember.presence.clientStatus = 'desktop') {console.log("my code here")}
if (newMember.presence.ActivityType = 'PLAYING') {
The reason these pieces of code don't work is because you're using the assignment operator = instead of a comparison operator like === or ==. Essentially, the code is setting the properties instead of comparing them.
Use comparison operators to check the values of properties, not assignment operators.
Presence.ActivityType is not a valid property of Presence.
Check the user's game (Presence.game) to see if they're playing something.
Some other bot change activity but I do not want the other bots of my server to be added in the role...
Check if a User is a bot with the User.bot property.
If a user changes their status (i.e. Online --> DND) or starts listening to music, watching a stream, etc., your code will be executed even though their game has not changed.
You need to check the old presence and compare it with the new presence to make sure the user started or stopped playing a game.
You aren't catching any rejected Promises.
Use try...catch statements or attach catch() methods to Promises.
Code
client.on('presenceUpdate', (oldMember, newMember) => {
const guild = newMember.guild;
const playingRole = guild.roles.find(role => role.id === 'PLAYING ROLE ID');
if (newMember.user.bot || newMember.presence.clientStatus === 'mobile' || oldMember.presence.status !== newMember.presence.status) return;
const oldGame = oldMember.presence.game && [0, 1].includes(oldMember.presence.game.type) ? true : false;
const newGame = newMember.presence.game && [0, 1].includes(newMember.presence.game.type) ? true : false;
if (!oldGame && newGame) { // Started playing.
newMember.addRole(playingRole)
.then(() => console.log(`${playingRole.name} added to ${newMember.user.tag}.`))
.catch(console.error);
} else if (oldGame && !newGame) { // Stopped playing.
newMember.removeRole(playingRole)
.then(() => console.log(`${playingRole.name} removed from ${newMember.user.tag}.`))
.catch(console.error);
}
});
I want to add a code to my bot where it will send a message when a specific user plays a specific game (i.e. Left 4 Dead 2). How do I do that? I don't want any commands anymore.
// Game Art Sender //
if (message.channel.id === '573671522116304901') {
if (msg.includes('!L4D2')) { // THIS is what I want to change.
message.channel.send('***[MATURE CONTENT]*** **Joining Game:**', {
files: [
"https://cdn.discordapp.com/attachments/573671522116304901/573676850920947733/SPOILER_l4d2.png"
]
});
}
});
Try this
if(GuildMember.username === 'Specific_Username_here')
if(GuildMember.presence.game === 'Specific_Game_here')
// do whatever here
GuildMember.id could also be used if you know that user's specific id string. I haven't tested this myself and I'd have rather posted this as a comment, but I don't have that permission yet.
To send a message to a specific channel, use this:
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE')
channel.send("MESSAGE GOES HERE")
or
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE')
channel.send(VARIABLE_GOES_HERE)
Summing it up, your code should be something like this:
if(GuildMember.username === 'Specific_Username_here')
if(GuildMember.presence.game === 'Specific_Game_here') {
const channel = message.guild.channels.find(ch => ch.name === 'CHANNEL_NAME_GOES_HERE)
channel.send("MESSAGE GOES HERE")
}
So I just figured it out. It was a long journey to figuring this one out.
Here's the code:
// Game Detector \\
client.on("presenceUpdate", (oldMember, newMember) => {
if(newMember.id === '406742915352756235') {
if(newMember.presence.game.name === 'ROBLOX') { // New Example: ROBLOX
console.log('ROBLOX detected!');
client.channels.get('573671522116304901').send('**Joining Game:**', {
files: [
"https://cdn.discordapp.com/attachments/567519197052272692/579177282283896842/rblx1.png"
]
});
}
}
});
However, I need one more problem solved:
It says "null" when I close the application.
How do I fix this?
How do you play an audio file from a Discord bot? Needs to play a local file, be in JS, and upon a certain message being sent it will join the user who typed the message, and will play the file to that channel.
GitHub Project: LINK
In order to do this there are a few things you have to make sure of first.
Have FFMPEG installed & the environment path set for it in Windows [link]
Have Microsoft Visual Studio (VS) installed [link]
Have Node.js installed.[link]
Have Discord.js installed in VS.
From there the steps are quite simple. After making your project index.js you will start typing some code. Here are the steps:
Add the Discord.js dependency to the project;
var Discord = require('discord.js');
Create out client variable called bot;
var bot = new Discord.Client();
3. Create a Boolean variable to make sure that the system doesn't overload of requests;
var isReady = true;
Next make the function to intercept the correct message;
bot.on('message', message =>{ENTER CODE HERE});
Create an if statement to check if the message is correct & if the bot is ready;
if (isReady && message.content === 'MESSAGE'){ENTER CODE HERE}
Set the bot to unready so that it cannot process events until it finishes;
isReady = false;
Create a variable for the channel that the message-sender is currently in;
var voiceChannel = message.member.voice.channel;
Join that channel and keep track of all errors;
voiceChannel.join().then(connection =>{ENTER CODE HERE}).catch(err => console.log(err));
Create a refrence to and play the audio file;
const dispatcher = connection.play('./audiofile.mp3');
Slot to wait until the audio file is done playing;
dispatcher.on("end", end => {ENTER CODE HERE});
Leave channel after audio is done playing;
voiceChannel.leave();
Login to the application;
bot.login('CLIENT TOKEN HERE');
After you are all finished with this, make sure to check for any un-closed brackets or parentheses. i made this because it took my hours until I finally found a good solution so I just wanted to share it with anybody who is out there looking for something like this.
thanks so much!
One thing I will say to help anyone else, is things like where it says ENTER CODE HERE on step 10, you put the code from step 11 IE:
dispatcher.on("end", end => voiceChannel.leave());
As a complete example, this is how I have used it in my message command IF block:
if (command === "COMMAND") {
var VC = message.member.voiceChannel;
if (!VC)
return message.reply("MESSAGE IF NOT IN A VOICE CHANNEL")
VC.join()
.then(connection => {
const dispatcher = connection.playFile('c:/PAtH/TO/MP3/FILE.MP3');
dispatcher.on("end", end => {VC.leave()});
})
.catch(console.error);
};
I went ahead an included Nicholas Johnson's Github bot code here, but I made slight modifications.
He appears to be creating a lock; so I created a LockableClient that extends the Discord Client.
Never include an authorization token in the code
auth.json
{
"token" : "your-token-here"
}
lockable-client.js
const { Client } = require('discord.js')
/**
* A lockable client that can interact with the Discord API.
* #extends {Client}
*/
class LockableClient extends Client {
constructor(options) {
super(options)
this.locked = false
}
lock() {
this.setLocked(true)
}
unlock() {
this.setLocked(false)
}
setLocked(locked) {
return this.locked = locked
}
isLocked {
return this.locked
}
}
module.exports = LockableClient;
index.js
const auth = require('./auth.json')
const { LockableClient } = require('./lockable-client.js')
const bot = new LockableClient()
bot.on('message', message => {
if (!bot.isLocked() && message.content === 'Gotcha Bitch') {
bot.lock()
var voiceChannel = message.member.voiceChannel
voiceChannel.join().then(connection => {
const dispatcher = connection.playFile('./assets/audio/gab.mp3')
dispatcher.on('end', end => voiceChannel.leave());
}).catch(err => console.log(err))
bot.unlock()
}
})
bot.login(auth.token)
This is an semi old thread but I'm going to add code here that will hopefully help someone out and save them time. It took me way too long to figure this out but dispatcher.on('end') didn't work for me. I think in later versions of discord.js they changed it from end to finish
var voiceChannel = msg.member.voice.channel;
voiceChannel.join()
.then(connection => {
const dispatcher = connection.play(fileName);
dispatcher.on("finish", end => {
voiceChannel.leave();
deleteFile(fileName);
});
})
.catch(console.error);
Note that fileName is a string path for example: fileName = "/example.mp3". Hopefully that helps someone out there :)
Update: If you want to detect if the Audio has stopped, you must subscribe to the speaking event.
voiceChannel
.join()
.then((connection) => {
const dispatcher = connection.play("./audio_files/file.mp3");
dispatcher.on("speaking", (speaking) => {
if (!speaking) {
voiceChannel.leave();
}
});
})