Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Telegram sendMessage limit handling #4

Closed
iMasoud opened this issue Dec 28, 2016 · 6 comments
Closed

Telegram sendMessage limit handling #4

iMasoud opened this issue Dec 28, 2016 · 6 comments

Comments

@iMasoud
Copy link

iMasoud commented Dec 28, 2016

Hi,

This module is very interesting to me. But I'm wondering if it's able to handle sendMessage limits of telegram?
I mean if I call sendMessage 31 times in a second, will it manage to execute first 30 in same second and execute the 31st in next?

I have the same question about two other limits of telegram which are; sending only one message per second to same chat id and sending 20 messages per second (at most) to same group.

@kamikazechaser
Copy link

Hi,

This module does not feature a rate-limiting feature yet. That means you will have to implemement it yourself for now. Telegram claims a max of 30 calls/sec however you can get 429 errors below or above that value.
Tgfancy features a Order sending feature that calls a method in the order you define (see example).
Also note that all Telegram methods are subject to rate limiting.

In the meanwhile we can wait to see if @GochoMugo will add a new rate-limiting fanciness!

@GochoMugo
Copy link
Owner

@iMasoud: Thanks for your interest in this library. Hope it helps you build better bots.
@kamikazechaser: Thanks for addressing the issue.

We can add this new fanciness:

rate-limiting:

On rate-limit errors, we receive error_code set to 429 (see Telegram docs). We are sure that our request had no effect on the implied state between the Telegram servers and the bot. We are free (and actually recommended) to repeat our request at a later time.

Currently, node-telegram-bot-api does passes us a generic Error object in the .catch() handler of our request promises. We need to parse the error's message to figure out the error code. (We need to improve the library to pass a proper error object, with important information readily available for consumers! A PR be expected there!)

My approach in implementing this feature:

  • wrap our requests in a promise that, on error, only rejects if the error is not due to rate-limiting. Otherwise, we wait for the recommended time before retrying the request.
  • we should keep retrying the request until we succeed or a maximum number of retries is exceeded, whichever comes first
  • this should be completely transparent and the user should not even realize we hit a rate-limiting issue (unless max retries!)

You (@kamikazechaser) might realize that I have decided not to use a rate-limiting library, like node-rate-limiter or pothole. I feel that would add too much complexity in the implementation. However, after the above suggested implementation has been worked out, we will consider including such capabilities within!

I will work on this asap!

@iMasoud
Copy link
Author

iMasoud commented Dec 28, 2016

@kamikazechaser: Thanks for your reply.
What did you mean by that (Also note that all Telegram methods are subject to rate limiting.) part? I didn't see any limits on telegram bot API docs except for sendMessage method.

@GochoMugo: Your concept sounds great. I can't wait to see it implemented!
But until then, would you suggest me to use one of those two mentioned modules to avoid hitting telegram limits? Or you would suggest me to make some kind of deligate myself for it?

@kamikazechaser
Copy link

@iMasoud The findings were made by the writer of GroupButler, who also was among the first to unofficially document the various error codes not found in the official docs.

C.C @RememberTheAir

@GochoMugo
Copy link
Owner

So, in the mean time, you might use pothole, in this way:

const pothole = require("pothole");

// creating a rate-limiter to use for the Telegram Bot API
pothole.add("TelegramBotAPI", {
    window: {
        size: 30,           // 30 requests...
        length: 1000,       // ...in 1 second (1000 ms)
    },
});


// the function that you will use instead of 'TelegramBot#sendMessage()'
function sendMessage(chatId, text) {
    return new Promise(function(resolve, reject) {
        pothole.enqueue("TelegramBotAPI", function() {
            bot.sendMessage(chatId, text).then(resolve).catch(reject);
        });
    });
}

// sending a message
sendMessage(chatId, text);

Note that the above solution does not take into account any other
requests made against the API, such as bot.sendPhoto(), etc.

GochoMugo added a commit that referenced this issue Dec 30, 2016
Feature:

    Please read the README.md for documentation on this
    feature.

References:

    * Feature request: #4
@GochoMugo
Copy link
Owner

Rate-limiting fanciness added in v0.7.0.

See the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants