Open wisienak opened 1 month ago
I added to the event a console.log message to debug how many this event is firing, but i only got one log but 3 messages on channel. Where can be problem?
after that time, does the event always fire X times?
if so, that sounds like the code attaching a listener is called multiple times over the session, which would cause the event callback to be execute X times, where X is the amount of listeners attached.
you can check for that with console.log(client.listenerCount("guildMemberAdd"))
after that time, does the event always fire X times? if so, that sounds like the code attaching a listener is called multiple times over the session, which would cause the event callback to be execute X times, where X is the amount of listeners attached. you can check for that with
console.log(client.listenerCount("guildMemberAdd"))
everytime event got fired 1 time, and this method shows 1 after debug
For reference, discord.js retries requests (by default, up to 3 times ^1): https://github.com/discordjs/discord.js/blob/d22b55fc829226fbfded9c38e7d33160efce67ea/packages/rest/src/lib/handlers/Shared.ts#L77-L84
But only on timeout (by default 15 seconds^2) and ECONNRESET[^3]: https://github.com/discordjs/discord.js/blob/d22b55fc829226fbfded9c38e7d33160efce67ea/packages/rest/src/lib/utils/utils.ts#L86-L97
Since ECONNRESET
implies Discord didn't process the request, this can then only mean a timeout, specifically, that your application has sent the request correctly, but due to Internet's nature, the response can fail make its way back to your server, making your app unable acknowledge the response, timing out as a result.
To work around this, we have two options:
Setting options.rest.timeout
to change the amount of time discord.js will wait before attempting a retry. This may increase (slightly) the chances of receiving a request, but it will also block any subsequent requests during the duration. For 3 retries at 15 seconds, a request can block for as long as 45 seconds.
Another solution, released by Discord rather recently, is to set enforceNonce
to true
and generate a random nonce
. The combination of the two fields allows Discord to deduplicate the request and therefore even if the library successfully sent 3 requests, Discord would take the first and ignore the rest, sending only one message.
To generate a random nonce
reliably, you can use SnowflakeUtil
:
import { SnowflakeUtil } from 'discord.js';
const nonce = SnowflakeUtil.generate();
[^3]: The ECONRESET error means that the server unexpectedly closed the connection and the request to the server was not fulfilled.
For reference, discord.js retries requests (by default, up to 3 times 1):
But only on timeout (by default 15 seconds2) and ECONNRESET3:
Since
ECONNRESET
implies Discord didn't process the request, this can then only mean a timeout, specifically, that your application has sent the request correctly, but due to Internet's nature, the response can fail make its way back to your server, making your app unable acknowledge the response, timing out as a result.To work around this, we have two options:
Setting
options.rest.timeout
to change the amount of time discord.js will wait before attempting a retry. This may increase (slightly) the chances of receiving a request, but it will also block any subsequent requests during the duration. For 3 retries at 15 seconds, a request can block for as long as 45 seconds.Another solution, released by Discord rather recently, is to set
enforceNonce
totrue
and generate a randomnonce
. The combination of the two fields allows Discord to deduplicate the request and therefore even if the library successfully sent 3 requests, Discord would take the first and ignore the rest, sending only one message.To generate a random
nonce
reliably, you can useSnowflakeUtil
:import { SnowflakeUtil } from 'discord.js'; const nonce = SnowflakeUtil.generate();
Footnotes
- https://github.com/discordjs/discord.js/blob/d22b55fc829226fbfded9c38e7d33160efce67ea/packages/rest/src/lib/utils/constants.ts#L24 ↩
- https://github.com/discordjs/discord.js/blob/d22b55fc829226fbfded9c38e7d33160efce67ea/packages/rest/src/lib/utils/constants.ts#L25 ↩
- The ECONRESET error means that the server unexpectedly closed the connection and the request to the server was not fulfilled. ↩
After add snowflakeutil
import { SnowflakeUtil } from 'discord.js';
const nonce = SnowflakeUtil.generate();
this problem still appears
Show how you implemented this nonce into your code please.
like this
import { SnowflakeUtil } from 'discord.js';
const nonce = SnowflakeUtil.generate();
You said that already.
How did you implement that into your code? What did you do with that variable? Where did you put it? Etc.
i just use require to SnowflakeUtil and create this nonce
variable with generate method inside index.js thats it
So you aren't actually using that variable anywhere?
oh sorry, i read kyranet comment again and i did mistake, i need to enable enforceNonce and use nonce generated string to use this option recommended by discord.
ok so i implemented it like this
require('dotenv').config();
const { EmbedBuilder, AttachmentBuilder, SnowflakeUtil } = require('discord.js');
module.exports = (member) => {
const attachment = new AttachmentBuilder('images/welcome.png', { name: 'welcome.png' });
const embed = new EmbedBuilder()
.setColor(0x169C9C)
.setDescription(`Welcome<@${member.user.id}>! (${member.user.username})\nSome text!\nSome text.\nSome text:\n<#${process.env.RULES_CHANNEL}>\n<#${process.env.TICKETS_CHANNEL}>`)
.setThumbnail(`https://cdn.discordapp.com/avatars/${member.user.id}/${member.user.avatar}.png`)
.setImage('attachment://welcome.png');
const nonce = SnowflakeUtil.generate();
const channel = member.guild.channels.cache.get(process.env.WELCOME_CHANNEL);
channel.send({ embeds: [embed], files: [attachment], enforceNonce: true, nonce: nonce });
};
i think it should work now
huh something dont work
/home/bot2/node_modules/discord.js/src/structures/MessagePayload.js:132
throw new DiscordjsRangeError(ErrorCodes.MessageNonceType);
^
RangeError [MessageNonceType]: Message nonce must be an integer or a string.
}
Because SnowflakeUtil.generate()
gives you a BigInt. You‘d need to .toString()
it when passing in your send.
Because
SnowflakeUtil.generate()
gives you a BigInt. You‘d need to.toString()
it when passing in your send.
yes i did it now, thanks for reply
Which package is this bug report for?
discord.js
Issue description
After bot being not used for example 2 hours, after firing (joining from another account) to the discord server, bot send embed message twice. And it only appears when the bot is not used for a while, when i work with bot and restart him often, this problem doesn't appear.
It it matter bot is in screen everytime. No any errors in output.
Code sample
Versions
node.js version: v20.13.1 discord.js version: 14.15.2
OS version: Ubuntu 20.04 LTS x86_64 (this problem also appears on my PC when i host it locally)
Issue priority
High (immediate attention needed)
Which partials do you have configured?
No Partials
Which gateway intents are you subscribing to?
Guilds, GuildMembers, GuildMessages, GuildMessageReactions, MessageContent
I have tested this issue on a development release
No response