I'm trying to make a music bot with DiscordJS. It sends a message again when it switches to new music. When it is too much, it causes pollution. How can I set the old message to be deleted and the new message to remain when I switch to a new song or skip a song?
Code:
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, Client } = require('discord.js');
const ms = require('ms');
/**
* #param {Client} client
*/
module.exports.run = async (client, player, track) => {
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
const row = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('loop')
.setEmoji(`π`)
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId('volume-')
.setEmoji(`π`)
.setStyle(ButtonStyle.Danger),
new ButtonBuilder()
.setCustomId('p/p')
.setEmoji(`β―οΈ`)
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId('volume+')
.setEmoji(`π`)
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId('skip')
.setEmoji(`βοΈ`)
.setStyle(ButtonStyle.Secondary),
);
const embed = new EmbedBuilder()
.setAuthor({
name: `Now Playing`,
iconURL: track.info.requester.displayAvatarURL(),
})
.setColor('Blue')
.setDescription(
`
**Track**: [${track.info.title}](${track.info.uri})
`,
)
const channel = client.channels.cache.get(player.textChannel)
await channel?.send({ embeds: [embed], components: [row] })
};
When I switch to the new song, I want the old message to be deleted. I tried removing some lines but it didn't work.
You could store an object that contains channel IDs and message IDs somewhere else in your code:
let songMessages = {
'channel-id-here':'message-id-here',
'another-channel-id':'another-message-id',
// etc
}
Instead of sending a new message at the bottom of your run() function, you could first check for an existing message in the current channel, and if there is one, you can delete it.
// assuming you're able to access the songMessages object globally
const channel = client.channels.cache.get(player.textChannel)
if(songMessages[channel.id]) {
let oldMessage = await channel.messages.fetch(songMessages[channel.id])
await oldMessage.delete()
}
let message = await channel?.send({ embeds: [embed], components: [row] })
songMessages[channel.id] = message.id
You'll have to make sure you remove the data from the object after the bot stops playing music as well.
Related
This probably has a very simple fix, but I'm a very beginner programmer so I have no clue what to do. I am trying to delete an embed after 5 seconds, and the error is saying "msg.delete is not a function" This is my code. (I am using slash commands).
const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, EmbedBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('br')
.setDescription('Battle to the death with your friends'),
async execute(message) {
const row = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('joinbutton')
.setLabel('JOIN BATTLE ROYALE')
.setStyle(1),
);
var embed = new EmbedBuilder()
.setTitle(`BATTLE ROYALE STARTING`)
.setColor("0090FF")
.setDescription(`<#${message.user.id}> is starting a battle royale match. Use the button below to join!`)
.setFooter({text: message.user.username, iconURL: message.user.avatarURL()})
.setTimestamp()
message.reply({ embeds: [embed], components: [row] }).then(msg => msg.delete({timeout: 5000}))
},
};
I also have code in my index.js which I don't think could be the problem but I'm just gonna send it anyway.
var brdb = require('./models/br')
if(interaction.isButton())
{
if(interaction.customId == 'joinbutton')
{
var data = {
userid: interaction.user.id,
hp: 100
}
console.log(data)
}
}
This is because "message" is a CommandInteraction, not a Message. You should instead use message.deleteReply() as mentioned in the docs.
I'm quite new to Javascript, normally a Python person. I've looked at some other answers but my embed does not add the fields as expected. The embed itself is sent.
My Discord bot follows the guide provided by the devs (primary file, slash commands, command files). I am trying to loop through the entries in an SQLite query and add them as fields.
My command file is below.
const { SlashCommandBuilder } = require('#discordjs/builders');
const { MessageEmbed } = require('discord.js')
const sqlite = require('sqlite3').verbose();
module.exports = {
data: new SlashCommandBuilder()
.setName('rank')
.setDescription('Rank all points.'),
async execute(interaction) {
const rankEmbed = new MessageEmbed()
.setColor('#0099ff')
.setTitle('Rank Board')
let db = new sqlite.Database('./databases/ranktest.db', sqlite.OPEN_READWRITE);
let queryall = 'SELECT name, points FROM pointstable ORDER BY points DESC'
db.all(queryall, [], (err, rows) => {
if (err) {
console.log('There was an error');
} else {
rows.forEach((row) => {
console.log(row.name, row.points)
rankEmbed.addField('\u200b', `${row.name}: ${row.points}`, true);
});
}
})
return interaction.reply({embeds: [ rankEmbed ] });
}
}
I would also like to convert row.name - held as Discord IDs - to usernames i.e. MYNAME#0001. How do I do this by interaction? I was able to obtain the User ID in another command by using interaction.member.id, but in this case I need to grab them from the guild. In Python I did this with await client.fetch_user but in this case the error await is only valid in async functions and the top level bodies of modules is thrown.
Thanks.
OK I've solved the first aspect, I had the return interaction.reply in the wrong place.
Relevant snippet:
rows.forEach((row) => {
console.log(row.name, row.points)
rankEmbed.addField('\u200b', `${row.name}: ${row.points}`, false);
})
return interaction.reply({embeds: [rankEmbed ]} );
Would still appreciate an answer to the converting row.name (user ID) to user name via fetch.
I've solved the second aspect also. Add the below into the loop.
rows.forEach((row) => {
let client = interaction.client
const uname = client.users.cache.get(row.name);
rankEmbed.addField('\u200b', `${uname}: ${row.points}`, false);
Wanting to have a readout channel for my bot to keep track of what happens, just like a second console log. Want to be able to have it read out in the message the username of the person who used the command. Any ideas? Also, in a similar note, is there a way to copy the console readout and possibly just paste that instead?
var Scraper = require('images-scraper');
const google = new Scraper({
puppeteer: {
headless: true
},
})
module.exports = {
name: 'image',
description: 'Google image scraper',
async execute(message, args){
const readout = message.guild.channels.cache.find(c => c.name === 'bot-readout');
const image_query = args.join(' ');
if(!image_query) return message.channel.send('Please enter a valid image search.');
const image_results = await google.scrape(image_query, 1);
message.channel.send(image_results[0].url);
readout.send('Image sent');
}
}
I think you want
message.author.username (It gives username who sent the message)
or message.member (it gives user as a guildmember)
Just access the author property of the message object and include it via a template string into the message:
readout.send(`Image sent to ${message.author.username}`);
Ended up doing an embed system in a separate channel on my discord.
const Discord = require('discord.js');
module.exports = {
name: 'suggestionlog',
description: 'logs suggestion',
execute(message){
const readout = message.guild.channels.cache.find(c => c.name === 'bot-readout');
const embed = new Discord.MessageEmbed()
.setColor('FADF2E')
.setTitle(message.channel.name)
.setAuthor(message.author.username, message.author.displayAvatarURL({ dynamic: true }))
.setDescription(message);
readout.send(embed)
.catch((err)=>{
throw err;
});
}
}
I want to make a confessions bot where it sends the confession to a private group so it can be reviwed before it is set to the public channel. but when I try to add reactions(to use as aprove or disaprove) it seams to want to add the reactions to the message that was deleted.
const discord = require("discord.js");
module.exports = {
name: 'confessions',
description: "comando para as pesoas confessarem anonimamente",
execute(message, args){
let cf = args.join(' ')
message.dlete()
const cfAdm = message.guild.channels.cache.get('767082831205367809')
let embed = new discord.MessageEmbed()
.setTitle('**CONFISSΓO**')
.setDescription(cf)
.setColor('#000000')
cfAdm.send(embed);
message.react('π').then(r => {
message.react('π');
});
}
}
Try changing
cfAdm.send(embed);
message.react('π').then(r => {
message.react('π');
to
cfAdm.send(embed)
.then( function (message) {
message.react('π').then(() => message.react('π'));
And you also made a typo with message.dlete() it needs to be message.delete()
I'm trying to create a channel switch logger which allows me to specify a channel where the messages get posted.
So, for example, I create a TextChannel called "Channel Switches". When now a user changes voice channel, it should appear a message in this Channel. (eg. <USER> left channel <CHANNEL> and joined <CHANNEL>.)
MY PROBLEM IS: I get no errors and the Bot is not responding...
Here my first try:
var Discord = require('discord.js');
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 + ")");
console.log("Logged in as ${client.user.tag}!");
});
bot.on('voiceStateUpdate', (oldMember, newMember) => {
let newUserChannel = newMember.voiceChannel
let oldUserChannel = oldMember.voiceChannel
if (!oldUserChannel && newUserChannel) {
bot.channels.get('475330828466126848').send("User went form Channel" + oldUserChannel.name + "to the new" +
newUserChannel.name + "Channel");
}
});
Your bot does not respond because the client is not initialized correctly. You're creating the client like this:
var bot = new Discord.Client({
token: auth.token, // <--
autorun: true // <--
});
The problem is that these arguments do not exist in discord.js, as stated by the Client docs.
To log into your bot, please use Client.login():
var bot = new Discord.Client();
bot.login(auth.token);