'Why can't telegram bot work with many users at the same time on Node.js?
I am writing a telegram bot in JavaScript. I ran into a problem, if several users write to the bot at the same time, then all messages in each chat are mixed. The main task is to create a separate listening channel for each user. So that many users can access the bot at the same time. The bot has the main file bot.js and profile.js where the listening logic is implemented. Help solve this problem.
bot.js
bot.on('message', async (msg) => {
const profileForm = new ProfileForm(bot, msg.chat.id);
profileForm.filter('phoneNumber', async (value) => {
const profileExists = await Phones.findOne({where: {phoneNumber: value}});
if (profileExists) {
return false;
}
return true;
});
const profileData = await profileForm.listen();
if (!profileData) {
return;
}
console.log(profileData);
const user = await User.create(profileData);
console.log(user);
})
profile.js
const options = require('../../Middleware/options')
class ProfileForm {
constructor(bot, chatId) {
this.bot = bot
this.chatId = chatId
this.filters = {};
}
filter(field, fn) {
if (!this.filters[field]) {
this.filters[field] = [];
}
this.filters[field].push(fn);
}
async checkFilter(field, value) {
if (!this.filters[field]) {
return false;
}
for (const fn of this.filters[field]) {
try {
const result = await fn(value);
if (!result) {
throw(`Filter blocked for field: ${field} with value: ${value}`);
}
}
catch (error) {
console.error(error.message);
return false;
}
}
return true;
}
async listen() {
return new Promise(async (resolve, reject) => {
const fields = [
{
name: 'username',
message: `message`
},
{
name: 'lastname',
message: `message`
}
]
const data = {}
let step = 0
let allow = false;
await this.sendMessage(fields[step].message, fields[step].options);
const profileFormHandler = async (msg) => {
let {text} = msg
text = text.trim();
data[fields[step].name] = text
allow = await this.checkFilter(fields[step].name, text);
if (allow) {
this.bot.off('message', profileFormHandler);
if (fields[step].stopMessage) {
await this.sendMessage(fields[step].stopMessage);
}
return resolve(null);
}
step++
if (step === fields.length) {
this.bot.off('message', profileFormHandler);
return resolve(data);
}
await this.sendMessage(fields[step].message, fields[step].options);
}
this.bot.on('message', profileFormHandler);
})
}
async sendMessage(message, options) {
return this.bot.sendMessage(this.chatId, message, options);
}
}
module.exports = ProfileForm;
Solution 1:[1]
Javascript is single-threaded programming language. So your bot is accepting all the incoming requests into the same single thread and same single context.
I think you have to create a "state", that will look like a key-value object where key is chatId and value is current_state of the chatId. So it will help you to keep track of multiple chats at the same time.
For example you are expecting some user to enter their phone number, it means you have to define it in the following way:
globalState[chatId] = States.ENTER_PHONE_NUMBER;
So whenever user sends any message to your bot, you have to check the current state of the chat with the user and act accordingly. If there's no state, it means that this is new user and new chat.
I am not sure that this is the best possible solution, but I like it and I use it in all of my bots.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dzhakhar Ukhaev |
