Skip to content

Commit

Permalink
Merge pull request #9 from NivEz/long-polling
Browse files Browse the repository at this point in the history
Long polling
  • Loading branch information
NivEz committed Sep 23, 2023
2 parents 7571a3a + c4fca3a commit abf3ea5
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Lightweight Telegram API framework for Node.js
✅ Buttons support (inline keyboard, reply keyboard and remove reply keyboard)
<br>
✅ Secret token support
<br>
✅ Long polling support

## Getting started

Expand Down Expand Up @@ -68,6 +70,16 @@ Then you can execute the following command:
npx set-webhook
```

### Long polling

If you prefer to use long polling method over creating a server with webhook you can use the `startLongPolling` method instead of `createServer`.
<br>
The method accepts `pollingDelay` - a number that represents milliseconds (must be at least 50ms).
<br>
You can view an example of long polling usage [here](https://github.com/NivEz/telenode/tree/main/examples/long-polling.js).

Note that long polling is usually not recommended and webhook is preferred for most use cases.

### Usage

```
Expand Down
29 changes: 29 additions & 0 deletions examples/long-polling.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const Telenode = require('../src/bot');

const bot = new Telenode({
apiToken: process.env.API_TOKEN,
});

bot.startLongPolling({ pollingDelay: 2000 }); // default is 1000ms

// The usage is the same as using the webhook

bot.onTextMessage('hello', async messageBody => {
await bot.sendReplyKeyboard(
messageBody.chat.id,
'Click on one of the keyboard buttons...',
inlineKeyboard,
true,
);
});

const inlineKeyboard = [
[
{
text: 'Hi!',
},
{
text: 'Bye!',
},
],
];
10 changes: 10 additions & 0 deletions src/bot.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { runServer } = require('./server');
const { longPoll } = require('./longPolling');
const axios = require('axios');

class Telenode {
Expand All @@ -19,7 +20,16 @@ class Telenode {
runServer(this, port);
}

startLongPolling({ pollingDelay } = {}) {
longPoll({
bot: this,
pollingDelay,
url: this.#baseUrl,
});
}

telenodeHandler(reqBody, headersSecretToken, unauthorizedCallback) {
// Note that if using long polling the secret token and unauthorizedCallback are irrelevant
if (this.#secretToken && this.#secretToken !== headersSecretToken) {
if (unauthorizedCallback) {
unauthorizedCallback();
Expand Down
39 changes: 39 additions & 0 deletions src/longPolling.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const axios = require('axios');

const longPoll = async ({ bot, pollingDelay = 1000, url }) => {
if (pollingDelay < 50) {
throw new Error('Polling delay must be at least 50ms');
}
let offset = 0;
while (true) {
try {
const res = await axios.get(url + '/getUpdates', {
params: { offset },
});
const updates = res.data.result;
updates.forEach(update => {
bot.telenodeHandler(update);
offset = update.update_id + 1;
});
} catch (err) {
if (err.name === 'AxiosError') {
console.error(
'Request error in long polling:\n',
err.message,
'\n',
err.response.data,
);
} else {
// If the handlers throw an error and it is not async, it will be caught here
console.error(err);
}
}
await sleep(pollingDelay);
}
};

module.exports = {
longPoll,
};

const sleep = ms => new Promise(r => setTimeout(r, ms));

0 comments on commit abf3ea5

Please sign in to comment.