Referencing a DM channel - javascript

I'm trying to create a command that allows users to create their password following prompts through DM. I'm able to send a message to the user, but not able to read a message sent back with a MessageCollector because I cannot find a way to reference the DM channel.
I have tried using another instance of bot.on("message", message) here, but that creates a leak in the system causing the second instance to never disappear.
I also can't let users use a command say !CreatePassword *** because this function is linked with many others in a strict order.
Maybe I'm doing something fundamentally wrong, or approaching the problem in a bad way, but I need a way to reference a DM channel.
This is the best iteration of my code so far.
function createAccount(receivedMessage, embedMessage)
{
const chan = new Discord.DMChannel(bot, receivedMessage.author);
const msgCollector = new Discord.MessageCollector(chan , m => m.author.id == receivedMessage.author.id);
msgCollector.on("collect", (message) =>
{
// Other Code
msgCollector.stop();
// Removing an embed message on the server, which doesn't have a problem.
embedMessage.delete();
})
}
I can show the rest of my code if necessary.
Thank you for your time. I've lost an entire night of sleep over this.

I would do it like this (I'll assume that receivedMessage is the message that triggered the command, correct me if I'm wrong)
async function createAccount(receivedMessage, embedMessage) {
// first send a message to the user, so that you're sure that the DM channel exists.
let firstMsg = await receivedMessage.author.send("Type your password here");
let filter = () => true; // you don't need it, since it's a DM.
let collected = await firstMsg.channel.awaitMessages(filter, {
maxMatches: 1, // you only need one message
time: 60000 // the time you want it to run for
}).catch(console.log);
if (collected && collected.size > 0) {
let password = collected.first().content.split(' ')[0]; // grab the password
collected.forEach(msg => msg.delete()); // delete every collected message (and so the password)
await firstMsg.edit("Password saved!"); // edit the first message you sent
} else await firstMsg.edit("Command timed out :("); // no message has been received
firstMsg.delete(30000); // delete it after 30 seconds
}

Related

Discord.JS Message Edit

I want to edit the message over and over again.
So I made variable
this.msgRef = await channel.send({ embeds: [embedMessage] });
If I want to edit I use
this.msgRef.edit(...)
If the bot for some reason disconnects, he will lose msgReference.
Because of that, I saved it to DB.
How to create a message again because Message (object) in Discord.JS have a private constructor?
If you want to get the message again, you can simply fetch the channel's messages every time you bot connects (on the ready event for example) like so
client.on('ready', () =>{
const messages = await channel.messages.fetch()
client.msgRef = messages.find(msg => msg.author.id === client.user.id
&& msg.embeds[0]
// Etc.. Add as many conditions to make sure you choose the right message
);
})
This way, use client.msgRef.edit(...) whenever you want.

How can I add a role to user, without him sending any message first?

I've searched for answers but only found how to assign a server role to someone who either sent some message or called a command.
How can I find a specific user on a server and assign a role to them without them sending any messages or doing anything at all?
I tried some things that didn't work:
// the server bot is in
const server = client.guilds.cache.get("my server id here");
// trying to find specific user on the server
let myusr = server.members.cache.get("id", "user id here");
Any suggestions/solutions?
EDIT: Here's the code I have so far:
const { Client } = require('discord.js');
const client = new Client();
client.on('ready', () => {
console.log(client.user.tag);
// grabbing the server
const guild = client.guilds.cache.get("my server's id");
// calling a function and passing my server to it
setUsrRole(guild);
});
function setUsrRole(server) {
// grabbing my user
let myusr = server.members.fetch("My user id");
// finding my role by name
let myRole = server.roles.cache.find(myRole => myRole.name === "role name");
// trying to add the role to my user
myusr.roles.add(myRole);
// I also tried myusr.addRole(myRole);
};
// Bot login
client.login('my bot token');
There are multiple ways, but I will show you 2 ways.
client.on('guildMemberAdd', member => {
member.roles.add('someRole');
})
That way is if you want to add on member join, but you need to make sure in your discord developer portal, when you invite your bot, the "Server Members Intent" box in the "bot" section is checked. Another way, which might be based on a different event is here:
await client.guilds.fetch(); //cache guilds
const guild = client.guilds.cache.get('someGuild');
await guild.members.fetch(); //should cache users automatically
const member = guild.members.cache.get('someMember');
member.roles.add('someRole');
//MAKE SURE ITS ASYNC
If these don’t work, please comment, and tell me what error you get.

How do I use readline for Discord Bots?

While trying to make my Discord Bot I ran into yet another problem. I'm trying to have a way to have the owner have the bot say something in the announcement section for me so it doesn't show up as my name.
I've tried the readline interface (though I don't know if I did it correctly) and I've tried to do different ways of making a variable (const, var).
if(message.member.roles.find(r => r.name === "Owner")){
return message.reply("What would you like to say?")
const dm = message.content;
return message.reply("$dm")
I want the bot to respond with whatever I say. So, If I put in The Server Is Going Down Soon! then the bot should say that back to me (in this case).
When you call return you're ending the execution of the function that you're writing.
In this case,
if(message.member.roles.find(r => r.name === "Owner")){
return message.reply("What would you like to say?") // the current function stops
const dm = message.content; // this line never executes
return message.reply("$dm")
You will have to wait for the response from the user who I presume is responding to a command of some sort
if (message.member.roles.find(r => r.name === "Owner")) {
await message.reply("What would you like to say?"); // Send the request
// Wait for the person who sent the original message to send another message
let userMessages = await message.channel
.awaitMessages(m => m.id === message.member.id, { max: 1 });
let userMessage = userMessages.first()
// Reply with the message they sent
return message.member.reply(userMessage.content);

Strings/Arguments for a new person

I need help with a command, for example, if someone writes
" !report #user Spamming " How can I do so my discord account gets a message from the bot about =
Who reports who and for what reason
I've tried watching videos and posts but I can't get my head around it
client.on('message', async function(message) {
if (message.content.startsWith(prefix + "report")) {
const user = await client.fetchUser(args[1].match(/^<#!?(\d+)>$/)[1]);
if (!user) return message.channel.send('Oops! Please mention a valid user.');
const reason = args.slice(2).join(' ');
const me = await client.fetchUser('123456890'); //My id
me.send(`${message.author} reported ${user} for: \`${reason}\``)
.catch(err => console.error(err));
}
}
)
I want for example
In channel = !report #patrick#4245 He is spamming
Then The bot sends a message to me
#fadssa#2556 Reported #patrick#4245 Reason = He is spamming
Before just copying this code, let's actually think this through...
So, let's start by first getting everything we need for the message. First, we should retrieve a User from the argument provided. We do this by comparing the string to that of a mention and picking out the ID. If one doesn't exist, we return an error telling the user to mention someone.
Now, assuming you already have your arguments declared (if not, see this guide to help), we can simply put together the arguments used for the reason. To do so, we should use Array.slice() and then join those words with Array.join().
Then, since we want the bot to send you a DM, we'll have to find you in the Discord world. For this, we can use client.fetchUser().
Now, we can just send you the DM and you'll be alerted of all reports.
/*
* Should be placed within your command's code, after checking required arguments exist
* Assuming 'client' is the Discord Client and 'args' is the array of arguments
* Must be within an async function to use 'await'
*/
const user = await client.fetchUser(args[1].match(/^<#!?(\d+)>$/)[1]); // see below
if (!user) return message.channel.send('Oops! Please mention a valid user.');
const reason = args.slice(2).join(' ');
const me = await client.fetchUser('189855563893571595'); // replace with your ID
me.send(`${message.author} reported ${user} for: \`${reason}\``))
.catch(err => console.error(err));
Although it may look confusing, using regex is a much better option than message.mentions. There's plenty of whack examples where seemingly perfect code will not return the expected user, so this is why I would definitely choose retrieving the ID from a mention myself.

Check for the message before the last

I am trying to make my bot delete a specific number of messages, I think an if would be best for the case, but I don't know how to do this...
This is how it's supposed to work: There's a message from my bot in the channel, it's always the last one in the chat. My bot will check if the message is actually there, if it is, it will delete the message, along with the command, and then send a new message. If the message is not there, it will just delete the command and send the new message.
Here's my code for reference:
if(/* message is there */) const fetched = await message.channel.fetchMessages({limit: 2});
else const fetched = await message.channel.fetchMessages({limit: 1});
// Deletes stuff
message.channel.bulkDelete(fetched)
.catch(error => message.reply(`There was an error: ${error}`));
message.channel.send("```Open```");
How can I check if that previous message is there?
I would check if the author of the last message is your bot:
let lastTwo = await message.channel.fetchMessages({limit: 2}), // Get the last 2 messages
last = lastTwo.last(); // The last in the collection will be the last message
if (last.author.id == client.user.id) await message.channel.bulkDelete(lastTwo);
else await last.delete();
message.channel.send("```Open```");

Categories