izy521 / discord.io

A small, single-file library for creating DiscordApp clients from Node.js or the browser
https://discord.gg/0MvHMfHcTKVVmIGP
MIT License
535 stars 154 forks source link

Bot is Timing Out (keepalive) #73

Closed Zamiell closed 8 years ago

Zamiell commented 8 years ago

Hello,

I just started recently using the discord.io framework, which is pretty great, so thanks for writing it!

One problem that I've immediately noticed is that, after 24+ hours, my bot will stop receiving messages from the Discord server. The only fix is that I completely restart the bot, which reconnects to the server, and all is well.

Not 100% sure why this is, but I suspect that it the keep-alive function (at line 1013?) is not robust enough. Has anyone else experienced this problem? Furthermore, can the bot be configured to automatically reconnect if this occurs?

tags: keep-alive, keepalive, timeout, heartbeat, phantom disconnect

izy521 commented 8 years ago

Robust enough? The keep alive code hasn't changed since it was created (aside from being moved to support API v5). I'm sure many users have had their bots on for more than 24 hours. Perhaps you're being disconnected for another reason. Are you not using the disconnect event?

bot.on('disconnect', function(erMsg, code) {});
Zamiell commented 8 years ago

Ah, okay. Thanks izy. I wasn't using the disconnect event. Is it as simple as adding the following to my bot?

// Automatically reconnect if the bot disconnects due to inactivity
bot.on('disconnect', function(erMsg, code) {
    console.log('----- Bot disconnected from Discord with code', code, 'for reason:', erMsg, '-----');
    bot.connect();
});
izy521 commented 8 years ago

Yes, that's all.

The error message is only applicable for application-level codes (4000-4999), but any other code is a standardized error code. The next time you disconnect, it should tell you why.

Discord uses Cloudflare for their WebSockets. Often it will disconnect with a general (1001) code meaning Cloudflare has to restart to push updates and it will come back immediately. Perhaps that's what you're seeing.

Zamiell commented 8 years ago

Ok. From what I understand, this is a relatively normal / common thing. Some follow up questions:

1) Why doesn't the framework abstract away automatically reconnecting after a timeout, similar to other JavaScript frameworks like node-irc (https://github.com/martynsmith/node-irc) and tmi-js for Twitch (https://github.com/tmijs/tmi.js)? In other words, is it unreasonable in this case to expect my above code snippet be handled automatically by the framework without me having to include this code snippet into every Discord bot that I write with Discord.IO?

(perhaps having an autoreconnect option that defaults to true to handle both use cases:)

var bot = new discord.Client({
    token: 'asdfghjkl',
    autoreconnect: false,
});

2) Since this is probably code that should be in every single bot written with Discord.IO (?), should my above code snippet be included in the example code located in the various READMEs?

https://github.com/izy521/discord.io (the main page of the repository) https://github.com/izy521/discord.io/wiki (the wiki) https://www.gitbook.com/book/izy521/discord-io/details (the GitBooks documentation)

3) Furthermore, in the docs for events (https://github.com/izy521/discord.io/wiki/2.-Events), it mentions the disconnect event, but has no explanation for it. You should probably include a sentence or two that explains the this will be triggered on more than just manual disconnects. Something along the lines of:

"This event will trigger whenever you call the disconnect() function, but also if your bot disconnects due to an error or a timeout. It is important to use this event, since Discord uses Cloudflare for their WebSockets, and often it will disconnect with a general (1001) code meaning Cloudflare has to restart to push updates and it will come back immediately.

izy521 commented 8 years ago

1). Although in recent times I've been asked to include it (which I'm still thinking about doing), it's never been an issue with the users. Generally they all realized that using Client#connect() in the disconnect event was what they needed to do.

I wouldn't say it's unreasonable, however there are many reasons your bot could disconnect (invalid session, rate-limited, general disconnection) and I'm not going to define logic in the back-end to pick and choose which are the right codes to reconnect on. If I add that autoreconnect property, it's going to attempt to reconnect on all. I figured simply firing the event was good enough, and letting the library user choose how they want to handle it.

2). The event and code to reconnect (albeit commented) is in the full example.js file (https://github.com/izy521/discord.io/blob/master/example.js) but the quick-start/inline examples lack it (and a few other events and helper functions). I don't see a reason to increase the documentation size with all of the code from the full example.

3). The Github documentation is deprecated and is only there for legacy reasons, I'm moving to Gitbook and I'm still populating it even right now (even though I have to actually go right now).

Zamiell commented 8 years ago

Ok, thanks again izy. Going forward, make sure that the documentation in GitBooks talks about this stuff and the other documentation is deleted.

cobrafast commented 7 years ago

I seem to be having the same problem; the bot randomly timeouts and goes offline after a seemingly random amount of inactive time. I am using the disconnect event with a connect() call, but even calling connect() manually has no effect as the bot remains offline. The bot, however, remains useable via another protocol so it should be a discord-specific problem.

Next im going to try to periodically call setPresence() as a hackish keepalive and see if that helps.