So I recently decided to make a Discord bot, and had been going through some tutorials with no problem. However, when I tried to make a ping command (you know, the kind that says "Your ping is 137 ms"), I got numbers that didn't make sense.
Numbers such as -627 ms, 32 ms, 1001 ms, -10 ms, 238 ms. Basically anything and everything between -1000 and 1000.
Now correct me if I'm wrong, but I'm pretty sure that getting negative numbers means I'm sending the response before I even ask for it, and I'm almost certain I didn't write a precognitive bot :P
I spent some time online looking for a reason why I was getting strange ping numbers, but I came up with zilch. I thought to myself, "Hmmmm..... maybe I'm generating them wrong." So I looked at how other people generated their numbers with discord.js...
...aaaand I hit a wall. As far as I can tell, no one has ever tried generating ping numbers with discord.js. If they have, they haven't shared their precious findings online. At least, that's what it looks like to me. (if you have a link to such a tutorial or post, please send it to me)
I'm generating the numbers with ${Date.now() - message.createdTimestamp} This is the only way I have found to generate them, so if anyone has a better method, I would love to see it.
That snippet fits right in with the rest of my code (and yes, it is a very boring bot):
const Discord = require('discord.js');
const client = new Discord.Client();
const token = require('./token.json').token;
client.on('ready', () => {
console.log('Bot is up and running!');
});
var prefix = "?"
client.on('message', message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
if (message.content.startsWith(prefix + 'ping')) {
message.channel.sendMessage('Pong! Your ping is `' + `${Date.now() - message.createdTimestamp}` + ' ms`');
}
});
client.login(token);
If anybody could give me a reason why I'm getting negative numbers, or give me a better way to generate them, I would be extremely grateful. Thanks in advance.
The variation in ping you're experiencing is due to the variation between between your clock and the remote clock as well as the message id's used to calculate the timestamp not being all that accurate.
Before you jump to one meaning for ping you have to decide what you want to measure. If you're looking to measure the round trip time to send a message and get that same message back frond discord, you could potentially send a discord message, start a timer. then when the promise resolves check how much time has passed.
You could also use .ping as suggested in another answer for the heartbeat ping.
You could also ping the api endpoint though you would probably only be measuring your delay to cloudflare...
You may getting different results, because the Date.now is based on your computer's clock and message.createdTimestamp comes from Discord server (not your computer) clock.
The reason nobody's sharing the ping feature is because it's just reading a client object property client.ws.ping.
https://discord.js.org/#/docs/main/stable/class/WebSocketManager?scrollTo=ping
You can not get the actual ping of another user. But you can get pretty close.
You know that using the system's clock won't work for you because it's out of sync with the actual server.
Your bot can send a message and edit it after that. Then you have two timestamps:
var resMsg = await msg.channel.send('Ping is being appreciated... :bar_chart:');
resMsg.edit('Ping: ' + Math.round((resMsg.createdTimestamp - msg.createdTimestamp) - client.ws.ping))); //client.ping has been moved to the WebSocketManager under client.ws.ping
Subtracting the ping of the bot will remove it's latency to the API while submitting the message.
Hope I could help!
Try this:
client.on('message', message => {
if (message.author.bot) return;
if (!message.content.startsWith(prefix)) return;
if (message.content.startsWith(prefix + 'ping')) {
msg.channel.send({embed: {
color: 0x2ed32e,
fields: [{
name: "Pong",
value: "My Ping: " + Math.round(client.ws.ping) + ' ms' //client.ping has been moved to the WebSocketManager under client.ws.ping
}
],
}
})
}})
I hope this will help c:
client.on('messageCreate', message => {
if (message.content === `${config.PREFIX}ping`) {
message.channel.send("Calculating ...").then(m =>{
var ping = Math.round((m.createdTimestamp - client.ws.ping) - message.createdTimestamp ); //more closer to discord ping
setTimeout(() => {
m.edit(`**Your Ping Is: **${ping}ms`);
}, 3000);
});
}) //DISCORD.JS V13
I'm sorry that you're facing this issue with your Discord bot. I used your code to analyse the issue and have come up with this solution. You see how you have:
${Date.now() - message.createdTimestamp}
Well, all you have to do is swap around "Date.now()" and "message.createdTimestamp" around
What you will achieve from this is:
${message.createdTimestamp - Date.now()}
I tried this method, and it worked fine. It gave me the most accurate results.
Hope this answer helped you!
Related
I'm new to node.js and discord.js, the previous version of this bot was written in discord.py (now deprecated).
This function iterates through all the webhooks (id and token) in my SQL database and sends a message to each of them. There are about 1500 of them (one for each server). I have to send a message roughly every 5 seconds. This worked perfectly in the python version, but that only had to run on about 300 guilds. I don't have the code for it anymore, but it worked the same way (all the requests were sent at once, probably about 300 requests in 500ms and this worked fine), so I don't think this is a rate limit issue.
client.on('messageCreate', (message) => {
if (message.channelId === '906659272744665139') {
console.log('found message');
const url = message.content;
var webhooklist = [];
//get all the webhooks from the database
db.prepare('SELECT * FROM webhooks').all().forEach(webhook => {
const webhookclient = new WebhookClient({id: webhook.webhookID, token: webhook.webhookToken});
webhooklist.push(webhookclient);
})
console.time('sent');
var failed = 0;
webhooklist.forEach(webhook => {
var row = new MessageActionRow()
.addComponents(
savebutton,
reportbutton
)
webhook.send({content: url, components: [row]})
.catch(err => {
if (err instanceof DiscordAPIError) {
if (err.code === 10015) {
//remove the webhook from the database
db.prepare('DELETE FROM webhooks WHERE webhookID = ?').run(webhook.id);
console.log(`Removed webhook ${webhook.id}`);
} else {
failed += 1;
console.log(err);
}
} else {
failed += 1;
}
});
});
console.timeEnd('sent');
console.log(failed);
});
}
});
The problem:
A request is sent to each webhook, however, the messages don't actually get sent half the time. For example, I'm looking at 3 different servers that this bot is in, and in one of them a message appeared and in the other two it didn't (any other combination of these outcomes also occurs, its not a problem with how the servers are set up). There are also no errors, indicated by the failed variable. To clarify, about 50% of the messages get through, but the other 50% are supposedly sent by the bot but never appear in the channel.
Things that are (most likely) NOT the issue:
-Discord Rate limits
Why: Sending messages through webhooks does not count against the bot's sent messages, and therefore will not cause rate limits (the global 50 messages per second). The only way this would cause me to be rate limited is if I was exceeding the 5/5 rate limit for each webhook individually (this is the same as what happens when you try to spam one channel).
-API rate limits
Why: API rate limits would only trip if I sent more than 10,000 invalid requests in 10 minutes. All of the requests go through, and there are no errors in the console. If I was being API rate limited, I would get completely blocked from using the discord API for up to an hour.
-I'm setting off some sort of spam protection
I've already considered this. Since most of the messages get through, I don't think this is the problem. If I did set off any filters regarding volume of requests, the requests would probably either time out, or I would get blocked.
Other notes:
-A delay between requests is not a viable solution because pretty much any amount of delay multiplied by the 1500 times this has to run would result in this function taking multiple minutes to run.
-This could be related to another issue I'm having, where buttons take a long time to respond to so the interactions will often time out before I can even run .deferReply(), however, none of the webhook requests time out (which suggests that this may not be the issue)
-my internet has seemed slow recently even though I have gigabit, but again, if internet was the issue there would be errors.
In conclusion, a large volume of webhook messages like this SHOULD work, so this issue is most likely client-side.
Found the issue: The large volume of webhook messages sent in such a short amount of time slowed my internet down to a crawl so many of the web requests ended up not going through. The way I wrote this function, those errors didn't get logged correctly. I solved this issue by using await instead of .then().
Is there a way to make this better? I'm trying to make unlimited purge command... But it seems like message.channel.messages.cache only gets message the time you used it and I don't really know how to make it better. The bot will just lag for a long time... and cycle wont break because of that.
for (let i = 1; i <= amount/100; i++) {
let messagecount = message.channel.messages.cache.size
if(messagecount<=5){
console.log("break")
break}
message.channel.bulkDelete(100)
}
}
According to the Discord API docs, you can't delete messages older than 2 weeks through the Discord API, and neither can you with more than 100 messages. This is not a limitation you should/would want to break, and you may encounter the risk of being ratelimited. Of course, you could loop this, as you tried, but the ratelimit is still here. If I were you and wanted to delete the messages this bad, I would either call the command multiple times, or loop the bulkDelete with a cooldown (2000ms would be enough, I guess?).
Hello!
So I'm currently updating my bot to version 12.3.1 of DiscordJS. Unfortunately, I got stuck on a problem that I can't really find a workaround. So, my bot has a module to filter out all of the bad words, like profanity, racial slurs, etc.
It's currently working just fine on 11.4, but cannot get it to work on 12.3.1
For some reason, the bot just does not react at all to given message.
I had two "filters" one for words, one for invites. Both of them stopped working.
bot.on('message', async message => {
// Events Listeners
if (message.author.bot) return;
if (message.channel.type === 'dm') return;
let messageArray = message.content.split(' ');
let command = messageArray[0];
let args = messageArray.slice(1);
if (!command.startsWith(prefix)) return;
let cmd = bot.commands.get(command.slice(prefix.length)) || bot.aliases.get(command.slice(prefix.length));
if (cmd) cmd.run(bot, message, args);
// First filter
var array = ['testing', 'yes', 'no'];
if (array.includes(message.content.toLocaleLowerCase())) {
message.channel.send('test')
}
// Second filter
if (message.content.includes('discord.gg/') {
message.delete()
}
}
That's the current one I found from another StackOverflow post, made 2 months ago.
Discord.js V12 Rude words filter not working
I'd really love to get some help if possible, as I can't find any reason why this feature has stopped working.
Thank you! :)
Your filters are after your command handling logic.
You have the line:
if (!command.startsWith(prefix)) return;
early in your code, and this causes message handling to terminate immediately on any message which is not a command. Due to this, the code will never reach your filters unless the message starts with your bot's prefix, at which point the message content cannot possibly be equal to any of the words and is extremely unlikely to contain discord.gg/.
Simply move your filters to the beginning of your message handler. Or alternatively separate the command handling and filter handling into separate functions, so that the return statement above only exits the command handling and the filter handling will still run.
Now i'm not that good at Javascript, i consider myself still a learner as i still make quite a lot of mistakes from time to time (not without being able to fix them shortly after) but i am at a complete loss with this Discord bot that i'm coding, now i know that a decent amount is my code but this one area of my code i believe to possibly be the culprit of my discord bot cutting off the music stream around 20 seconds before the end.
function play(guild, song) {
const serverQueue = queue.get(guild.id);
if (!song) {
serverQueue.voiceChannel.leave();
return queue.delete(guild.id);
}
const dispatcher = serverQueue.connection.play(ytdl(song.url))
.on("end", () => {
const shiffed = serverQueue.songs.shift();
if (serverQueue.loop === true) {
serverQueue.songs.push(shiffed);
};
play(guild, serverQueue.songs[0]);
})
.on("error", error => console.error(error));
dispatcher.setVolume(serverQueue.volume / 100);
I am completely at a loss as i am not that good at Javascript i would really appreciate the help!
Edit:
Should mention i seen this post:
Discord bot audio end before the song end
they have the exact same issue as me and they said they were able to fix it but i am not able to do so and i would really appreciate if someone could give me a bit of help on this
I'm trying to make a fun little discord chat bot with JavaScript and node.js and I'd like to put in a specific command without it affecting another one I already have set up.
She works wonderfully on all the servers I have her on, and I've got it set up so that when someone in the server says anything with "rei are", she responds with a constant from areResponses.
//const!!!
const areResponses = ["HELL yeah!", "Yep!", "I'm pretty sure that's true!", "I\'m not gonna put all the responses here because then it'd be too long..."];
//theres some other bot stuff (console log, now playing) under here but it isn't relevant until...
//the basics...
if (message.content.toLowerCase().includes("rei are")) {
var response = areResponses [Math.floor(Math.random()*areResponses.length)];
message.channel.send(response).then().catch(console.error);
}
What I want to have happen is, preferably, this command to function without setting off the "rei are" command I coded in.
if(message.content.toLowerCase().includes("rei are you happy")) {
message.channel.send("Yes, absolutely.");
}
As of right now, whenever I try to input the above command, it just triggers the "rei are" command AND the "rei are you happy" command with two messages...
else/if chains work beautifully for this actually!!!
if(message.content.toLowerCase().includes("rei do you like girls")) {
message.channel.send("Yes, absolutely. Girls are just... yeah...");
}
else if (message.content.toLowerCase().includes("rei are")) {
var response = areResponses [Math.floor(Math.random()*areResponses.length)];
message.channel.send(response).then().catch(console.error);
}
All you need to do is put the command that would overlap with the larger commands at the very bottom of the else if chain, and then you're good!!