How to detect a discord message being edited (but not updated)? - discord

I'm using Node and Discord.JS, trying to see if there's a way to differentiate between types of edits whenever a message is edited so a bot can tease the user for editing their message. The function works well so far, and is as follows:
let responses = ["some", "responses"];
bot.on('messageUpdate', ( message ) => {
let result = responses[Math.floor(Math.random()*(responses.length)-1)]
message.channel.send(result);
})
However, this detects all message updates, including say a link updating to have an embed. Is there any way to differentiate between a deliberate user edit and a message being updated with an embed through event listeners, or will I need to make a workaround with an if..else statement?

To check when message is edited, You'll be required to use the messageUpdate event listener.
In the messageUpdate event, there is 2 parameters. (oldMessage, newMessage) Learn More
Then, you can check the content of the oldMessage & newMessage parameters by using the .content property.
Example of code:
client.on("messageUpdate", (oldMessage, newMessage) => {
if(oldMessage.content === newMessage.content) return // Will do nothing if the content of oldMessage is equals to newMessage's content
// Do here your stuff
})
I hope I helped you!

Ignore this, i have not found an answer as I had hoped ;(

Related

How to get bot to reply to user with a (#)ping

I am trying to get a bot to respond to people with a ping in the message, for example: "#user", but everything I've tried have given me not a function error or undefined error. All the stuff I can find about it is either outdated for discord.js v14 or it is for discord.py
Here is my code:
client.on("messageCreate", (message) => {
if (message.content.startsWith("test")) {
const user = message.author.userId();
message.channel.reply(`Hello <#${user}>`)
}
});
I've also attempted variations of the .userId() part - such as .tag, .user.id, and .username but all of them have come back with some sort of undefined error. I know it says userId is a snowflake on discord.js but I am unsure on how to use that for I am fairly new to javascript and discord.js. Also, please know that I am using Replit to host the bot and have discord.js#14.5.0 installed.
So, there are a couple issues here.
Issue 1
message.author.userId() is not a function. When trying to get a user's ID, you want to know what each property is returning.
message -> returns the Message object, which contains the data for the message.
message.author -> returns the User object, which contains the data for the user profile.
message.member -> returns the Member object, which contains the data for the guild member profile.
And so on.
In this case, you're going to want to get the User object: being message.author. You've already figured this out.
Now, the User Object has it's own set of properties (which you can find in the documentation at https://discord.js.org/).
The property that you are looking for is: .id, or in your use-case, message.author.id.
Your other attempts, message.author.tag returns the tag, message.author.user.id will throw an error, and message.author.username returns the user's username.
Issue 2
Your second issue is the .reply() method that you're using. The Channel Object doesn't have a .reply() method, but the message does.
So, how you would write this code:
client.on("messageCreate", async(message) => {
if(message.content.toLowerCase().startsWith("test")) {
// Note that I added the .toLowerCase() method to ensure you can do tEST and it still works!
message.reply({ content: `Hello, ${message.author}!` });
}
});
Also, a cool feature that discord.js has is that you can supply the User or Member Object to the content of a message, and it will automatically mention the desired person.
Hope this helps!

Message object .edit() stops working after some time

First I create an object
var queue = {1:{},2:{},3:{}};
And then I store the message based on QueueKey, or edit if it's already created
if (typeof queue[QueueKey].messageOBJ == 'undefined')
{
queue[QueueKey].messageOBJ = await configChannel.send({ embeds: [getEmbedFloor(QueueKey)] });
}
else
{
queue[QueueKey].messageOBJ = await queue[QueueKey].messageOBJ.edit({ embeds: [getEmbedFloor(QueueKey)] });
}
everything starts working well but after sometime(1~2 hours) bot stops editing the already created message, looks like it lose object reference.
It not pops any error message or code break, seems like the message was edited sucessfully but the real message in discord still the same
I'm thinking in store the messageID instead the whole object and search for the message ID with .fetch() but this will lead to other problems
is there any way to store message Objects properly?
I discovered my problem, actually bot was editing the message to frequently, so after some time discord "auto ban" my bot for some time, something like a cooldown, só it starts to get slower and slower, up to seems like it is stuck.
My solution was check message before edit, to compare if the changes in message are really necessary, before edit or not

How to check if message contains emojis discord.js

I need to check if a message sent by user contains emojis because my database can't store this type of data. So I thought that I'll use a message.content.match() or message.content.includes() but when I use it, it still is not enough. I was thinking about making something like blacklist but for emojis and then I realized that I need to save a blacklist of all emojis so I gave up on that. My question for you is, do you know any easier way to make this? I was searching for solution to my problem but I didn't find anything.
Thank you a lot for any help.
if(message.author.id!='botid' && message.author.id===userdbId && message.content.match(/<a?:.+?:\d+>/)){
const name = args.join(" ");
const username = name.slice(0);
conn.query(`UPDATE users SET ignick='`+username+`' WHERE userID='${message.author.id}'`);
console.log(username);
message.channel.send("success message");
conn.end(err => {
if(err){
throw error;
}
console.log('Disconnected from database');
})
}
else{
console.log('bot has been stopped from adding his message to database');
}```
At top of this code i made a connect function and two constructors to pull from database userId
Whenever an emote is used in a message, it follows this format: <:OmegaStonks:723370807308582943>, where the name of the emote is "OmegaStonks" and the id links to the link to the image, like so: https://cdn.discordapp.com/emojis/723370807308582943.png
Detecting this pattern is pretty easy using regex.
<a?:.+?:\d+>
which takes any character from the first : to the second : (and I used a ? to make the wildcard . stop as soon as possible). You also can't have colons in emote names, so it won't abruptly stop there.
Source
Here is how you could do it
client.on('message', msg => {
if(msg.content.match(/<a?:.+?:\d+>/)) return; //or whatever action(s) you want to do
})

How to not send bots message edit discord.js

I have a message edit log but I want to stop sending the log if a mobs message was updated, I tried a few codes like
if(bot.oldMessage.content.edit()){
return;
}
It showed and error
cannot read property 'edit' of undefined
I then removed edit then content was undefined. The code for the message update is below.
The Code
module.exports = async (bot, oldMessage, newMessage) => {
let channels = JSON.parse(
fs.readFileSync('././database/messageChannel.json', 'utf8')
);
let channelId = channels[oldMessage.guild.id].channel;
let msgChannel = bot.channels.cache.get(channelId);
if (!msgChannel) {
return console.log(`No message channel found with ID ${channelId}`);
}
if (oldMessage.content === newMessage.content){
return;
}
let mEmbed = new MessageEmbed()
.setAuthor(oldMessage.author.tag, oldMessage.author.displayAvatarURL({dynamic: true}))
.setColor(cyan)
.setDescription(`**Message Editied in <#${oldMessage.channel.id}>**`)
.addField(`Before`, `${oldMessage.content}`)
.addField(`After`, `${newMessage.content}`)
.setFooter(`UserID: ${oldMessage.author.id}`)
.setTimestamp()
msgChannel.send(mEmbed)
}
How would I stop it from sending the embed if a bots message was updated.
Making a really simple check will resolve this issue. In Discord.js there is a user field that tells you if the user is a bot or not.
In fact, it is really recommended you add this in the "onMessage" part of your code as it stops other bots from using your bot, this is to make sure things are safe and no loopbacks/feedbacks happen, either way, you don't want a malicious bot taking advantage of your bot, which can get your bot in trouble too.
Here is what you want to do;
if (message.author.bot) return;
What this code specifically does is check if the message's author is a bot, if it returns true, it will break the code from running, if it returns a false, the code continues running.
You can do the same if you want to listen to bots ONLY by simply adding a exclamation mark before the message.author.bot like this;
if (!message.author.bot) return;
It is also possible to see what other kinds of information something holds, you can print anything to your console. For example, if you want to view what a message object contains, you can print it into your console with;
console.log(message) // This will show everything within that object.
console.log(message.author) // This will show everything within the author object (like ID's, name, discriminators, avatars, etc.)
Go ahead and explore what you can do!
Happy developing! ^ -^
That is really easy to do. All you need to do is check if the author of the message ist a bot and then return if true. You do that like this
if (oldMessage.author.bot) return;

Discord JS v12: How do you get a message's content by it's ID?

I'm relatively new to discord.js, and I've started building a bot project that allows a user to create a message via command, have that message stored in a hidden channel on my private server, and then said message can be extracted through the message ID.
I have the write working and it returns the message ID of the message sent in the hidden channel, but I'm completely stumped on the get command. I've tried searching around online but every method I tried would return errors like "Cannot read property 'fetch' of undefined" or "'channel' is not defined". Here are some examples of what I tried, any help would be appreciated. Note that my args is already accurate, and "args[0]" is the first argument after the command. "COMMAND_CHANNEL" is the channel where the command is being executed while "MESSAGE_DATABASE" is the channel where the targeted message is stored.
let msgValue = channel.messages.cache.get(args[0])
client.channels.cache.get(COMMAND_CHANNEL).send(msgValue.content)
let msgValue = msg.channel.message.fetch(args[0])
.then(message => client.channels.cache.get(COMMAND_CHANNEL).send(msgValue.content))
.catch(console.error);
I even tried using node-fetch to call the discord API itself
const api = require("node-fetch")
let msgValue = api(`https://discordapp.com/api/v8/channels/${MESSAGE_DATABASE}/messages/${args[0]}`)
.then(message => client.channels.cache.get(COMMAND_CHANNEL).send(msgValue.content))
.catch(console.error);
Am I missing something or am I making some sort of mistake?
Edit: Thanks for the help! I finished my bot, it's just a little experimental bot that allows you to create secret messages that can only be viewed through their ID upon executing the command :get_secret_message <message_id>. I posted it on top.gg but it hasn't been approved yet, so in the meantime if anyone wants to mess around with it here is the link: https://discord.com/api/oauth2/authorize?client_id=800368784484466698&permissions=76800&scope=bot
List of commands:
:write_secret_message - Write a secret message, upon execution the bot will DM you the message ID.
:get_secret_message <message_id> - Get a secret message by its ID, upon execution the bot will DM you the message content.
:invite - Get the bot invite link.
NOTE: Your DMs must be turned on or the bot won't be able to DM any of the info.
My test message ID: 800372849155637290
fetch returns the result as promise so you need to use the then to access that value instead of assigning it to a variable (msgValue). Also you made a typo (channel.message -> channel.messages).
I would recommend using something like this:
msg.channel.messages
.fetch(args[0])
.then(message => {
client.channels
.fetch(COMMAND_CHANNEL)
.then(channel => channel.send(message.content))
.catch(console.error)
})
.catch(console.error)
I think you were quite close with the second attempt you posted, but you made one typo and the way you store the fetched message is off.
The typo is you wrote msg.channel.message.fetch(args[0]) but it should be msg.channel.messages.fetch(args[0]) (the typo being the missing s after message). See the messages property of a TextChannel.
Secondly, but this is only a guess really as I can't be sure since you didn't provide much of your code, when you try to fetch the message, you are doing so from the wrong channel. You are trying to fetch the message with a given ID from in the channel the command was executed from (the msg.channel). Unless this command was executed from the "MESSAGE_DATABASE" channel, you would need to fetch the message by ID from the "MESSAGE_DATABASE" channel instead of the msg.channel.
Thirdly, if you fetch a message, the response from the Promise can be used in the .then method. You tried to assign the response to a variable msgValue with let msgValue = msg.channel.message.fetch(args[0]) but that won't do what you'll expect it to do. This will actual assign the entire Promise to the variable. What I think you want to do is just use the respone from the Promise directly in the .then method.
So taking all that, please look at the snippet of code below, with inspiration taken from the MessageManager .fetch examples. Give it a try and see if it works.
// We no longer need to store the value of the fetch in a variable since that won't work as you expect it would.
// Also we're now fetching the message from the MESSAGE_DATABASE channel.
client.channels.cache.get(MESSAGE_DATABASE).fetch(args[0])
// The fetched message will be given as a parameter to the .then method.
.then(fetchedMessage => client.channels.cache.get(COMMAND_CHANNEL).send(fetchedMessage.content))
.catch(console.error);

Resources