I need help reassigning a variable in a bot menu - javascript

I am trying to build a setup menu for my bot that the server owner can use to configure the bot. The menu is triggered when the owner types =setup. I want the bot to reply with several embed messages asking the user questions in order to correctly configure the bot.
This is my first Discord.js project so I am unaware of the syntax but trying to learn. I have a constant variable called prefix assigned to = when the bot is implemented into the server.
The first prompt on the bot menu asks the user to change the prefix to anything they want. I need help understanding how to reassign my original constant variable to the new prefix they are requesting.
var PREFIX = '=';
bot.on('message', message=>{
let args = message.content.substring(PREFIX.length).split(" ");
switch(args[0]){
case 'setup':
const embed = new Discord.RichEmbed()
.setTitle('Step 1 of 1')
.setDescription('Set your Prefix')
.setColor(0xF1C40F)
message.channel.sendEmbed(embed);
//I want the user to now enter their own PREFIX and have the
//bot save their responce as the new PREFIX
break;
}
})
What I want to happen is when the user types their desired prefix, the bot will reassign prefix in the code, and delete the bots question and the users response and begin to prompt them with the next question.

depending if your bot is going to be in multiple servers with different prefixes:
If so then you need a database to save the prefix for each server and
then get it when a user sends a message from that server
If not I would use a json file to store the prefix, then have node
edit the file when it needs to change
Or look at https://discordjs.guide/keyv/ there is a great tutorial there to do what you want

You can't prompt the user to respond (from what I know), you'll need to wait for the user to write another message and analyze it.
A message is linked to a user, so when a user initiates the command to change the prefix, you want to make sure that the same user changed the prefix.
This untested but should be close to the solution you're looking for.
let prefix = '=';
let expectingResponseFrom = null;
bot.on('message', message=>{
// same user sent a response
if(expectingResponseFrom !== null && expectingResponseFrom === message.user.id){
expectingRepsonseFrom = null;
prefix = message.content.trim();
return;
}
const regex = new RegExp(`^${prefix}([^\s]+)`, 'g');
cosnt command = regex.exec(message.content)[1] || '';
switch(command){
case 'setup':
const embed = new Discord.RichEmbed()
.setTitle('Step 1 of 1')
.setDescription('Set your Prefix')
.setColor(0xF1C40F)
message.channel.sendEmbed(embed);
// memorize user who initiated a prefix change
expectingResponseFrom = message.user.id;
break;
}
})
The regex allows for a better (my opinion) way of getting the command
console.log(
(/^=([^\s]+)/g).exec("=hello should not get this"),
(/^=([^\s]+)/g).exec("="),
(/^=([^\s]+)/g).exec("= should not get this")
)

You should definitely use a database to store prefixes and other server settings, it's more efficient and stable than using a JSON file for example.
I suggest you use mongoose and/or just MongoDB if you're unsure as to what to use.

Related

How do I set a variable to a specific voice channel discord.js?

I'm trying to set a variable to a specific voice channel so that I can always have the bot work in the same channel rather than whatever channel the user is in. I'm new to js and writing discord bots. Most of my code is from here.
So far I've tried everything I can think of from
const voiceChannel = channel_ID;
to
const voiceChannel = channel.id(channel_ID);
(Where channel_ID is the actual ID number discord assigns)
I've looked on discord.js.org but I can't find a solution.
I'm probably doing something incredibly obvious wrong, but I can't figure out what it is. Any ideas?
So, in order to join your bot on a specific channel you first have to actually get the channel
How to get the (ID of your) channel?
Well, you have two options for this:
Activate the developer mode in your Discord > Right-click on the target channel and select Copy ID > paste it into your code
const channelId = '1234567890';
const targetChannel = client.channels.cache.get(channelId);
Get the channel by it's name
const targetChannel = guild.channels.cache.find(channel => channel.name === "Name of the channel");
If this is done you should have your channel now, but that's not all!
Now you want to check, if your bot really got the channel and if you want to be able to use .join(), you have to make sure it's a VoiceChannel:
// Check if the channel is undefined or not
if(!targetChannel) return message.channel.send('Channel not found!');
// Check if the channel is a voice channel
if(targetChannel.type !== 'voice') return message.channel.send('This is not a voice channel!');
// If it passed the code above you can now let your bot join the channel
targetChannel.join().then(connection => {
console.log("Successfully connected.");
}).catch(e => {
console.error(e);
You may store the variable as anything, as ID is a set of integers it can be stored without quotes ("") , template literals (``), etc.
Although since it may conflict upon using methods such as parseInt() we would store it as a string. So let's say we have an ID now and we store it as:
const Channel = ('ChannelID');
var Channel = ('ChannelID');
let Channel = ('ChannelID'); // of course only one of these
Where ChannelID is the actual ID, now we may access it later to fetch/get the channel like so:
<client>.channels.cache.get(Channel) || <client>.channels.fetch(Channel);

How to work with member role update part of audit log in discord.js

I am currently making a bot to notify people by sending a message when a member role is being updated on the server. I don’t know how to set up the initial part which should be formally client.on part.
Here I have shown a bit of my code that I think should be working but unfortunately it is not working.
const Discord = require(‘discord.js’);
const client = Discord.Client();
client.on('guildMemberUpdate', (oldMember, newmember) => {
This is what I’m expecting to do:
Before I give you the code, I'll give you the steps that I took to achieve it.
Tip: ALWAYS use the documentation. The discord.js documentation helped me a lot of times.
Process:
Set up a designated text channel. In my case, I manually grabbed the channel's ID and set it as the variable txtChannel. You will have to replace my string of numbers with your own channel ID.
I cached every single role ID from the "new" member as well as from the "old" member.
Checked whether or not the length of the new member roles array was longer than the old member roles array. This signifies that the member has gained a role.
Created a filter function that "cancels" out every single role ID that both new and old role arrays have in common.
Grabbed the icon URL - I found out that if you try to get the URL of a user who has the default discord icon, it'll return NULL. To bypass this, you could just grab some sort of invisible PNG online and set it as a placeholder. Else you'll get an error saying that it wasn't able to retrieve the proper URL link.
Set up the embed, and sent it into the text channel!
Note:
At first, I couldn't figure out why the bot wasn't registering for other users who have their roles changed. Then I found this question on Stack Overflow. The link states that you have to make sure to enable Guild Members Intent. Just follow the instructions from the link and you should be all set! It's a little bit outdated (in terminology), so when it references "Guild Members Intent" it actually is "Server Members Intent" now.
Code:
It's awfully elaborate, but it gets the job done.
client.on('guildMemberUpdate', (oldMember, newMember) => {
let txtChannel = client.channels.cache.get('803359668054786118'); //my own text channel, you may want to specify your own
let oldRoleIDs = [];
oldMember.roles.cache.each(role => {
console.log(role.name, role.id);
oldRoleIDs.push(role.id);
});
let newRoleIDs = [];
newMember.roles.cache.each(role => {
console.log(role.name, role.id);
newRoleIDs.push(role.id);
});
//check if the newRoleIDs had one more role, which means it added a new role
if (newRoleIDs.length > oldRoleIDs.length) {
function filterOutOld(id) {
for (var i = 0; i < oldRoleIDs.length; i++) {
if (id === oldRoleIDs[i]) {
return false;
}
}
return true;
}
let onlyRole = newRoleIDs.filter(filterOutOld);
let IDNum = onlyRole[0];
//fetch the link of the icon name
//NOTE: only works if the user has their own icon, else it'll return null if user has standard discord icon
let icon = newMember.user.avatarURL();
const newRoleAdded = new Discord.MessageEmbed()
.setTitle('Role added')
.setAuthor(`${newMember.user.tag}`, `${icon}`)
.setDescription(`<#&${IDNum}>`)
.setFooter(`ID: ${IDNum}`)
.setTimestamp()
txtChannel.send(newRoleAdded);
}
})

Message Specific PFP. (like TupperBox)

I am looking to send a message that has a different profile picture than the bot. Basically, like Tupper Bot does. I can't seem to figure out how to do it anywhere, I've read the documentation and searched around.
You can use a webhook to do what you describe. If you already have a webhook link see here on how to use it. This works from external programs too.
If you don't, you can create a webhook with your bot and then send messages to it. In this example we will create a simple webhook and send a message to it.
First we should check if the channel already has a webhook. That way you don't create a new one everytime you use the command. You do that with the fetchWebhooks() function which returns a collection if there is a webhook present. If that is the case we will get the first webhook in the collection and use that. Note: if you have more then one webhook you can of course add additional checks after the initial one.
If there are no webhooks present, we create a new one with createWebhook(). You can pass additional options after the name.
let webhook;
let webhookCollection = await message.channel.fetchWebhooks();
if (webhookCollection.first()) {
webhook = webhookCollection.first();
} else {
webhook = await message.channel.createWebhook("new webhook", {
avatar: "https://i.imgur.com/tX5nlQ3.jpeg"
});
}
Note: in this example we use the channel the message came from but you can use any channel you want
Technically we can now send messages already.
webhook.send("this is a test");
What you can also do is create a webhookClient. Thats a little like the discord client you create when you start your bot. It takes the webhook ID and token as well as additional options you can set for clients.
const hookclient = new Discord.WebhookClient(webhook.id, webhook.token);
This lets you use a few additional methods like setInterval.
hookclient.setInterval(() => {
hookclient.send("This is a timer test");
}, 1000)
This lets you use the webhook without creating or fetching one first.

How do I make a Commando bot respond to a message with a certain substring anywhere in the message

I'm working with a friend to add something to an existing Discord bot. There a number of working commands that use discord.js-commando, so we're tied to using Commando.
The guild we're doing this for has moved some resources from an old site to a new one, and we'd like to remind the guild members who link to the old site that they should use the new site instead:
// User123 says...
Check out https://www.example.com/.
// bot responds:
Hey User123! You should use our new site! https://www.example2.com/
The bot would only trigger if it sees www.example.com.
Here's the code...
// file: index.js
const bot = new Commando.Client({
commandPrefix: './'
});
bot.registry
.registerGroup('autoresponses', 'AutoResponses')
// other groups
.registerDefaults()
.registerCommandsIn(__dirname + '/commands')
;
and the file I'm working on
// file: commands/autoresponses/messages.js
const discord = require('discord.js');
client.on("message", function(message) {
if (message.author.bot) {
return;
}
if (message.content.includes("www.example.com")) {
var responseString = "Hey " + message.author + "! That's the old site! Please use the new one: https://www.example2.com/";
message.channel.send(responseString);
}
};
Trouble is, this doesn't use Commando, just regular discord.js. Is this even possible with Commando? Or do I need another approach?
If you intend on using Comando you'll need to work with the Commando.Client. The way your bot is set up is so you only need to add a command in the commands folder. Seems like Comando has a way to trigger on a regular expression.
let Command = require('Comando').client;
module.exports = class OldWebsite extends Command {
constructor(client){
super(client, {/* Your command config here */, patterns: [/website\.com/] });
//patterns is a prop that accepts regular expressions to match on a message
}
async run(msg){
return msg.reply('Hey that\'s our old webiste!');
}
}
Here's an example of a Command. Here's the documentation of what can go into the CommandInfo (your command config).

How to get specific member username with discord.js

I would like to add one specific member information (username + avatar) into an embed message. Does someone know how to do that?
const feedback = new discord.RichEmbed()
.setColor([0, 0, 255])
.setFooter("Bot created by : " + message.author.username, message.author.avatarURL)
.setDescription("The text I want to be sent")
On the code above, I would like to change "message.author.username" and "message.author.avatarUrl" by a specific discord member identification id such as : 436577130583949315 for example.
However I don't know what is the way from that discord identification number to be able to show the username and the avatar.
Thanks in advance for your help :)
The following code must be modified to use the latest version of Discord.js (v12 at the time of this edit) due to the implementation of Managers.
You can retrieve a user by their ID from the client's cache of users, Client#users. However, every user isn't guaranteed to be cached at all times, so you can fetch a user from Discord using Client#fetchUser(). Keep in mind, it returns a Promise. If the user is in the cache, the method will return it.
Example:
// Async context needed for 'await'
try {
const devID = '436577130583949315';
const dev = await client.fetchUser(devID);
const feedback = new discord.RichEmbed()
.setColor([0, 0, 255])
.setFooter(`Bot created by ${dev.tag}.`, dev.displayAvatarURL)
.setDescription('Your text here.');
await message.channel.send(feedback);
} catch(err) {
console.error(err);
}

Categories