I am trying to move the bot from 1 channel to another when the user switches channels
const client = require("../index.js");
module.exports = client => {
client.on("voiceStateUpdate", (oldState, newState) => {
let oldChannel = oldState.voiceChannel, // the previous channel, if there was one
newChannel = newState.voiceChannel; // the current channel, if there is one
if (oldChannel != newChannel) {
// if the channel has changed
// do your stuff....
channel = msg.member.voice.channel
channel.join()
}
});
}
You just need to use the newState's voiceChannel
client.on("voiceStateUpdate", (oldState, newState) => {
let oldChannel = oldState.voiceChannel, // the previous channel, if there was one
let newChannel = newState.voiceChannel; // the current channel, if there is one
if (oldChannel != newChannel) {
newChannel.join();
}
});
Related
I am building a discord bot to listen to messages on a specific channel. The issue is that my code listens to all channels.
Even if I use a condition to check for the channel id before picking the message, it means it will do more work than is necessary.
I want to avoid the case of selecting messages from multiple channels and just concentrate on the messages in the channel I want to listen to.
require('dotenv').config();
const { Client, Intents, Collection } = require('discord.js');
const {TOKEN, CHANNEL_ID} = require('./src/config/index');
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
client.once('ready', (c) => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client.on('messageCreate', async (message) => {
console.log(message)
})
client.login(TOKEN);
This code above is the current code I am using
You can check where the message was posted before running any code.
As far as i am aware that is the only way to do this
client.on('messageCreate', async (message) => {
if (message.channel.id === "YOUR CHANNEL ID") {
// run code here
}
})
There are three ways of sending a message to a specific channels.
//1. Single channel listener
client.on('messageCreate', async (message) => {
if (message.channel.id === "channel_id") {
//For a single channel listener.
} else {
//You can send a message if the channel_id is not equal.
}
})
//2. Multiple channel listener / can be use as .json
let channels = [
"channel_id",
"channel_id"
]
if(channels.includes(message.channel.id)) {
//Multiple Channel ID's
} else {
//An example of return for not including some channel_id
message.channel.send("I can't use these command on this channel.")
}
//3. Can be use like using a database such as mongodb / mongoose / etc.
let channels = {
"chan": [
"987627957478637619",
"948780253948575764"
]
}
if(channels?.chan.includes(message.channel.id)) {
//Multiple Channel ID's
} else {
//An example of return for not including some channel_id
message.channel.send("I can't use these command on this channel.")
}
This is my code, pretty simple and it works.
let allowedChannels = [
/*bot-channel*/"1053346645779152993",
/*console*/"1053346646227959900"
];
client.on('messageCreate', msg => {
//VERY important, exit if the message is from a bot to prevent loops
if (msg.author.bot) {
return;
};
//Check if the channel is accepting bot commands
if (allowedChannels.includes(msg.channel.id) === false) {
return;
}
}
I am making a discord bot that plays music. Currently, the embedded list works fine and every time I add a song to the queue, the list deletes itself and creates a new embedded queue list updated with the new song. However, I can't figure out how to make this queue list update itself when I use the skip button I have implemented (I'm new to programming).
Example of how it works now:
Pressing the button skips the song, but as stated before, how would I refresh the list every time I press the button?
const ytdl = require('ytdl-core');
const ytSearch = require('yt-search');
process.setMaxListeners(1000000000000);
const { MessageEmbed } = require('discord.js');
ffmpeg_options = {
'options': '-vn',
"before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5"
}
//Global queue for your bot. Every server will have a key and value pair in this map. { guild.id, queue_constructor{} }
const queue = new Map();
module.exports = {
name: 'play',
aliases: ['skip', 'stop'], //We are using aliases to run the skip and stop command follow this tutorial if lost: https://www.youtube.com/watch?v=QBUJ3cdofqc
cooldown: 0,
description: 'Advanced music bot',
async execute(message, args, cmd, button, skip, client, Discord){
//Checking for the voicechannel and permissions (you can add more permissions if you like).
const voice_channel = message.member.voice.channel;
if (!voice_channel) return message.channel.send('You need to be in a channel to execute this command!');
const permissions = voice_channel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) return message.channel.send('You dont have the correct permissions.');
if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissions.');
//This is our server queue. We are getting this server queue from the global queue.
const server_queue = queue.get(message.guild.id);
let checker = false;
if (cmd === 'stop' && !server_queue){
return message.channel.send("The bot is not in the channel, you dont have to stop him.");
}
//If the user has used the play command
if (cmd === 'stop') stop_song(message, server_queue);
else if(skip === true) {
skip_song(message, server_queue);
}
else if (cmd === message.content){
//if (!args.length) return message.channel.send('You need to send the second argument!');
let song = {};
//If the first argument is a link. Set the song object to have two keys. Title and URl.
if (ytdl.validateURL(args[0])) {
const song_info = await ytdl.getInfo(args[0]);
song = { title: song_info.videoDetails.title, url: song_info.videoDetails.video_url }
message.delete({ timeout:1000 })
} else {
//If there was no link, we use keywords to search for a video. Set the song object to have two keys. Title and URl.
const video_finder = async (query) =>{
const video_result = await ytSearch(query);
return (video_result.videos.length > 1) ? video_result.videos[0] : null;
}
const video = await video_finder(args.join(' '));
if (video){
song = { title: video.title, url: video.url }
} else {
message.channel.send('Error finding video.');
}
message.delete({ timeout:1000 })
}
if (skip === true && server_queue) {
}
//If the server queue does not exist (which doesn't for the first video queued) then create a constructor to be added to our global queue.
if (!server_queue){
const queue_constructor = {
voice_channel: voice_channel,
text_channel: message.channel,
connection: null,
songs: []
}
//Add our key and value pair into the global queue. We then use this to get our server queue.
queue.set(message.guild.id, queue_constructor);
queue_constructor.songs.push(song);
//Establish a connection and play the song with the vide_player function.
try {
const connection = await voice_channel.join();
queue_constructor.connection = connection;
video_player(message.guild, queue_constructor.songs[0]);
} catch (err) {
queue.delete(message.guild.id);
message.channel.send('There was an error connecting!');
throw err;
}
} else {
server_queue.songs.push(song);
message.channel.bulkDelete(2)
.then(messages => console.log(`Bulk deleted ${messages.size} messages`))
.catch(console.error);
//where I actually make the embeded queue list
const queueList = server_queue.songs.map((song, i) => `[${++i}] - ${song.title}`);
const queueEmbed = new MessageEmbed()
.setDescription(queueList);
return message.channel.send(queueEmbed, button);
}
}
}
}
const video_player = async (guild, song) => {
const song_queue = queue.get(guild.id);
//If no song is left in the server queue. Leave the voice channel and delete the key and value pair from the global queue.
if (!song) {
song_queue.voice_channel.leave();
queue.delete(guild.id);
return;
}
const stream = ytdl(song.url, { filter: 'audioonly' });
song_queue.connection.play(stream, { seek: 0, volume: 0.5 })
.on('finish', () => {
song_queue.songs.shift();
video_player(guild, song_queue.songs[0]);
});
//await song_queue.text_channel.send(`🎶 Now playing **${song.title}**`)
}
const skip_song = (message, server_queue) => {
if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!');
if(!server_queue){
return message.channel.send(`There are no songs in queue 😔`,);
}
server_queue.connection.dispatcher.end();
//message.delete({ timeout:20000})
}
const stop_song = (message, server_queue) => {
if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!');
server_queue.songs = [];
server_queue.connection.dispatcher.end();
//message.delete({ timeout:20000})
}
return message.channel.send(queueEmbed, button);
That line above returns a Promise which resolves to a Message object. Change it to something like this:
const embeddedMessage = await message.channel.send(queueEmbed, button);
return embeddedMessage;
So when a user clicks the skip button you can simply call
embeddedMessage.edit(your_new_embed, button)
I have a basic ticketing system for a suggestions channel.
Ideally, when a user does .exesuggest <whatever suggestion they want> (.exe is the bot prefix), I want the bot to reply that the ticket has been sent to staff, i want the bot to delete the user's message, and to delete it's own message after 5 seconds. At the same time, the bot will send a message with the suggestion's author and the suggestion itself into a staff channel.
At the moment everything is working except for the bot deleting it's own message after 5 seconds.
Here is my code:
const Discord = require("discord.js")
const channelId = '873769980729106442'
const check = '✅'
let registered = false
const registerEvent = client => {
if (registered) {
return
}
registered = true
client.on('messageReactionAdd', (reaction, user) => {
if (user.bot) {
return
}
const { message } = reaction
if (message.channel.id === channelId) {
message.delete()
}
})
}
module.exports = {
commands: ['ticket', 'suggest', 'suggestion'],
minArgs: 1,
expectedArgs: '<message>',
callback: (userMessage, arguments, text, client) => {
const { guild, member } = userMessage
registerEvent(client)
const channel = guild.channels.cache.get(channelId)
const newTicketEmbed = new Discord.MessageEmbed()
.setAuthor(userMessage.author.username)
.setTitle('Created a new ticket.')
.setDescription(`"${text}"`)
.setFooter(`Click the ${check} icon to delete this message.`)
channel.send(newTicketEmbed).then(ticketMessage => {
ticketMessage.react(check)
const replyEmbed = new Discord.MessageEmbed()
.setDescription(`<#${member.id}> Your ticket has been created! Expect a reply soon!`)
userMessage.channel.send(replyEmbed)
})
}
}
I have a working command base handler in another file that makes the command work.
I just need to know exactly how to make that bot's reply in replyEmbed to be deleted after 5 seconds.
You can use a setTimeout function to delay the <message>.delete() function from executing.
Example:
setTimeout(function() { // Setup a timer
userMessage.delete(); // Deletes the users message
ticketMessage.delete(); // Deletes the ticket message
}, 5000); // 5 seconds in milliseconds
Full example:
const Discord = require("discord.js")
const channelId = '873769980729106442'
const check = '✅'
let registered = false
const registerEvent = client => {
if (registered) return;
registered = true
client.on('messageReactionAdd', (reaction, user) => {
if (user.bot) return;
const { message } = reaction
if (message.channel.id === channelId)
message.delete()
});
}
module.exports = {
commands: ['ticket', 'suggest', 'suggestion'],
minArgs: 1,
expectedArgs: '<message>',
callback: (userMessage, arguments, text, client) => {
const { guild, member } = userMessage
registerEvent(client)
const channel = guild.channels.cache.get(channelId)
const newTicketEmbed = new Discord.MessageEmbed()
.setAuthor(userMessage.author.username)
.setTitle('Created a new ticket.')
.setDescription(`"${text}"`)
.setFooter(`Click the ${check} icon to delete this message.`)
channel.send(newTicketEmbed).then(ticketMessage => {
ticketMessage.react(check)
const replyEmbed = new Discord.MessageEmbed()
.setDescription(`<#${member.id}> Your ticket has been created! Expect a reply soon!`)
userMessage.channel.send(replyEmbed);
setTimeout(function() { // Setup a timer
userMessage.delete(); // Deletes the users message
ticketMessage.delete(); // Deletes the ticket message
}, 5000); // 5 seconds in milliseconds
});
}
}
In Discord.js v13 you have to use setTimeout.
You can implement what you want like this:
userMessage.channel.send(replyEmbed).then(msg => {
setTimeout(() => msg.delete(), 5000);
});// It will delete after 5 seconds
It might work.
Message.delete has an options argument which is an object, and you can set the timeout there (v13 doesn’t have this!):
userMessage.delete({timeout: 5000}) //deletes after 5000 ms
v13 must use setTimeout since the feature was removed
setTimeout(() => userMessage.delete(), 5000) //deletes after 5000 ms
This code is for playing music, and I want to have a stop command on my bot. Could you help me?
const Discord = require("discord.js");
const client = new Discord.Client();
const config = require("./config.json")
const ytdl = require("ytdl-core")
const streamOptions = {seek:0, volume:1}
client.on("message", async message => {
if(message.author.bot) return
if(message.channel.type === "dm") return
if(!message.content.startsWith(config.prefix)) return
const args = message.content.slice(config.prefix.length).trim().split(/ +/g)
const comando = args.shift().toLocaleLowerCase()
if(comando === "play") {
var voiceChannel = message.guild.channels.cache.get("733122593019789314")
let file = args[0]
if(voiceChannel == null) {
console.log("Canal não encontrado.")
}
if(voiceChannel != null) {
console.log("Canal encontrado.")
await voiceChannel.join().then(connection => {
const stream = ytdl(file, {filter:"audioonly", quality:"highestaudio"})
const DJ = connection.play(stream, streamOptions)
DJ.on("end", end => {
voiceChannel.leave()
})
}).catch(console.error)
}
}/* I was trying to do the command this way:
else if(comando === "stop") {
voiceChannel.leave()
}*/
}
client.login(config.token);
Everything works, I just want to stop the music.
(I'm Brazilian, some words or sentences may be wrong.)
Thank you for your help! 😁
You can use StreamDispatcher.pause() and StreamDispatcher.resume().
Your StreamDispatcher is defined as DJ, so you can use:
DJ.pause(); // Pauses the stream.
DJ.resume(); // Resumes the stream.
DJ.destroy(); // Ends the stream.
When I'm Trying To Make My Discord Music Bot I Get An Error In Discord Not The Command Line Though, It Cannot Tell If I'm In A Voice Channel Or Not
Here's My Code
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
const serverQueue = queue.get(message.guild.id);
if (message.content.startsWith(`${prefix}play`)) {
execute(message, serverQueue);
return;
} else if (message.content.startsWith(`${prefix}skip`)) {
skip(message, serverQueue);
return;
} else if (message.content.startsWith(`${prefix}stop`)) {
stop(message, serverQueue);
return;
} else {
message.channel.send('You need to enter a valid command!')
}
});
process.on('unhandledRejection', error => console.error('Uncaught Promise Rejection', error));
async function execute(message, serverQueue) {
const args = message.content.split(' ');
const voiceChannel = message.member.voiceChannel;
if (!voiceChannel) return message.channel.send('You need to be in a voice channel to play music!');
const permissions = voiceChannel.permissionsFor(message.bot.user);
if (!permissions.has('CONNECT') || !permissions.has('SPEAK')) {
return message.channel.send('I need the permissions to join and speak in your voice channel!');
}
const songInfo = await ytdl.getInfo(args[1]);
const song = {
title: songInfo.title,
url: songInfo.video_url,
};
if (!serverQueue) {
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: 5,
playing: true,
};
queue.set(message.guild.id, queueContruct);
queueContruct.songs.push(song);
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
play(message.guild, queueContruct.songs[0]);
} catch (err) {
console.log(err);
queue.delete(message.guild.id);
return message.channel.send(err);
}
} else {
serverQueue.songs.push(song);
console.log(serverQueue.songs);
return message.channel.send(`${song.title} has been added to the queue!`);
}
}
function skip(message, serverQueue) {
if (!message.member.voiceChannel) return message.channel.send('You have to be in a voice channel to stop the music!');
if (!serverQueue) return message.channel.send('There is no song that I could skip!');
serverQueue.connection.dispatcher.end();
}
function stop(message, serverQueue) {
if (!message.member.voiceChannel) return message.channel.send('You have to be in a voice channel to stop the music!');
serverQueue.songs = [];
serverQueue.connection.dispatcher.end();
}
function play(guild, song) {
const serverQueue = queue.get(guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection.playStream(ytdl(song.url))
.on('end', () => {
console.log('Music ended!');
serverQueue.songs.shift();
play(guild, serverQueue.songs[0]);
})
.on('error', error => {
console.error(error);
});
dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
}
I Found It On This Website https://medium.com/free-code-camp/how-to-create-a-music-bot-using-discord-js-4436f5f3f0f8
And When I Start The Code It Says I'm Not In One,
Any Type Of Feedback Would Be Greatly Appreciated!
Try this
if (!message.member.voice.channel)
return message.reply('you are not in a voice channel'),
The problem comes from the fact that you're using the GuildMember.voiceChannel property, which exists only in discord.js#v11. The v12 equivalent is GuildMember.voice.channel, you can use it like this:
// You can use this as before, since it's the same VoiceChannel element
const voiceChannel = message.member.voice.channel