Discord.js Forward DM message to specific channel - discord

So, I need a way to forward a message sent in the bot's dm to a specific channel in my server.
this is the code that I got so far:
execute(message, args) {
if(message.channel.type == "dm"){
let cf = args.join(' ')
const cfAdm = message.guild.channels.cache.get('767082831205367809')
let embed = new discord.MessageEmbed()
.setTitle('**CONFISSÃO**')
.setDescription(cf)
.setColor('#000000')
const filter = (reaction, user) => ['πŸ‘', 'πŸ‘Ž'].includes(reaction.emoji.name);
const reactOptions = {maxEmojis: 1};
cfAdm.send(embed)
.then(function (message) {
message.react('πŸ‘')
.then(() => message.react('πŸ‘Ž'))
/**** start collecting reacts ****/
.then(() => message.awaitReactions(filter, reactOptions))
/**** collection finished! ****/
.then(collected => {
if (collected.first().emoji.name === 'πŸ‘') {
const cfGnr = message.guild.channels.cache.get('766763882097672263')
cfGnr.send(embed)
}
})
});
}
else {
message.delete()
message.channel.send('Send me this in the dm so you can stay anon')
.then (message =>{
message.delete({timeout: 5000})
})
}
}
But for some reason that I can't seem to understand, it gives me this error:
TypeError: Cannot read property 'channels' of null
If anyone can help me, that would be greatly apreciated.
Thanks in advance and sorry for the bad english

The error here is that you are trying to call const cfAdm = message.guild.channels.cache.get('ID') on a message object from a Direct Message channel ( if(message.channel.type == "dm"){)
DMs don't have guilds, therefore message.guild is null and message.guild.channels does not exist.
You will need to first access the channel some other way. Luckily, Discord.js has a way to access all channels the bot can work with* (you don't need to muck around with guilds because all channels have unique IDs):
client.channels.fetch(ID) or client.channels.cache.get(ID)
(I have not tested this but it seems fairly straight forward)
*See the link for caveats that apply to bots in a large amount of servers.

Related

Discord.JS | AwaitReaction in DM

I don't want bots to join my server and advertise in chat or dm's of users, so I thought I'll let new users react to a message, and after that my bot will send them a question in dm's, if they answer correctly he should give them the verified role. The bot can send the message, but after that an error appears.
(node:12356) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'type' of undefined
I dont know how to solve this, because in the Docs channel.type exists.
Here is the code
client.on('messageReactionAdd', async (reaction, user) =>{
const filter = m => true
if (reaction.message.partials) await reaction.message.fetch();
if (reaction.partials) await reaction.fetch();
if (user.bot) return;
if (!reaction.message.guild) return;
if (reaction.message.id === '814035246399488001'){
if (reaction.emoji.name === 'βœ…'){
user.send("What is the subtrahend of 156 - 123?")
.catch(()=>{console.log('couldnt send a DM')})
if ( channel.type === 'dm' )
user.dmChannel.awaitMessages(filter, {
max:1,
time:30000,
error:["time"]
})
.then(collected => {
if (collected.first().content === "33"){
reaction.message.guild.members.cache.get(user.id).roles.add('779523805492019254')
if(err => {
console.log(err)
});
}else{
user.send("this is not the correct answer, you will not get verified.")
return;
}
})
}
}
});
I have asked around in some discord servers and found the solution:
if (reaction.emoji.name === 'βœ…'){
let msg = await user.send("What is the subtrahend of 156 - 123?")
.catch(()=>{console.log('couldnt send a DM')})
if (msg.channel.type == `dm`)
What i think happens is, the bot now knows that msg.channel.type is the channel where he sent the message before, and yeah, i am so happy now that it works :3 and thank you too NullDev your comment lead to the solution too <3

Always getting back an, "Internal Server Error," when trying to run ban command on my Discord bot

I have tried many different ways of formatting the code, however, whenever I add code so that I must provide a reasoning to ban someone, I am always given an Internal Server Error. Here is my code.
module.exports.run = async (client, message, args) => {
const member = message.mentions.members.first();
const reason = args.slice(1).join(" ")
if (!message.member.hasPermission("BAN_MEMBERS")) {
return message.reply("you lack sufficiant permissions to execute this command.");
} else if (member.hasPermission("ADMINISTRATOR")) {
message.reply("you cannot ban this member.")
}
member.ban(reason).then((member) => {
message.channel.send(`${member} has been banned.`);
});
I use a command handler, and all my other commands work fine.
first step: Define the user
let user = message.mentions.members.first() || message.guild.members.cache.get(args.join(' '));
Second step: Create embed message or normal message
const userbanned = new Discord.MessageEmbed()
.setColor('#FF0000')
.setAuthor('User Banned')
.setDescription(`**${user.user.username}#${user.user.discriminator}** is now banned from this server`)
.setFooter(`bot_name`);
Third step: Send message
user.send(`You were banned from **${message.guild.name}** by ${message.author.username}#${message.author.discriminator}`)
return user
.ban()
.then(() => message.channel.send(userbanned))
.catch(error => message.reply("ERROR"));
Try changing
member.ban().then((member) =>//
to
member.ban({reason : args.slice(1).join(' ')}).then((member) =>//

Discord.js - How do you move a user that reacts to an embed?

I am new to Discord js and I am trying to make my bot move all users that react to an embed into a certain voice channel. Currently, it takes whoever wrote the message and moves them to the specified voice channel.I tried many combinations of user.id, guild.member, etc. What would I put before the .setVoiceChannel? I am confused as to what message.member is other than the person that wrote the message. Thank you!
collector.on('collect', (reaction, user) => {
if (reaction.emoji.name == reactionControls.VOID) {
const channel = message.guild.channels.find('name', 'Void 1');
message.member.setVoiceChannel(channel);
}
});
message.member does refer to the user who execute the command, if you want the member who reacted you will have to convert user using <GuildMember>.fetchMember, the only issue now is that the collect event doesn't give the parameter of user in v11.5.1 so you will need to just use collector.users.last() to get the last reactor
collector.on('collect', async (reaction) => {
if (reaction.emoji.name == reactionControls.VOID) {
const channel = message.guild.channels.find('name', 'Void 1');
const user = collector.users.last();
const member = await message.guild.fetchMember(user);
member.setVoiceChannel(channel);
}
});

How to add roles when user reacts to specific message

I need it so that a bot will send a message and if anyone on the server reacts to that message with a reaction it will give them a role.
I Have already tried multiple times, different code samples which allow reactions anywhere in the guild but i want it specific to one channel.
client.on("messageReactionAdd", (reaction, user) => {
if (user.bot) return;
const member = reaction.message.member
switch (reaction.name) {
case "😎":
member.addRole("597011179545690121").then((res) => {
reaction.message.channel.send(`You've been given the \`${res.name}\` role!`)
}).catch(console.error);
break;
case "πŸ•΅":
member.addRole("597011179545690121").then((res) => {
reaction.message.channel.send(`You've been given the \`${res.name}\` role!`)
}).catch(console.error);
};
})
client.on("messageReactionRemove", (reaction, user) => {
if (user.bot) return;
const member = reaction.message.member
switch (reaction.name) {
case "emoji_name_1":
member.removeRole("roleID").then((res) =>
reaction.message.channel.send(`You've been removed from the \`${res.name}\` role!`)
}).catch(console.error);
break;
case "emoji_name_2":
member.removeRole("someOtherRole").then((res) => {
reaction.message.channel.send(`You've been removed from the \`${res.name}\` role!`)
}).catch(console.error);
};
})
I Want the outcome to be that the person reacts with say a smiley face and they get a certain role but they have to react to a certain message sent by the bot in its own dedicated channel same as pre-made bots such as Reaction Roles bot.
First we have to fetch our Message.
let channel_id = "ChanelID of message";
let message_id = "ID of message";
client.on("ready", (reaction, user) => {
client.channels.get(channel_id).fetchMessage(message_id).then(m => {
console.log("Cached reaction message.");
}).catch(e => {
console.error("Error loading message.");
console.error(e);
});
Then we'll check if someone reacted to our message and give them the appropriate Role
client.on("messageReactionAdd", (reaction, user) => {
if(reaction.emoji.id == "EMOJI ID HERE" && reaction.message.id === message_id)
{
guild.fetchMember(user) // fetch the user that reacted
.then((member) =>
{
let role = (member.guild.roles.find(role => role.name === "YOUR ROLE NAME HERE"));
member.addRole(role)
.then(() =>
{
console.log(`Added the role to ${member.displayName}`);
}
);
});
}
}
I advise against using this code for multiple Roles at once as that would be rather inefficient.
const member = reaction.message.member
Problem: This is defining member as the GuildMember that sent the message, not the one that added the reaction.
Solution: Use the Guild.member() method, for example...
const member = reaction.message.guild.member(user);
switch (reaction.name) {...}
Problem: name is a not a valid property of a MessageReaction.
Solution: What you're looking for is ReactionEmoji.name, accessed via reaction.emoji.name.
...[the users] have to react to a certain message...
Problem: Your current code isn't checking anything about the message that's been reacted to. Therefore, it's triggered for any reaction.
Solution: Check the message ID to make sure it's the exact one you want. If you'd like to allow reactions on any message within a certain channel, check the message's channel ID.
Consider these examples:
if (reaction.message.id !== "insert message ID here") return;
if (reaction.message.channel.id !== "insert channel ID here") return;
Problem: The messageReactionAdd event is not emitted for reactions on uncached messages.
Solution: Use the raw event to fetch the required information and emit the event yourself, as shown here. Alternatively, use Caltrop's solution and fetch the message when the client is ready via TextChannel.fetchMessage().

Get Discord Bot to Check If It's Reacted To It's Own Post

I'm writing a discord bot using discord.js, and I've recently added a //translate command that utilizes the Google Translate API to translate between all the languages supported by Google Translate. I want to add the ability to quickly re-translate the translation back into English using reactions, and I want the bot to check if 1 person has reacted to the post with the provided reaction, and if they have, re-translate the translation back to English.
I'm really close, but I've run into the problem that I can't get the bot to check if it itself sent the reaction, so it auto-retranslates back to English because it's detecting it's own reaction. I want for it to only re-translate when A PERSON reacts, and only ONCE.
I'm not super familiar with this area of discord.js yet, so I can't really figure out how to do it.
Here is the code:
if (msg.content.startsWith(`${prefix}translate`) || msg.content.startsWith(`${prefix}t`)) {
const text = args.slice(1).join(` `);
if (!text) return msg.channel.send(`Nothing to translate provided! Languages codes are at https://cloud.google.com/translate/docs/languages !\n Command syntax: \`${prefix}translate\` or \`${prefix}t\` [text] [language code]`);
const text1 = text.substring(0, text.length - 2)
const target = text.substring(text.length - 2, text.length) || languages
translate
.translate(text1, target)
.then(results => {
const translation = results[0];
msg.channel.send(`Translation: ${translation}`).then(sentText => {
sentText.react(`πŸ”€`);
const filter = (reaction, user) => {
return ['πŸ”€'].includes(reaction.emoji.name);
};
sentText.awaitReactions(filter, { max: 2, time: 5000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === 'πŸ”€' && sentText.react.me === false) {
const target = `en`
translate
.translate(text1, target)
.then(results => {
const translation = results[0];
msg.channel.send(`Translation: ${translation}`);
})
.catch(err => {
console.log(err);
})
}
})
})
})
//code for command continues below this line, but it is irrelevant to what I'm trying to achieve
Expected result: Bot re-translates back to English if a user reacts with the provided reaction, and only once.
Actual result: Bot does nothing, or, if I remove the && sentText.react.me === false, the bot re-translates back to English because it's detecting its own reaction.
Any help would be appreciated!
In your filter, you can check to make sure the user isn't the client, like so...
const filter = (reaction, user) => reaction.emoji.name === 'πŸ”€' && user.id !== client.user.id;
That way, only reactions that are not added by the client are collected.
You'll have to change your max option in the collector to 1, since the client's own reaction won't be collected. You can also remove the if statement comparing reaction.emoji.name.

Resources