How can I check If a message exists in discord.js - javascript

I would like to have some kind of reaction roles into my bot. For that I have to test If the message ID that the User sends to the bot is valid. Can someone tell me how to do that?

You can do that with .fetch() as long as you also know what channel you're looking in.
If the message is in the same channel the user sent the ID in then you can use message.channel to get the channel or if it's in another channel then you have to get that channel using its ID using message.guild.channels.cache.get(CHANNEL_ID).
So your code could be like this if it's in the same channel:
const msg = message.channel.messages.fetch(MESSAGE_ID)
or if it's in a different channel:
const channel = message.guild.channels.cache.get(CHANNEL_ID)
const msg = channel.messages.fetch(MESSAGE_ID)

This works for me (Discord.js v12)
First you need to define the channel where you want your bot to search for a message.
(You can find it like this)
const targetedChannel = client.channels.cache.find((channel) => channel.name === "<Channel Name>");
Then you need to add this function:
async function setMessageValue (_messageID, _targetedChannel) {
let foundMessage = new String();
// Check if the message contains only numbers (Beacause ID contains only numbers)
if (!Number(_messageID)) return 'FAIL_ID=NAN';
// Check if the Message with the targeted ID is found from the Discord.js API
try {
await Promise.all([_targetedChannel.messages.fetch(_messageID)]);
} catch (error) {
// Error: Message not found
if (error.code == 10008) {
console.error('Failed to find the message! Setting value to error message...');
foundMessage = 'FAIL_ID';
}
} finally {
// If the type of variable is string (Contains an error message inside) then just return the fail message.
if (typeof foundMessage == 'string') return foundMessage;
// Else if the type of the variable is not a string (beacause is an object with the message props) return back the targeted message object.
return _targetedChannel.messages.fetch(_messageID);
}
}
After this procedure, just get the function value to another variable:
const messageReturn = await setMessageValue("MessageID", targetedChannel);
And then you can do with it whetever you want.Just for example you can edit that message with the following code:
messageReturn.edit("<Your text here>");

Related

Can't send a message to a specific channel

I'm trying to create a modmail system and whenever I try to make it, it says "channel.send is not a function, here is my code."
const Discord = require("discord.js")
const client = new Discord.Client()
const db = require('quick.db')
// ...
client.on('message', message => {
if(db.fetch(`ticket-${message.author.id}`)){
if(message.channel.type == "dm"){
const channel = client.channels.cache.get(id => id.name == `ticket-${message.author.id}`)
channel.send(message.content)
}
}
})
// ...
client.login("MYTOKEN")
I'm trying this with version 12.0.0
EDIT:
I found my issue, for some reason the saved ID is the bots ID, not my ID
As MrMythical said, you should use the find function instead of get. I believe the issue is that you're grabbing a non-text channel, since channel is defined, you just can't send anything to it.
You could fix this by adding an additional catch to ensure you are getting a text channel, and not a category or voice channel. I would also return (or do an error message of sorts) if channel is undefined.
Discord.js v12:
const channel = client.channels.cache.find(c => c.name === `ticket-${message.author.id}` && c.type === 'text');
Discord.js v13:
const channel = client.channels.cache.find(c => c.name === `ticket-${message.author.id}` && c.type === 'GUILD_TEXT');
Edit:
You can tell channel is defined because if it weren't it would say something along the lines of: Cannot read property 'send' of undefined.
You are trying to find it with a function. Use .find for that instead:
const channel = client.channels.cache.find(id => id.name == `ticket-${message.author.id}`)

discord.js Javascript string manipulation

so i am creating a bot with a kick command and would like to be able to add a reason for said action, i've heard from somewhere that i may have to do string manipulation. currently i have a standalone reason as shown in the code below:
client.on("message", (message) => {
// Ignore messages that aren't from a guild
if (!message.guild) return;
// If the message starts with ".kick"
if (message.content.startsWith(".kick")) {
// Assuming we mention someone in the message, this will return the user
const user = message.mentions.users.first();
// If we have a user mentioned
if (user) {
// Now we get the member from the user
const member = message.guild.member(user);
// If the member is in the server
if (member) {
member
.kick("Optional reason that will display in the audit logs")
.then(() => {
// lets the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
.catch((err) => {
// An error happened
// This is generally due to the bot not being able to kick the member,
// either due to missing permissions or role hierarchy
message.reply(
"I was unable to kick the member (this could be due to missing permissions or role hierarchy"
);
// Log the error
console.error(err);
});
} else {
// The mentioned user isn't in this server
message.reply("That user isn't in this server!");
}
// Otherwise, if no user was mentioned
} else {
message.reply("You didn't mention the user to kick!");
}
}
});
Split message.content and slice the first 2 array elements, this will leave you with the elements that make up the reason. Join the remaining elements back to a string.
const user = message.mentions.users.first();
const reason = message.content.split(' ').slice(2).join(' ');
Here is something that could help:
const args = message.content.slice(1).split(" "); //1 is the prefix length
const command = args.shift();
//that works as a pretty good command structure
if(command === 'kick') {
const user = message.mentions.users.first();
args.shift();
const reason = args.join(" ");
user.kick(reason);
//really close to Elitezen's answer but you might have a very terrible problem
//if you mention a user inside the reason, depending on the users' id, the bot could kick
//the user in the reason instead!
}
Here's how you can take away that problem (with regex)
const userMention = message.content.match(/<#!?[0-9]+>/);
//you may have to do some more "escapes"
//this works since regex stops at the first one, unless you make it global
var userId = userMention.slice(2, userMention.length-1);
if(userId.startsWith("!")) userId = userId.slice(1);
const user = message.guild.members.cache.get(userId);
args.shift();
args.shift();
user.kick(args.join(" "))
.then(user => message.reply(user.username + " was kicked successfully"))
.catch(err => message.reply("An error occured: " + err.message))
I assume you want your full command to look something like
.kick #user Being hostile to other members
If you want to assume that everything in the command that isn't a mention or the ".kick" command is the reason, then to get the reason from that string, you can do some simple string manipulation to extract the command and mentions from the string, and leave everything else.
Never used the Discord API, but from what I've pieced from the documentation, this should work.
let reason = message.content.replaceAll(".kick", "")
message.mentions.forEach((mentionedUser) => reason.replaceAll("#" + mentionedUser.username, "")
// assume everything else left in `reason` is the sentence given by the user as a reason
if (member) {
member
.kick(reason)
.then(() => {
// lets the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
}

Responding to a message in discord.js

I would like to send a message "E" to the channel where someone sent a message starting with s#. I have got 2 problems:
I have got a function:
function read(msg)
{
if(msg[0] === "s" && msg[1] === "#") console.log("E");
}
and I don't know how to call this function with a message that someone sent as 'msg'.
And when I figure out how to do this, I would like to add a channel.send("E");, but I don't know how to get the id of the channel that the message was sent to.
If you want to use the read function there two ways
As #SickBoy Said,
function read(msg){
if(msg.content.startsWith('s#'){
return true;
}
else{
return false;
}
}
or else,
function read(msg){
const data = msg.content.split('')
if(data[0] === 's' && data[1] === '#'){
return true;
}
else{
return false;
}
}
To call this function simply add a event of message.
client.on('message' , message=> {
const res = read(message)
if(res){
//The message starts with s#
}
else{
//It doesn't start with s#
}
})
client.on('message', message => {
if(message.content.startsWith('s#')) console.log('s#');//check if the message starts with s#
});
message.channel.send('this is a reply to the message sent in this channel');
see docs: https://discord.js.org/#/docs/main/stable/class/Client?scrollTo=e-message
Edit (the whole code with the read function):
const Discord = require('discord.js');
const client = new Discord.Client();
client.on('message', message => {
read(message);
});
function read(message){
if(message.content.startsWith('s#')) console.log('s#');
}
client.login('your-token-here');
There is an event called message which gets emitted whenever someone sends a message in the server. This event returns a message object which contains all the information about that message like content, author, channel, member, etc. So to send something back as a reply you can do this:
client.on('message', message => {
if (message.content.startsWith('s#')) {
message.channel.send('E');
}
}
Also, I saw you're doing this in your ready function: msg[0]. This is not how you access the content of a message object. It's not an array. You can get the content of a message using let text = message.content. This text is of string type and stores the message text.

Filtering the content of all messages in a channel

I'm writing a bot which logs user reactions to specific messages (events). Each generates a message containing id of the event to which they reacted on a log channel. Now I'm trying to get the bot to remove any generated messages for an event if the reaction was removed. My code:
client.on("messageReactionRemove", (reaction, user) => {
if(user.bot) return;
let message = reaction.message;
ORid = message.id;
ORid = ORid.toString();
if(message.channel.id == '709887163084439555') {
if(message.content.charAt(0) == '|'){
var logChannel = client.channels.get('710092733254991893')
logChannel.fetchMessages().then(messages => {
var msgToRemove = messages.filter(m => message.content.includes(ORid))
logChannel.bulkDelete(msgToRemove)
}).catch(err => {
console.log('Error while doing Bulk Delete');
console.log(err);
});
} else return;
} else return;
});
The first id is event channel, the other is where logs are generated. However, instead of filtering all the messages on the log channel, it checks whether the event contains it's id and if so, purges all logs. What can I do to fix this?
It looks like you have a bug in the line filtering the messages:
var msgToRemove = messages.filter(m => message.content.includes(ORid))
You're checking message.content.includes(ORid), which is always going to be false.
This is because you're using the message variable defined earlier instead of m from the filter. The correct way to write the line would be:
var msgToRemove = messages.filter(m => m.content.includes(ORid))

discord delete message filter

I made a code that states that when offline users were chatting, they were deleted and a message was sent to the console that offline chat was detected.
const Discord = require('discord.js');
const bot = new Discord.Client();
bot.on('message', message => {
let member = message.member;
let status = member.user.presence.status;
let args = message.content.trim().split(' ');
if(args[0]){
if(status === "offline") {
message.delete();
}
}
bot.on('messageDelete', (msg, status) => {
if(status === "offline"){
console.log('Offline user chat detected.')
}
}
However, the messageDelete section did not work and I knew status was a problem.
How can I get the other handler variables and apply them?
Client.messageDelete only allows 1 paramter, being the Message. Therefore, you may use the Message object to access the author property which is a User object. From the User object, you can access the status by getting the User.presence.status.
As a result, your messageDelete event should look like this:
bot.on('messageDelete', msg => {
if(msg.author.presence.status === "offline") {
console.log('Offline user chat detected.');
}
}

Categories

Resources