I am trying to close a ticket by reacting to a button. But reaction must be given by "support" role. I couldnt do it. reaction.message.member.roles.has is not helping me at this point. Here is my code ;
client.on("messageReactionAdd", (reaction, user) => {
if(reaction.message.member.roles.has('ROLE')) {
let id = user.id.toString().substr(0, 4) + user.discriminator;
let chan = `ticket-${id}`;
const supchan = reaction.message.guild.channels.find(
(channel) => channel.name === chan
);
const chan_id = supchan ? supchan.id : null;
if (
reaction.emoji.name === "🔒" &&
!user.bot &&
user.id != "ID"
) {
reaction.removeAll();
const channel = client.channels.find("name", chan);
const delMsg = new Discord.RichEmbed()
.setColor("#E74C3C")
.setDescription(`:boom: Ticket will be deleted in 5 seconds.`);
channel.send(delMsg).then(() => {
var counter = 0;
const intervalObj = setInterval(() => {
counter++;
if (counter == 5) {
const message = reaction.message;
message.delete();
Thanks for helps !
All of this wrapped inside the messageReactionAdd event
// Replace "message_id" with the proper message id
// Checks if it's the correct message
if (reaction.message.id == "message_id") {
// Check if author of ticket message is from the same user who reacted
if (reaction.message.author == user) {
// Check correct emoji
if (reaction.emoji.name == "🔒") {
// Code to close ticket
}
}
}
EDIT:
Again, this would be wrapped inside the messageReactionAdd event:
// Try to get the ticket message
// If there's none then the user was never opened a ticket so we simply return the code
const ticketMessage = client.tickets.get(user);
if (!ticketMessage) return;
// Checks if it's the correct message
if (reaction.message.id == ticketMessage.id) {
// Check correct emoji
if (reaction.emoji.name == "🔒") {
// Code to close ticket
}
}
I removed the code that check for the reaction message author because getting ticketMessage already handles that. Do note that this means you can make sure a user can only open one ticket.
Related
EDIT: ColinD solved my problem but now the message doesn't delete and I have no idea why the message wont delete because its worked for me before with bots
Code:
const discord = require('discord.js')
const newEmbed = require('embedcord')
const randomHex = require('random-hex')
module.exports = (client, message, options) => {
let links = require('./links.json')
let foundLink = false
let banReason = (options && options.banReason) || 'Sent a phishing link.'
let logs = (options && options.logs)
let member = message.mentions.members.first()
for(var i in links) {
if(message.content.toLowerCase().includes(links[i])) foundLink = true
}
if(foundLink) {
if(message.author.hasPermission('ADMINISTRATOR'))
return
message.delete()
member.ban({reason: banReason})
const embed = newEmbed(
'**Member Banned**',
`${randomHex.generate()}`,
`Member was banend for ${options.banReason}`
)
logs.send(embed)
}
}
Your return position might be preventing anything below if from running try changing this
if (foundLink) {
if (message.author.hasPermission('ADMINISTRATOR')) return;
const embed = newEmbed(
'**Member Banned**',
`${randomHex.generate()}`,
`Member was banend for ${options.banReason}`
);
message.delete();
member.ban({
reason: banReason
});
logs.send(embed);
}
Or this if you want if/else
if (foundLink) {
if (message.author.hasPermission('ADMINISTRATOR')) {
return;
} else {
const embed = newEmbed(
'**Member Banned**',
`${randomHex.generate()}`,
`Member was banend for ${options.banReason}`
);
message.delete();
member.ban({
reason: banReason
});
logs.send(embed);
}
}
EDIT: ColinD solved my problem but now the message doesn't delete and I have no idea why the message wont delete because its worked for me before with bots
foundLink variable is unnecessary, you can move your code inside the loop.
Use message.member.hasPermission() instead of message.author.hasPermission().
Example code for v12.5.3(Message Event):
client.on('message', (message) => {
if (message.author.bot) return; // Ignore bot messages
const { member, channel, guild } = message; // Get the message author, channel, and guild
if (!member || !channel || !guild) return; // Ignore messages without a member, channel or guild
const { links } = require('./links.json'); // Get links from json file
for (let i = 0; i < links.length; i++) { // Check if the message contains a link in the links.json file
if (message.content.toLowerCase().includes(links[i])) { // If the message contains a link
if (member.hasPermission('ADMINISTRATOR')) return; // If the member has the administrator permission, don't ban them
const banReason = 'Sent a phishing link'; // Reason for the ban
message.delete(); // Delete the message
guild.member(member).ban({ reason: banReason }); // Ban the member
channel.send(`${member.displayName} has been banned for sending a phishing link.`) // Send a message to the channel
break;
}
}
})
Problem: I have been trying to add a "Activity" field to my info command, and its not working.
Expected result: Responds with the other stuff, along with the Activity field, showing what the user is doing.
Actual response: Shows everything else correctly, except the Activity field, which says undefined/null.
Code:
if (command == "info") {
const embed = new Discord.MessageEmbed()
let member = message.mentions.members.first() || message.guild.members.cache.get(args[1]) || message.guild.member(message.author)
const Roles = new Array()
message.guild.roles.cache.forEach(role => {
if (member.roles.cache.find(r => r.id == role.id)) {
Roles.push(role)
}
})
console.log(member.presence)
embed.setAuthor(user.tag, member.user.avatarURL())
embed.setTitle(`👋 Welcome to ${user.username}'s Profile!`)
embed.addField('#️⃣ Tag:', member.user.tag)
embed.addField('📡 Joined Guild at:', member.user.joinedAt)
embed.addField('💬 Joined Discord at:', member.user.cretedAt
)
if (!member.presence.activities) {
embed.addField('⚽️ Activity:', 'Not playing anything')
} else {
embed.addField('⚽️ Activity:', `${member.presence.activities.type} ${member.presence.activities.name}\n${member.presence.activities.details}\n${member.presence.activities.state}`)
}
embed.addField('📱 Platform:', member.presence.clientStatus)
embed.addField('🤖 Bot:', user.bot)
embed.addField('📜 Roles:', Roles.join(' | '))
embed.setFooter('Bot made with discord.js')
message.channel.send(embed)
}
Presence.activities is an array of Activity.
// Add check for empty activities array
if (!member.presence.activities || member.presence.activities.length == 0) {
embed.addField('⚽️ Activity:', 'Not playing anything')
} else {
const activity = member.presence.activities[0];
embed.addField('⚽️ Activity:', `${activity.type} ${activity.name}\n${activity.details}\n${activity.state}`);
}
Most of the time you will only need the first item of the array. Because you rarely see users with multiple activities.
I want the user to answer a "yes or no" question using reactions. Here is my code below.
var emojiArray = ['🔥', '👍', '👎', '✅', '❌'];
client.on('message', (negotiate) => {
const listen = negotiate.content;
const userID = negotiate.author.id;
var prefix = '!';
var negotiating = false;
let mention = negotiate.mentions.user.first();
if(listen.toUpperCase().startsWith(prefix + 'negotiate with '.toUpperCase()) && (mention)) {
negotiate.channel.send(`<#${mention.id}>, do you want to negotiate with ` + `<#${userID}>`)
.then(r => r.react(emojiArray[3], emojiArray[4]));
negotiating = true;
}
if(negotiating == true && listen === 'y') {
negotiate.channel.send('Please type in the amount and then the item you are negotiating.');
} else return;
})
As you can see, the code above allows the user to tag someone and negotiate with them (the negotiating part doesn't matter). When the user tags someone else, it asks them if they want to negotiate with the user that tagged them. If the user says yes, they negotiate.
I want to do this in a cleaner way using reactions in discord. Is there any way to just add a yes or no reaction emoji and the user will have to click yes or no in order to confirm?
First of all, you kinda messed up while getting the user object of the mentioned user, so just so you know it's negotiate.mentions.users.first()!
While wanting to request user input through reactions, we'd usually want to use either one of the following:
awaitReactions()
createReactionCollector
Since I personally prefer awaitReactions(), here's a quick explanation on how to use it:
awaitReactions is a message object extension and creates a reaction collector over the message that we pick. In addition, this feature also comes with the option of adding a filter to it. Here's the filter I usually like to use:
const filter = (reaction, user) => {
return emojiArray.includes(reaction.emoji.name) && user.id === mention.id;
// The first thing we wanna do is make sure the reaction is one of our desired emojis!
// The second thing we wanna do is make sure the user who reacted is the mentioned user.
};
From there on, we could very simply implement our filter in our awaitReactions() function as so:
message.awaitReactions(filter, {
max: 1, // Accepts only one reaction
time: 30000, // Will not work after 30 seconds
errors: ['time'] // Will display an error if using .catch()
})
.then(collected => { // the reaction object the user reacted with
const reaction = collected.first();
// Your code here! You can now use the 'reaction' variable in order to check certain if statements such as:
if (reaction.emoji.name === '🔥') console.log(`${user.username} reacted with Fire emoji!`)
Finally, your code should look like this:
const filter = (reaction, user) => {
return emojiArray.includes(reaction.emoji.name) && user.id === mention.id;
};
message.awaitReactions(filter, {
max: 1,
time: 30000,
errors: ['time']
})
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '🔥') console.log(`${user.username} reacted with Fire emoji!`)
you should use a ReactionCollector:
var emojiArray = ['🔥', '👍', '👎', '✅', '❌'];
const yesEmoji = '✅';
const noEmoji = '❌';
client.on('message', (negotiate) => {
const listen = negotiate.content;
const userID = negotiate.author.id;
var prefix = '!';
var negotiating = false;
let mention = negotiate.mentions.user.first();
if(listen.toUpperCase().startsWith(prefix + 'negotiate with '.toUpperCase()) && (mention)) {
negotiate.channel.send(`<#${mention.id}>, do you want to negotiate with ` + `<#${userID}>`)
.then(async (m) => {
await m.react(yesEmoji);
await m.react(noEmoji);
// we want to get an answer from the mentioned user
const filter = (reaction, user) => user.id === mention.id;
const collector = negotiate.createReactionCollector(filter);
collector.on('collect', (reaction) => {
if (reaction.emoji.name === yesEmoji) {
negotiate.channel.send('The mentioned user is okay to negotiate with you!');
// add your negotiate code here
} else {
negotiate.channel.send('The mentioned user is not okay to negotiate with you...');
}
});
});
negotiating = true;
}
})
This allows you to listen for new reactions added to a message. Here is the documentation: https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=createReactionCollector
I've been trying to get the last message of a channel writing a command in another channel.
I want to do something like this:
Channel 1 : (I write) "Get last message of channel 2
channel 2: Last message is ("Hello");
Channel 1: i receive the last message of channel 2 saying, the last message of channel 2 is . "Hello".
My code is this, but isn't working.
if (message.channel.id === '613573853565681671') {
message.channel.fetchMessages().then(collected => {
const filtered = collected.filter(message => message.author.bot);
const lastMessages = filtered.first(1); //Get the last message of this channel.
const TextMessages = `${lastMessages[0].content}`;
console.log(TextMessages + " is the last message of aviso jobs")
if (TextMessages === "look") { //If the last message of this channel is look then go to the other channel
if (message.channel.id === '613553889433747477') {
message.channel.fetchMessages().then(collected => {
const filtered = collected.filter(message => message.author.bot);
const lastMessages2 = filtered.first(1); //Get the last message of this other channel.
const TextMessages2 = `${lastMessages2[0].content}`;
console.log(TextMessages2 + " is the last message of bot")
});
}
}
});
}
I'm having troubles understanding your code so here's how i would do it, maybe it'll help you:
if (message.content.startsWith("!lastmessage")) {
let args = message.content.split(" "); //find every word of the message
if (args.length > 1) { //make sure that there is at least 1 argument, which should be the target channel's id
let target = message.guild.channels.find(c => c.id == args[1]) || null; // find the targeted channel
if (target) { // make sure that the targeted channel exists, if it exists then fetch its last message
target
.fetchMessages({ limit: 1 })
.then(f =>
message.channel.send(
`Last message from <#${target.id}> is...\n> ${f.first().content}`
) // send the last message to the initial channel
);
} else { //if target doesn't exist, send an error
message.channel.send("Target does not exist!");
}
}
}
Currently, the user is able to choose as many roles given within the section, however, I would like to be able to do something along the lines of:
(roleA OR roleB) AND (roleC OR roleD) AND roleE etc
The above is all meant to be triggered by checking what reactions they've already submitted and removing them if the new selection contradicts the current.
Users are able to apply reaction roles to themselves by reacting to a specified message. Depending on whether a certain choice is made, it's to be able to add/remove from another role i.e
How old are you?
- 18-24
- 25-30
- 31+
What's your Gender?
- Male
- Female
What Continent are you in?
- IDK, I'm running out of
- Bogus Questions
- To fill in space.
if user clicks, 25-30, but then realises they're 24, and click that instead, I'd like the prior reaction & role to be removed without manual interference required.
Not only 1 option will be available, so would like to have multiple selections available as well.
bot.on("raw", event =>{
console.log(event);
const eventName = event.t;
if(eventName === 'MESSAGE_REACTION_ADD')
{
if(event.d.message_id === '<REMOVED ID>')
{
var reactionChannel = bot.channels.get(event.d.channel_id);
if(reactionChannel.messages.has(event.d.message_id))
return;
else {
reactionChannel.fetchMessage(event.d.message_id)
.then(msg => {
var msgReaction = msg.reactions.get(event.d.emoji.name + ":" + event.d.emoji.id);
var user = bot.users.get(event.d.user_id);
bot.emit('messageReactionAdd', msgReaction, user);
})
.catch(err => console.log(err));
}
}
}
else if (eventName === 'MESSAGE_REACTION_REMOVE')
{
if(event.d.message_id === '<REMOVED ID>')
{
var reactionChannel = bot.channels.get(event.d.channel_id);
if(reactionChannel.messages.has(event.d.message_id))
return;
else{
reactionChannel.fetchMessage(event.d.message_id)
.then(msg => {
var msgReaction = msg.reactions.get(event.d.emoji.name + ":" + event.d.emoji.id);
var user = bot.users.get(event.d.user_id);
bot.emit('messageReactionRemove', msgReaction, user);
})
.catch(err => console.log(err));
}
}
}
});
bot.on('messageReactionAdd', (messageReaction, user) => {
var roleName = messageReaction.emoji.name;
var role = messageReaction.message.guild.roles.find(role => role.name.toLowerCase() === roleName.toLowerCase());
if(role)
{
var member = messageReaction.message.guild.members.find(member => member.id === user.id);
if(member)
{
member.addRole(role.id);
console.log('Success. Added role.');
}
}
});
bot.on('messageReactionRemove', (messageReaction, user) => {
var roleName = messageReaction.emoji.name;
var role = messageReaction.message.guild.roles.find(role => role.name.toLowerCase() === roleName.toLowerCase());
if(role)
{
var member = messageReaction.message.guild.members.find(member => member.id === user.id);
if(member)
{
member.removeRole(role.id);
console.log('Success. Removed role.');
}
}
});```
In your messageReactionAdd event, you can try to find a reaction or role applied by/to the user that corresponds with a specific choice. If there is one, that means they had already chose that answer. You can then remove them before adding the new role to the user. If not, the code should continue as usual.
bot.on('messageReactionAdd', async (messageReaction, user) => { // async needed for 'await'
const name = messageReaction.emoji.name.toLowerCase();
const message = messageReaction.message;
const role = message.guild.roles.find(role => role.name.toLowerCase() === name);
const member = message.guild.member(user);
if (!role || !member) return;
const emojis = message.reactions.map(emoji => emoji.name);
const conflictingReaction = message.reactions.find(reaction => reaction.users.get(user.id) && emojis.includes(reaction.emoji.name));
const conflictingRole = member.roles.find(role => emojis.includes(role.name.toLowerCase());
try {
if (conflictingReaction || conflictingRole) {
await conflictingReaction.remove(user);
await member.removeRole(conflictingRole);
}
await member.addRole(role);
console.log('Success.');
} catch(err) {
console.error(err);
}
});