How to delete n messages from a channel? - discord.js

I am working on a discord bot. I want to implement a feature like Tatsumaki's t!prune 5 (deletes 5 messages from the history).
Okay, lemme show you what I mean one way or another:
msg.channel.delete(2); // 2 is the number of messages being deleted.
// this is not a real function, just an example
Is there such a thing like what I showed?

Try to use the following
const fetchedMessages = await msg.channel.fetchMessages();
const amount = 50 // number of messages that should be deleted (max 50 otherwise you have to change the option limit property for .fetchMessages())
for (let i = 0; i < amount; i++) {
await fetchedMessages[i].delete()
}
You could also use the .bulkDelete() function:
await msg.channel.bulkDelete(AMOUNT)

Related

how would i get embed messages from a specific channel? [Discord.js V12]

I am trying to get a number from an embed field value from all the embeds in a specific channel and combine those numbers into one big number
Currently fetching messages from a specific channel like this
async function fetchMessagesUntil(channel, endDate, lastID) {
let messages = [];
try {
messages = (await channel.messages.fetch({ limit: 100, before: lastID })).array();
for (let i = 0; i < messages.length; i++) {
if (messages[i].createdAt.getTime() < endDate.getTime()) {
return messages.slice(0, i);
}
}
return messages.concat(await fetchMessagesUntil(channel, endDate, messages[messages.length - 1].id));
} catch {
return messages;
}
}
let end = new Date();
end.setDate(end.getDate() - 2); // Subtract two days from now
(await fetchMessagesUntil(channel, end)).forEach(x => console.log(x.content));
message.delete()
but embeds are empty when logging it to console
any ideas?
You can look here at the docs. The Message class has many properties. Message.content can be empty, but the message object may contain other properties like Message.embeds, Message.attachments, etc.
So in your code you would access the embeds like this:
let result = 0;
(await fetchMessagesUntil(channel, end)).forEach((message) => {
message.embeds.forEach((embed) => {
console.log(embed);
// result += ...
});
});
Also take a look at MessageEmbed at the docs. There you can see all the methods and properties it has, access them and get what you want from the embeds.
When getting a value from embed's field, I would check if it is the field you want to extract a value from, for example by checking its name. If you know that it is the wanted field, you can get the value from there. First use !isNaN(fieldValue), so you know that the field value is a number. Then I would use parseInt(fieldValue) to parse the string into an integer. And finally using the += operator, add the field's numeric value to the final result variable.

How do I set a delay on a file upload in React?

I want to batch my records for uploading so I don't create server issues. I would like to be able to push 10 records at a time, every five seconds, just to prove the concept for now. I've put setInterval functions all over my code but can't get it to run at the right time. I've been at this for days but can't figure it out.
chunkData(data) {
const maxRecords = 10;
const loops = (data.length % maxRecords > 0) ? Math.floor(data.length / maxRecords) + 1 : data.length / maxRecords;
//console.log('data: ', data);
//console.log('loops: ', loops);
//setInterval(() => {
for (let loop = 0; loop < loops; loop++) {
console.log('loop: ', loop);
let start = loop * maxRecords;
//setInterval(() => {
for (let batch = start; batch < start + maxRecords; batch++) {
// the line below will become the upload function once I get this to work
if (data[batch] !== undefined) console.log('data[batch]: ', data[batch]);
}
//start = start + 10;
//}, 5000);
}
//}, 5000);
}
I'm certain it's a simple tweak I need but I'm clueless as to how to make it happen right now. Any advice would be greatly appreciated.
The bigger problem you'll have to figure out is that a client-side change will not help in this case. If you're trying to help your server this way, what happens when there is more than 1 concurrent user uploading? 2? 3? 100? 1000? This solution isn't scalable. You'll eventually (or very quickly) have to make sure your server is robust enough to handle upload traffic.
As for your specific code. Your problem is that you're using setInterval inside a for-loop but use the same value. Remember, uploading (or any XHR/fetch request) is an asynchronous action. Right now, you're setting the intervals to run at basically the same time.
To get actual intervals between uploads, you'd need something like this:
for (let loop = 0; loop < loops; loop++) {
console.log('loop: ', loop);
let start = loop * maxRecords;
for (let i=1, batch = start; batch < start + maxRecords; i++, batch++) {
// the line below will become the upload function once I get this to work
if (data[batch] !== undefined) {
setInterval(() => {
//make upload request here
}, (loop + 1) * i * 5000);
}
}
}
I'm not sure what your "start" variable is supposed to be.
In any case, this code is really error prone and fragile. I really advise reconsidering your approach and look into fixing your server side.
If you still wish to go with this client-side hack and even if not, and you're looking for a more stable client-side solution. I advise to go with react-uploady. It takes care of the uploads for you and all the edge cases that come with managing uploads in React.
You can even do your intervals easily:
import ChunkedUploady, { useChunkStartListener } from "#rpldy/chunked-uploady";
import UploadButton from "#rpldy/upload-button";
const CHUNK_SIZE = 1e+6;
const UploadButtonDelayedChunks = () => {
useChunkStartListener(() => new Promise((resolve) => {
//delays chunk upload by 5 seconds
setTimeout(resolve, 5000);
}));
return <UploadButton/>;
};
export const ChunkedExample = () => {
return (
<ChunkedUploady
destination={{ url: "https://my-server/upload" }}
chunkSize={CHUNK_SIZE}>
<UploadButtonDelayedChunks/>
</ChunkedUploady>
);
};

Getting count of a specific reaction on a message

I'm trying to make a bot that will delete messages with a certain amount of thumbsdown reactions. I'm having trouble identifying the count of a specific reaction on a message.
Basically, I've created a command that waits for messages and adds them to my msgarray. After each message, I want to go through the array and delete any messages with the specified amount of reactions.
This is what I have so far:
var msgarray = [];
const msgs = await message.channel.awaitMessages(msg => {
msgarray.push(msg);
for (i = 0; i < msgarray.length; i++) {
// I'm not sure where to go from here, I want to make an if statement that checks
// for a certain amount of thumbsdown reactions on the message
if (msgarray[i].reactions) {
// incomplete
}
}
});
This is my first time programming in javascript, so I apologize if this code doesn't make much sense.
TextChannel.awaitMessages() resolves with a Collection, so the msg parameter you're using is not a single message, but a Collection of multiple messages.
Also, it would be better to check messages only when they get a reaction, using the messageReactionAdd event, that fires every time someone adds a reaction.
It should look like this:
// this code is executed every time they add a reaction
client.on('messageReactionAdd', (reaction, user) => {
let limit = 10; // number of thumbsdown reactions you need
if (reaction.emoji.name == '👎' && reaction.count >= limit) reaction.message.delete();
});

Deleting my messages in a server using bulkDelete (discord.js)

I am new to discord.js but learned that I can delete my messages using bulkDelete and it will delete them all, even if they are older than 2 weeks. I clear my messages in a server I moderate manually once a month and needless to say it takes forever. I was wondering if anyone would be able to help me make a command that will do this automatically whenever I call it?
Thanks,
K
I would set up a recursive function that checks if there are messages in the channel (100 max every time): if there are no messages it stops otherwise it deletes them and restarts.
function clean(channel, limit = 100) {
return channel.fetchMessages({limit}).then(async collected => {
let mine = collected.filter(m => m.author.id == 'your_id_here'); // this gets only your messages
if (mine.size > 0) {
await channel.bulkDelete(mine, true);
clean(channel);
} else channel.send("The channel is now empty!").delete(5000); // this message is deleted after 5 s
});
}
You can adapt this idea to your existing command parser or, if you don't know how to implement this, try:
client.on('message', msg => {
if (msg.author.bot || msg.author != YOU) return;
// with YOU i mean your User object, to check permissions
let command = 'clean', // the name of your command
args = msg.content.split(' ');
if (args[0].toLowerCase() == command)
clean(msg.channel, !isNaN(args[1]) ? args[1] : undefined); //<-- THIS is how to use the function
// used a ternary operator to check if the other arg is a number
});
This is just a very basic implementation, there are a lot of better ways to detect commands.
I've just found a way to filter messages.
You can fetch messages and then check for each message if its yours
await message.channel.fetchMessages({
limit: 100
}).then((msgCollection) => {
msgCollection.forEach((msg) => {
if(msg.author.id == message.author.id) {
msg.delete();
}
})
});

User input for a counter

I'm totally new to this and I'm trying to learn by doing. I have some basic skills in c and I've been making small, simple apps for about 2 weeks all by studying other apps and trying to understand how they are built.
I'm trying to make a counter now that is supposed to count people going in or out.
I got everything to work perfectly except for letting the user define the maximum amount. I would like to have the user type in the max amount in the text field and then press a button called start which would give the variable max the value typed in the text box.
Can I get some help with that?
Pseudo code:
mx = Max from User;
nrPersons = 0;
While (Userinput is not ExitProgramm) do
{
if (0 < nrPersons < mx) // allwoed range
{
run your programm that works
}
else
{
if (nrPersons > mx) => take action
if (nrPersons < 0) => take action
}
}

Resources