DiscordJS (Node) Sending PM to user and await reply - javascript

I'm trying to get my bot to send a user a private message when a user types a command, and then wait for a reply to the private message.
Expected flow:
Jim types: !auth
bot sends Jim a private message
Jim replies to the message with blablabla
Bot sees the blablabla reply and outputs to terminal => console.log( replyResponse );
I have tried numerous examples I have found from here and in the docs but none of them works.
message.author.send('test').then(function () {
message.channel
.awaitMessages((response) => message.content, {
max: 1,
time: 300000000,
errors: ['time'],
})
.then((collected) => {
message.author.send(`you replied: ${collected.first().content}`);
})
.catch(function () {
return;
});
});

message.author.send('test') returns the sent message so you should use that returned message to set up a message collector. At the moment, you're using message.channel.awaitMessages and that waits for messages in the channel where the user sent the !auth message, not the one where the bot sent a response.
Check out the working code below. It uses async-await, so make sure that the parent function is an async function. I used createMessageCollector instead of awaitMessages as I think it's more readable.
try {
// wait for the message to be sent
let sent = await message.author.send('test');
// set up a collector in the DM channel
let collector = sent.channel.createMessageCollector({
max: 1,
time: 30 * 1000,
});
// fires when a message is collected
collector.on('collect', (collected) => {
collected.reply(`✅ You replied: _"${collected.content}"_`);
});
// fires when we stopped collecting messages
collector.on('end', (collected, reason) => {
sent.reply(`I'm no longer collecting messages. Reason: ${reason}`);
});
} catch {
// send a message when the user doesn't accept DMs
message.reply(`❌ It seems I can't send you a private message...`);
}
Make sure, you don't forget to enable the DIRECT_MESSAGES intents. For example:
const { Client, Intents } = require('discord.js');
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.DIRECT_MESSAGES,
],
});

Related

nodemon: clean exit - waiting for changes before restart

I've been working on this code for a discord bot that tracks a the voice channels of a server until a specific person joins which then the bot joins and then plays an audio. However whenever I start up my file, it keeps on saying
[nodemon] starting `node index.js`
[nodemon] clean exit - waiting for changes before restart
I have no clue why, I've looked online and I haven't seen any other people having the same issue as me, and if they did the answer didn't help.
Here is my code.
const { Client, GatewayIntentBits } = require('discord.js');
const { Lavalink } = require('discord.js-lavalink');
class MyBot {
// The Discord.js client object that represents our bot
client;
// The ID of the specific person we want to track
userIdToTrack;
// The audio file to play when the specific person joins
audioFile;
constructor(client, userIdToTrack, audioFile) {
// Save the client object and user ID and audio file for later use
this.client = "[bot token]";
this.userIdToTrack = '[discord id]';
this.audioFile = '[file name]';
}
onGuildVoiceJoin(event) {
// Get the member who just joined the voice channel
const member = event.member;
// If the member is the specific person we want to track...
if (member.id === this.userIdToTrack) {
// Get the voice channel that the member joined
const voiceChannel = event.channel;
// Join the voice channel with the bot
voiceChannel.guild.voice.channel.join();
// Play the audio file using Lavalink
lavalink.play(voiceChannel, {
track: '[file name]',
});
const client = new Client({
token: 'bot token]',
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildPresences,
],
});
// Create a new instance of the Lavalink class and connect to the Lavalink nodes
const lavalink = new Lavalink({
client: client,
nodes: [
{ host: 'ratio-w', port: 2334, password: 'youshallnotpass' },
],
});
lavalink.connect();
client.on('ready', () => {
console.log('The bot is ready');
// Create a new instance of the bot, passing in the client object, user ID, and audio file
const bot = new MyBot("bot token", "user id", "file name");
// Listen for voice state update events, which are triggered when a user joins or leaves a voice channel
client.on('voiceStateUpdate', (oldState, newState) => {
// Check if the user we want to track has just joined a voice channel
if (newState.member.id === userIdToTrack && newState.channel) {
// Get the voice channel the user joined
const voiceChannel = newState.channel;
// Join the voice channel with the bot
voiceChannel.join().then(connection => {
// Play the audio file using Lavalink
lavalink.play(voiceChannel, {
track: audioFile,
});
});
}
});
client.on('messageCreate', message => {
if (message.content === 'ping') {
message.reply('hey <#user id>, you STINK!!!!111!');
}
});
client.on('messageCreate', message => {
if (message.content === 'shut up [redacted]') {
message.reply('yeah <#user id> shut up smelly');
}
});
client.on('messageCreate', message => {
if (message.content === 'stop being a nerd [redacted]') {
message.reply('<#user id> be like :nerd:');
}
});
});
process.on('unhandledRejection', (reason, promise) => {
console.log('Unhandled Rejection at:', reason.stack || reason)
// Recommended: send the information to sentry.io
// or whatever crash reporting service you use
})
client.login('[bot id]');}}}
I tried fixing any possible syntax errors, I've tried looking online but no help was found, I've properly started lavalink (I think), I've edited some of the code so that all possible parts are fixed. I've downloaded all possible directories like updating discord.js, node.js, lavalink.js, and more I think.

Bot isn't replying to any message

I'm trying to make a simple Discord bot, but I haven't been able to get it to respond to any of my messages.
const Discord = require("discord.js");
const { GatewayIntentBits } = require('discord.js');
const client = new Discord.Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`)
})
client.on("messageCreate", msg => {
if(msg.content === "ping") {
msg.reply("pong");
}
})
const token = process.env['TOKEN']
client.login(token)
The bot is logging into discord, I'm not getting any errors in the console, and I've toggled on all the privileged gateway intents.
Edit
So, my previous answer was wrong, but is most definitely a better way to send messages.
There's not anything else that I can see is wrong with the code -- so I guess I'll try to debunk?
const { Client, GatewayIntentBits } = require("discord.js");
const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent ]});
client.on("ready", async() => {
console.log(`${client.user.tag} logged in.`);
});
client.on("messageCreate", async(message) => {
if(message.content.toLowerCase() === "ping") {
message.reply({ content: "pong!" }); // or message.reply("pong!");
}
});
client.login(process.env.TOKEN);
This should be a runnable instance of your code. What you should do is see if you're even getting the messageCreate event at all, by running it like this:
client.on("messageCreate", (message) => {
console.log(`Received message!`);
});
If you do get something, then it is unable to correctly parse the message content. Are you ensuring it's the same capitalization wise? Is it spelt correctly?
If you don't get something, it's an issue with your Intents, or the way your event is structured.
Try adding parenthesis around your msg, though that shouldn't affect anything. Just a thought.
Incorrect Answer
In discord.js#13.x.x, the way to send messages has changed.
Formerly, you could do the following:
message.reply("Hello world!");
But now, to make formatting what provided property is what, it goes as follows:
message.reply({
content: "Hello world!",
});
You can also add things such as Embeds by using embeds: [], or Components by: components: [] (which requires Action Rows, not base Components).
Hope this helps.

DiscordJS V13 doesnt react to dms

I have this very basic code for a very basic discord bot
since the new discord.js version 13 you need to declare intents.
I tried doing that using the bitmap 32767 (basically declaring all intents), however the bot doesnt trigger the "messageCreate" event when a message is send
in the dms it only works in servers.
All privileged gateway intents on the developer site have been set to true.
What am I missing?
const Discord = require("discord.js");
const allIntents = new Discord.Intents(32767);
const client = new Discord.Client({ intents: allIntents });
require("dotenv").config();
const botName = "Miku";
client.once("ready", () => {
//gets executed once at the start of the bot
console.log(botName + " is online!");
});
client.on("messageCreate", (message) => {
console.log("got a message");
});
(async() => {
//bot connects with Discord api
client.login(process.env.TOKEN);
})();
You cannot listen for events in the Direct Messages unless they are direct responses/replies/reactions to the initial message.
For example, you can send a message to new members and wait for a response:
client.on('guildMemberAdd', member =>{
member.send("Welcome to the server!");
message.awaitReactions(filter, { max: 1, time: 60000, errors: ['time'] })
.then((collected) => {
//Now, write your code here that handles the reactions.
});
but there is no way to listen for events within the Direct Messages. As in, client.on... will never fire because of a DM event.

TypeError: Cannot read property 'send' of undefined when trying to direct message a user

I'm trying to make a system that allows my bot to direct message people, but an error always seems to come up when trying to direct message a user that has not sent a dm to the bot since it was last restarted.
This is the error that I keep on getting:
TypeError: Cannot read property 'send' of undefined
This is the important code:
message.channel.send({ embed: dmattempt }).then(sentMessage => {
try {
// Tries to send a message to the user
const themsguser = client.users.cache.get(dmId);
themsguser.send(`${sentence}`);
Here is the code for the entire command:
client.on('message', async message => {
function directMsgUser(dmUser, dmCommand, dmId) {
if (message.content.startsWith(`${prefix}${dmCommand}`)) {
let sentence = message.content.split(' ');
sentence.shift();
sentence = sentence.join(' ');
const dmattempt = {
color: [0, 0, 255],
title: `trying to direct message ${dmUser}`,
description: 'please wait',
footer: {
text: `message sending from ${message.author.tag}`,
icon_url: `${message.author.avatarURL()}`,
},
};
const msgsent = {
color: [0, 255, 0],
title: `message sent to ${dmUser}`,
description: `message content: ${sentence}`,
footer: {
text: `message sent by ${message.author.tag}`,
icon_url: `${message.author.avatarURL()}`,
},
};
// Sends a message confirming that the message is trying to be sent
console.log(`Trying to direct message ${dmUser}`);
message.channel.send({ embed: dmattempt }).then(sentMessage => {
try {
// Tries to send a message to the user
const themsguser = client.users.cache.get(dmId);
themsguser.send(`${sentence}`);
// Edits the message to verify it was sent
sentMessage.edit({ embed: msgsent });
console.log('Message sent!');
}
catch (error) {
// Edits the message to verify something went wrong
const errorembed = {
color: [255, 0, 0],
title: 'error!',
description: `There was an error messaging ${dmUser}`,
footer: {
text: `message sent by ${message.author.tag}`,
icon_url: `${message.author.avatarURL()}`,
},
};
sentMessage.edit({ embed: errorembed });
console.error(error);
console.error('There was an error sending a direct message.');
}
});
}
}
if (message.content.startsWith(`${prefix}dm`)) {
directMsgUser(theUser, theCommand, idforuser);
}
});
Note that this command works if the user the message is getting sent to has sent a dm to the bot since it has been restarted.
Thanks for your help in advance.
It is possible that the problem is that since you are attempting to get the user from the cache, the user may not be in the cache yet. And this would make sense with why it works if the user has previously sent the bot a DM already, because doing so would add them to the cache. But if they haven't DM'd the bot before, then they might not be in the user cache yet.
You could use .fetch(id, cache) instead of .cache.get(id) in order to ensure that you fetch the user, even if they are not in the cache yet:
client.users.fetch(dmID, true).then(themsguser => {
themsguser.send(`${sentence}`);
});
This method will make the bot first check if the user with ID dmID is in the cache. If it is, it will use the value in the cache. If it isn't, it will fetch the user by directly requesting the Discord API. And because we set the second argument of our .fetch() to true, the method will also add our user to the cache after fetching it (if it wasn't already in the cache), therefore preventing the need to repeatedly request data from the API.
Relevant resources:
https://discord.js.org/#/docs/main/stable/class/UserManager?scrollTo=fetch

Sending a DM to people who react to message - Discord JS

I'm trying to send a message to the first 5 people who react to the message, however it only sends a DM to the first person who reacted and does not allow anyone else to react or receive a DM.
How would I do this?
case 'await':
message.channel.sendMessage('React for dm').then(sentMessage => {
sentMessage.react('1️⃣').then(() => sentMessage.react('2️⃣'));
const filter = (reaction, user) => {
return ['1️⃣', '2️⃣'].includes(reaction.emoji.name);
};
sentMessage.awaitReactions(filter, {
max: 1,
time: 60000,
errors: ['time']
})
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '1️⃣') {
message.author.sendMessage('I told you I would!')
}
})
})
You have max: 1 That tells the collector to quit after it has successfully collected 1 reaction. You should set that to 5.
After that you need to loop through the collected to send a DM to all of them rather than using first().

Categories