javascript is still vague to my knowledge, and I cannot be precise on the sensibility in the following code I have manufactured. I am programming a discord bot that categorizes messages into a variety of channels, and the question has approached me to how I can program the bot by deleting follow up bot messages after 2 user messages were sent subsequently after the bot message.
if (bot.on(client, user.msg = '2'));{
msg.channel('message' = msg.delete)
}
Help is to be requested and I hope my query makes sense in the context I am implying, Regards, Coder
P.S: How do I change the bot messages text color as well?
No offense, but your code was completely faulty, so I just made some new code.
bot.on('message', aysnc message => {
var messagenumber = 0; //Makes variable for the number of messages sent
if(message.member.user.username === bot.user.username) return; //If the person who posts a message is the bot, it doesn't the code below.
if(messagenumber = 1) return bulkDelete(100), messagenumber = 0 //Checks if the variable is 1, and if it is, this means it's the second time a message posted, so it deletes messages (Limit is 100) then resets variable.
messagenumber = 1; //Makes variable 1 (This is to make it know it is the the second time a message is posted for the next time).
});
I didn't test this code, so it may not work properly, but if it does work I hope it helps you with your bot.
For the P.S (Changing text color): You can use these (Replace "NoKeyWordsHere" with your message). I don't recommend this, cause it'd take a long time to add it to every message sent. (You can use these on your messages too)
Related
I'm currently running discord.js v13 and I'm trying to find a way of finding the last message sent by a specific user. So far, I've come up with the idea of iterating on an array of user IDs, then iterating on each channel and comparing each timestamp with the pervious timestamp found until it finds the latest one and stores it. However, this doesn't seem to work and I just keep getting today's date for ALL the users even though the majority of them haven't sent a message today.
My Code:
for(var i = 0; i < array_of_users.length; i++) {
for (const channel of message.guild.channels.cache.values()) {
if (channel.isText()) {
let messages = await channel.messages.fetch().catch(e => console.log(e));
messages.each((msg) => {
if (msg.author.id === array_of_users[i]) {
if(x == 0) {
old_date = new Date(msg.createdTimestamp).toDateString();
snowflakes.push(old_date);
x += 1;
} else {
var new_date = new Date(msg.createdTimestamp).toDateString();
let splitOld = old_date.split(" ");
let splitNew = new_date.split(" ");
if(parseInt(splitNew[3]) >= parseInt(splitOld[3])) {
year = splitNew[3];
if(getMonthInt(splitNew[1]) >= getMonthInt(splitOld[1]) ) {
monthC = splitNew[1];
if(getDayInt(splitNew[2]) >= getDayInt(splitOld[2])) {
dayNum = splitNew[2];
} else {
dayNum = splitOld[2];
}
} else {
monthC = splitOld[1];
dayNum = splitOld[2];
}
} else {
year = splitOld[3];
dayNum = splitOld[2];
monthC = splitOld[1];
}
}
}
})
}
}
console.log(`${monthC}-${dayNum}-${year}`);
}
The code above I've written to sort the dates and get the latest one, However something is wrong that it keeps getting the latest date and sometimes even future dates that haven't occurred yet. I can't seem to find the issue but I am speculating that it is originating around the if (msg.author.id === array_of_users[i]) area.
I'm trying to find a way of finding the last message sent by a specific user.
Discord.JS provides no 'built in' way of doing this. The best you can do is by grabbing their messages and comparing each of them to one another until you've exhausted your options and are left with the optimal result. So your approach is (more or less) correct, although your implementation does have some function errors that are throwing you off.
So far, I've come up with the idea of iterating on an array of user IDs, then iterating on each channel and comparing each timestamp with the pervious timestamp found until it finds the latest one and stores it.
If you only are only looking for the most recent message for a specific User, then it is redundant to be dealing with an Array of Users altogether.
However, this doesn't seem to work and I just keep getting today's date for ALL the users even though the majority of them haven't sent a message today.
There are a number of errors in your approach which could be causing this. Here's a quick few of the more generalized / lack-of-experience related errors in your solution for you to work on:
The else block where you're comparing days split up from timestamps is super convoluted. Why not just use the createdTimestamp value from the Message instance itself, then reconstruct the whole monthC-dayNum-year thing again later on using that if you need to?
You're likely going to be hitting Discord's Rate limits (rather frequently) with your script as-is. To put it in perspective, you're basically spamming requests to their API for the next X messages in channels [A, B, ...ZA, ZB] repeatedly. You can optimize this a lot by making logical inferences as to when you can safely 'exclude' a Channel from your search (e.g. if the most recent message you've found in channel X was created on Jun 18 2022, and most recent message found in channel Y was created on Mar 13 2022, you can safely avoid asking Discord for more Messages for channel Y, as it won't have any information relevant to your use case). Writing some additional logic here will pay dividends to you both in how quickly your function can execute, and how frustrating it is to debug once Discord gets upset with you for your small-scale DDOS attack against them.
If I was to solve this problem, the way I would do it would be to employ the following logic:
Given GuildMember X, grab all the Channels in the Guild they belong to.
Filter those Channels so you're only working on TextChannels.
Recursively iterate through those Channels, keeping track of the 'latest message' found belonging to GuildMember X in that Channel (when/if found). Whenever you find a new message belonging to GuildMember X in Channel Y, check if that beats the most recent message found across the entire set thus far. If so, update the best message for the set accordingly. Continually filter the Channels you're working with as you go to exclude Channels that logically cannot hold anything relevant to your search-- any time you finish a recursion, you can go back over the set of Channels and look for any one where the 'best message' in that channel does not beat the current best message. Since you're fetching 'backwards in time' (asking Discord for progressively older and older messages as you continue to recurse), any time the best message in a given channel does not beat the best message across the entire set, you can be certain that the channel does not hold the droids that you are looking for. You're only going to be fetching even older messages than the earliest one already fetched if you continue to look in that Channel, which makes that Channel irrelevant to you at that point.
Lucky for you, I had some time to kill while travelling today, and for whatever reason trying to find an optimal solution to your problem interested me enough to give it a proper shot. The tips I wrote above should help you understand the code below, and if not, leave a comment and maybe I can help you out. Here's how I would solve your problem, while paying attention to logical exclusion and avoiding doing unnecessary work / API calls.
https://codesandbox.io/s/holy-surf-50vpmf?file=/index.js
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
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;
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);
I'm a selflearned mIRC programmer and started very recently so my experience is quite limited. Here's the problem I have:
I'm creating a chat bot for Twitch and have created besides a raffle system a timed message for promting the stream it's on every few minutes. However, I'd also like to repeat the message after X lines of chat lines sent in the chat in-case the chat is going quickly so you don't miss out on social links and stuff for new visitors.
Pseudo-code for what I want to be done:
on !startpromote
if (broadcaster) then PromoteMessage every X amount of lines passed
else return
end
on !stoppromote
if (broadcaster) then PromoteMessage stop
else return
end
You could have a %msgCounter variable in the variables tab and then you could use the TEXT event:
on *:TEXT:#:{
INC %msgCounter
if (%msgCounter > 10) { msg $chan Promotion message. }
}
You'd have to keep track of the %msgCounter variable and reset it when it hits a certain threshold.
Not sure what you mean by broadcaster, however if you mean IRCOp than you can use isop and do:
if ($1 isop $chan) {
}
Where $1 is the user who typed the message, isop determines if the user is an operator (or maybe broadcaster) and $chan for the IRC Channel.