I am trying to create a temporary channel what is working with "Slash" commands. I am almost there but I am getting an error when creating a second channel because the "voiceStateUpdate" is getting called twice.
else if (commandName === "createchannel") {
var channelName = options.getString("channelname");
var rolesThatCanJoin = options.getRole("roles");
var state = options.getString("state");
var channel = interection.guild.channels.create(channelName, {
type: "GUILD_VOICE"
}).then((channel) => {
channel.setParent("670691620844470320")
createdChannelID = channel.id;
interection.reply({
content: `**Channel named:** ${channelName}\n**Role that can join:** ${rolesThatCanJoin}\n**State:** ${state}`,
ephemeral: true,
})
client.on('voiceStateUpdate', (oldState, newState) => {
var newChannelID = newState.channelId;
if (newChannelID === createdChannelID) {
console.log("User has joined voice channel with id " + newChannelID);
}
else {
console.log("User has left");
channel.delete()
}
});
});
}
Console:
User has joined voice channel with id 936252040865284156
User has left
User has joined voice channel with id 936252068568641576
User has joined voice channel with id 936252068568641576
User has left
User has left
Error:
DiscordAPIError: Unknown Channel
It seems like every time the command runs, you are calling client.on('voiceStateUpdate'... again, which adds another listener. This is causing you to receive the same event multiple times. I suggest you move your client.on('voiceStateUpdate'... code to another location where it will get called once, same as how you are handling other events like client.on('messageCreate'... or client.on('interactionCreate'...
Related
Hello I am trying to use a discord bot to wait for a message from an admin of my server and then check the following messages from users. My code waits for the admin message however it somehow caches it ?? At least it doesnt check the users messages. I made my bot write the message where it got triggered to make it more understandable:
const Discord = require("discord.js");
const bot = new Discord.Client();
const bot_config = require("./settings.json")
var token = bot_config.usertoken
var userid = bot_config.userid
var channel = "940800688219369483"; //
bot.on("ready", () => {
console.log(`SUCCESSFULLY LOGGED IN AS ${bot.user.tag}!`);
});
let counter = 0
bot.on("message", (msg) => {
//Waiting for mesage from specific admin
if(msg.author == "1011983215650672781"){
if(counter == 0){ // check if message has already been send
if (msg.channel.id != channel) return; // Checks valid Channel ID
if (msg.author == userid && msg.author == "703629528454660106" && msg.authot == "255396012045238222" && msg.authot == "142772377047199744" && msg.authot == "235748962103951360") { //CHECK IF NEXT MESSAGE IS NOT AN ADMIN
console.log("ADMIN MESSGAE");
}
else{
let answer = msg.content
bot.channels.cache.get(channel).send(answer)
counter ++
console.log("SUCCESSFULLY SENT MESSAGE")
}
}
else{
console.log("ALREADY SENT MESSAGE - CLOSE BOT")
}
}
})
bot.login(usertoken)
The problem is, the bot still writes the first admin message in the channel and not the onw from the first user
You might kick yourself for this, but you have used msg.authot instead of msg.author.id.
You may want to check out the docs, they come in handy when you need to know how to access properties.
To put it simply, my bot is reading off another bot to see if a drop has been dropped, however, there are some problems occurring.
Current Scenario:
User 1 drops
User 2 drops
The bot my bot is reading off (ID:733122859932712980, hence the filter) sends the first drop
My bot pings the role twice before the second drop has dropped.
The bot my bot is reading off sends the second drop
No ping from my bot
What I want is for the second ping to happen after the second drop happens
Current code:
const Discord = require('discord.js');
module.exports = {
name: "drop",
aliases:["d"],
async execute(client, msg, args) {
const filter = m => m.author.id === "733122859932712980";
const collector = msg.channel.createMessageCollector({
filter
});
collector.on("collect", m => {
if (m.embeds[0]){
const embed = m.embeds[0]
if(embed.author?.name.includes("K-DROP")){
for (var i=0; i<embed.fields.length ; i++){
if(embed.fields[i].name) {
if(embed.fields[i].value.includes("Winner")){
return;
}
else
{
m.channel.send("<#&980128851495641101>")
break;
}
}
}
}
collector.stop();
}
})}};
I have an invite create command, but whenever it creates an invite it does it under the bots ID. I'm wondering if there is a way I can add the invite code to a different user ID so when they use an invites command, it will show the amount of invites that specific code has sent. Bump
module.exports = {
commands: 'invites',
requiredRoles: ['Affiliate'],
callback: (message) => {
if (message.channel.id === '824652970410770443'){
var user = message.author
message.guild.fetchInvites()
.then
(invites =>
{
const userInvites = invites.array().filter(o => o.inviter.id === user.id);
var userInviteCount = 0;
for(var i=0; i < userInvites.length; i++)
{
var invite = userInvites[i];
userInviteCount += invite['uses'];
}
const embed = new Discord.MessageEmbed()
.setColor('#1AA2ED')
.setTitle(message.author.username + "'s Invites")
.setDescription(`Invites: ${userInviteCount}`)
message.reply(embed).then((msg) => {
message.delete()
})
}
)
}
if (message.channel.id !== '824652970410770443'){
message.reply(`You can't do that here`)
}
}
}; ```
You can not change the Invite Creator that Discord knows, however you could locally store which user created which invite link.
This would however have to be done when in the command that creates an invite.
You have multiple options on how to store this data, but the simplest one would just be writing the data to an Object that associates the User ID to the Invite ID, then stringifying and saving that Object to a file whenever your bot exits and loading and parsing that file whenever your bot starts.
Then, whenever you need to know which user created an invite link, look it up in that Object.
I'm attempting to make it so that when someone joins the Voice Channel, so the Bot will add the specific person to the text channel with the permission to read and send messages and remove the individual and their permissions when they leave the Voice Channel. I'm not overly familiar with discord.js so I'm not sure on how to do it.
First and foremost, welcome to Stack Overflow. I hope we can be of help to you.
Let's start by detecting when a member joins a voice channel. To do so, we can listen to your client's voiceStateUpdate event. Next, we can compare the old voice channel with the new one, and see if the member joined or left. Finally, we can change the permissions for the member in the text channel using GuildChannel.overwritePermissions().
Update: Multiple "pairs" of text channels and voice channels with similar behavior.
To do this for many different channels, you could set up a json file to store the voice channels and corresponding text channels, and then iterate over each pair, checking if the situation matches any.
channelPairs.json
[
{ "voice": "voiceChannelIDHere", "text": "textChannelIDHere" }
]
index.js
const pairs = require('./channelPairs.json'); // Keep in mind the path may vary
client.on('voiceStateUpdate', (oldMember, newMember) => {
let oldID;
let newID;
if (oldMember.voiceChannel) oldID = oldMember.voiceChannel.id;
if (newMember.voiceChannel) newID = newMember.voiceChannel.id;
for (let i = 0; i < pairs.length; i++) {
const textChannel = newMember.guild.channels.get(pairs[i].text);
if (!textChannel) {
console.log('Invalid text channel ID in json.');
continue;
}
const vcID = pairs[i].voice;
if (oldID !== vcID && newID === vcID) { // Joined the voice channel.
textChannel.overwritePermissions(newMember, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true
}).catch(console.error);
} else if (oldID === vcID && newID !== vcID) { // Left the voice channel.
textChannel.overwritePermissions(newMember, {
VIEW_CHANNEL: null,
SEND_MESSAGES: null
}).catch(console.error);
}
}
});
Okay so let's take a look at the DiscordJS API:
Found here.
As we can see, there's a class called "WSEvent" (stands for WebsocketEvent). We can use this to detect when a user joins the channel...
But we can't really use that because there's no "CHANNEL_JOIN" event. So instead, we must listen for this voiceStateUpdate or VOICE_STATUS_UPDATE event.
Like so:
// voiceStateUpdate
/* Emitted whenever a user changes voice state - e.g. joins/leaves a channel, mutes/unmutes.
PARAMETER TYPE DESCRIPTION
oldMember GuildMember The member before the voice state update
newMember GuildMember The member after the voice state update */
client.on("voiceStateUpdate", function(oldMember, newMember){
console.log(`a user changes voice state`);
// Here we can just check if newMember is in the channel that we want. Bam.
if(newMember.voiceChannel.name == 'channelname') {
// DO SOMETHING.
myVoiceChannel.overwritePermissions(newMember, {
SEND_MESSAGES: true
});
} else {
myVoiceChannel.overwritePermissions(newMember, {
SEND_MESSAGES: null
});
}
});
Let's reduce this:
newMember.voiceChannel - This means what channel their connected to.
voiceChannel.name - Get the name of the channel so we can check it.
Hope I was a help, and by the way, here's a neat little cheatsheet I like to use when developing DiscordJS bots: https://gist.github.com/koad/316b265a91d933fd1b62dddfcc3ff584
So I have been search far and wide over the internet, trying to find a possible way to make a purge command. Now I have found quite a lot of different ways to make one, but none of them either suited me in the way I wanted, or simply worked for me.
SO to start off, here is my code
const Discord = require("discord.js"); // use discord.js
const BOT_TOKEN = "secret bot token :)" // bot's token
const PREFIX = "*" // bot's prefix
var eightball = [ // sets the answers to an eightball
"yes!",
"no...",
"maybe?",
"probably",
"I don't think so.",
"never!",
"you can try...",
"up to you!",
]
var bot = new Discord.Client(); // sets Discord.Client to bot
bot.on("ready", function() { // when the bot starts up, set its game to Use *help and tell the console "Booted up!"
bot.user.setGame("Use *info") // sets the game the bot is playing
console.log("Booted up!") // messages the console Booted up!
});
bot.on("message", function(message) { // when a message is sent
if (message.author.equals(bot.user)) return; // if the message is sent by a bot, ignore
if (!message.content.startsWith(PREFIX)) return; // if the message doesn't contain PREFIX (*), then ignore
var args = message.content.substring(PREFIX.length).split(" "); // removes the prefix from the message
var command = args[0].toLowerCase(); // sets the command to lowercase (making it incase sensitive)
var mutedrole = message.guild.roles.find("name", "muted");
if (command == "help") { // creates a command *help
var embedhelpmember = new Discord.RichEmbed() // sets a embed box to the variable embedhelpmember
.setTitle("**List of Commands**\n") // sets the title to List of Commands
.addField(" - help", "Displays this message (Correct usage: *help)") // sets the first field to explain the command *help
.addField(" - info", "Tells info about myself :grin:") // sets the field information about the command *info
.addField(" - ping", "Tests your ping (Correct usage: *ping)") // sets the second field to explain the command *ping
.addField(" - cookie", "Sends a cookie to the desired player! :cookie: (Correct usage: *cookie #username)") // sets the third field to explain the command *cookie
.addField(" - 8ball", "Answers to all of your questions! (Correct usage: *8ball [question])") // sets the field to the 8ball command
.setColor(0xFFA500) // sets the color of the embed box to orange
.setFooter("You need help, do you?") // sets the footer to "You need help, do you?"
var embedhelpadmin = new Discord.RichEmbed() // sets a embed box to the var embedhelpadmin
.setTitle("**List of Admin Commands**\n") // sets the title
.addField(" - say", "Makes the bot say whatever you want (Correct usage: *say [message])")
.addField(" - mute", "Mutes a desired member with a reason (Coorect usage: *mute #username [reason])") // sets a field
.addField(" - unmute", "Unmutes a muted player (Correct usage: *unmute #username)")
.addField(" - kick", "Kicks a desired member with a reason (Correct usage: *kick #username [reason])") //sets a field
.setColor(0xFF0000) // sets a color
.setFooter("Ooo, an admin!") // sets the footer
message.channel.send(embedhelpmember); // sends the embed box "embedhelpmember" to the chatif
if(message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.channel.send(embedhelpadmin); // if member is a botadmin, display this too
}
if (command == "info") { // creates the command *info
message.channel.send("Hey! My name is cookie-bot and I'm here to assist you! You can do *help to see all of my commands! If you have any problems with the Minecraft/Discord server, you can contact an administrator! :smile:") // gives u info
}
if (command == "ping") { // creates a command *ping
message.channel.send("Pong!"); // answers with "Pong!"
}
if (command == "cookie") { // creates the command cookie
if (args[1]) message.channel.send(message.author.toString() + " has given " + args[1].toString() + " a cookie! :cookie:") // sends the message saying someone has given someone else a cookie if someone mentions someone else
else message.channel.send("Who do you want to send a cookie to? :cookie: (Correct usage: *cookie #username)") // sends the error message if no-one is mentioned
}
if (command == "8ball") { // creates the command 8ball
if (args[1] != null) message.reply(eightball[Math.floor(Math.random() * eightball.length).toString(16)]); // if args[1], post random answer
else message.channel.send("Ummmm, what is your question? :rolling_eyes: (Correct usage: *8ball [question])"); // if not, error
}
if (command == "say") { // creates command say
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!");
var sayMessage = message.content.substring(4)
message.delete().catch(O_o=>{});
message.channel.send(sayMessage);
}
if(command === "purge") {
let messagecount = parseInt(args[1]) || 1;
var deletedMessages = -1;
message.channel.fetchMessages({limit: Math.min(messagecount + 1, 100)}).then(messages => {
messages.forEach(m => {
if (m.author.id == bot.user.id) {
m.delete().catch(console.error);
deletedMessages++;
}
});
}).then(() => {
if (deletedMessages === -1) deletedMessages = 0;
message.channel.send(`:white_check_mark: Purged \`${deletedMessages}\` messages.`)
.then(m => m.delete(2000));
}).catch(console.error);
}
if (command == "mute") { // creates the command mute
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!"); // if author has no perms
var mutedmember = message.mentions.members.first(); // sets the mentioned user to the var kickedmember
if (!mutedmember) return message.reply("Please mention a valid member of this server!") // if there is no kickedmmeber var
if (mutedmember.hasPermission("ADMINISTRATOR")) return message.reply("I cannot mute this member!") // if memebr is an admin
var mutereasondelete = 10 + mutedmember.user.id.length //sets the length of the kickreasondelete
var mutereason = message.content.substring(mutereasondelete).split(" "); // deletes the first letters until it reaches the reason
var mutereason = mutereason.join(" "); // joins the list kickreason into one line
if (!mutereason) return message.reply("Please indicate a reason for the mute!") // if no reason
mutedmember.addRole(mutedrole) //if reason, kick
.catch(error => message.reply(`Sorry ${message.author} I couldn't mute because of : ${error}`)); //if error, display error
message.reply(`${mutedmember.user} has been muted by ${message.author} because: ${mutereason}`); // sends a message saying he was kicked
}
if (command == "unmute") { // creates the command unmute
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!"); // if author has no perms
var unmutedmember = message.mentions.members.first(); // sets the mentioned user to the var kickedmember
if (!unmutedmember) return message.reply("Please mention a valid member of this server!") // if there is no kickedmmeber var
unmutedmember.removeRole(mutedrole) //if reason, kick
.catch(error => message.reply(`Sorry ${message.author} I couldn't mute because of : ${error}`)); //if error, display error
message.reply(`${unmutedmember.user} has been unmuted by ${message.author}!`); // sends a message saying he was kicked
}
if (command == "kick") { // creates the command kick
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!"); // if author has no perms
var kickedmember = message.mentions.members.first(); // sets the mentioned user to the var kickedmember
if (!kickedmember) return message.reply("Please mention a valid member of this server!") // if there is no kickedmmeber var
if (!kickedmember.kickable) return message.reply("I cannot kick this member!") // if the member is unkickable
var kickreasondelete = 10 + kickedmember.user.id.length //sets the length of the kickreasondelete
var kickreason = message.content.substring(kickreasondelete).split(" "); // deletes the first letters until it reaches the reason
var kickreason = kickreason.join(" "); // joins the list kickreason into one line
if (!kickreason) return message.reply("Please indicate a reason for the kick!") // if no reason
kickedmember.kick(kickreason) //if reason, kick
.catch(error => message.reply(`Sorry #${message.author} I couldn't kick because of : ${error}`)); //if error, display error
message.reply(`${kickedmember.user.username} has been kicked by ${message.author.username} because: ${kickreason}`); // sends a message saying he was kicked
}
});
bot.login(BOT_TOKEN); // connects to the bot
It is the only file in my bot folder except the package.json, package-lock.json and all the node_modules.
What I'm trying to do is type in discord *purge [number of messages I want to purge] and get the bot to delete the amount of the messages I asked it to delete, PLUS the command I entered (for example, if I ask the bot to delete 5 messages, he deletes 6 including the *purge 5 message.
Any help would be much appreciated, thanks!
What you are looking for is this (bulkDelete()) method for Discord.js.
It bulk deletes a message, just simply pass in a collection of message in the method and it will do the job for you.
(You can use messages property from channel, otherwise if you prefer promises, then try fetchMessages() method. )
Just make sure that the channel is not a voice channel, or a DM channel. And finally, your bot needs to have permission too.
You can get your own bot's permission for the guild using message.guild.member(client).permissions, or you can just directly use message.guild.member(client).hasPermission(permission), which returns a boolean that determines if your bot have a desired permission.
(The method docs for hasPermission() is here)
note sure if this is still relevant but this what i use in my bots
if (!suffix) {
var newamount = "2";
} else {
var amount = Number(suffix);
var adding = 1;
var newamount = amount + adding;
}
let messagecount = newamount.toString();
msg.channel
.fetchMessages({
limit: messagecount
})
.then(messages => {
msg.channel.bulkDelete(messages);
// Logging the number of messages deleted on both the channel and console.
msg.channel
.send(
"Deletion of messages successful. \n Total messages deleted including command: " +
newamount
)
.then(message => message.delete(5000));
console.log(
"Deletion of messages successful. \n Total messages deleted including command: " +
newamount
);
})
.catch(err => {
console.log("Error while doing Bulk Delete");
console.log(err);
});
basic function is to specify number of messages to purge and it will delete that many plus the command used, the full example is here