I am migrating a long polling bot to webhook using AWS Lambda. I added '@telegraf/session/mongodb' package to store sesion info in my mongodb database.
After I finished setting up my bot everything works fine but the wizard scenes. I started debuguing and it looks like the problem is related to the session middleware. Let me show you my AWS Cloudwatch logs:
2023-12-20T14:25:29.214Z telegraf:session (642696426) did not find cached session
2023-12-20T14:25:29.214Z telegraf:session (642696426) fetching from upstream store
END RequestId: 5b8e1b5d-4e74-4691-83ac-d21894357d13
As you can see it doesn't print the following message:
2023-12-20T14:25:39.277Z telegraf:session (642696426) updating cache
That's why my code never gets into the wizard scenes. Let me show you my code because maybe I am missing something
export const message = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
const body = JSON.parse(event.body!)
console.log(body)
initBot()
await webhookHandle(body)
return { body: JSON.stringify({ message: 'Ok' }), statusCode: 200 }
} catch (error) {
return { body: JSON.stringify({ message: 'Error' }), statusCode: 500 }
}
}
webhookHandle function:
const webhookHandle = (update: Update) => {
return bot.handleUpdate(update)
}
My problem basically is that I don´t know why but the webhook handle function is not waiting for the bot to completely handle the update
I added this to my code and everything works perfectly now:
console.log('Finished webhook handle')
await sleep(150)
I added this above the return statement inside the handler function and everything worked now. But it is not an elegant solution and I added 150 ms of billing time to every request, so the question is:
Why do you think it is not waiting for the bot to handle the update?
Let me show you my initBot function
const initBot = () => {
const config = { telegram: { webhookReply: false } }
bot = new Telegraf<BotContext>(process.env.BOT_TOKEN, config)
const wizardsStage = new Scenes.Stage<any>([])
const store = Mongo({
url: process.env.DATABASE_URL,
database: process.env.SESSION_DATABASE_NAME,
})
bot.use(checkUserType)
bot.use(allowedUsers)
bot.start(ctx => {
console.log('start bot')
return ctx.reply('Menú Principal', ctx.customState.isSalesman ? SalesmanMainmenuKeyboard : MainmenuKeyboard)
})
bot.hears(UserInteractionConstants.MAIN_MENU, ctx => {
return ctx.reply('Menú Principal', ctx.customState.isSalesman ? SalesmanMainmenuKeyboard : MainmenuKeyboard)
})
initBrandsRoutes(bot, wizardsStage)
initModulesRoutes(bot, wizardsStage)
initInventoriesRoutes(bot, wizardsStage)
initProductsRoutes(bot, wizardsStage)
initCurrenciesRoutes(bot, wizardsStage)
initSalesRoutes(bot, wizardsStage)
initUsersRoutes(bot, wizardsStage)
initPaymentsRoutes(bot, wizardsStage)
initDoubtsRoutes(bot, wizardsStage)
initSettingsRoutes(bot, wizardsStage)
bot.use(session({ store }))
bot.use(wizardsStage.middleware())
}
Now inside initCurrenciesRoute function (this is just an example of how it is implemented all routes for each entity)
export const initCurrenciesRoutes = (bot: Telegraf<BotContext>, wizardsStage: WizardsStageType) => {
registerScenes(wizardsStage)
bot.hears(UserInteractionConstants.CURRENCIES_MENU, ctx => {
ctx.reply('Menú divisas', ctx.customState.isAdmin ? CurrencyActionsKeyboard : SalesmanCurrencyActionsKeyboard)
})
bot.hears(UserInteractionConstants.CURRENCY_INCREASE_ACTION, ctx => {
ctx.reply('Incrementar divisas', CurrencyIncreaseKeyboard)
})
bot.hears(UserInteractionConstants.CURRENCY_DECREASE_ACTION, ctx => {
ctx.reply('Decrementar divisas', CurrencyDecreaseKeyboard)
})
bot.hears(UserInteractionConstants.CURRENCY_EXCHANGE_ACTION, ctx => {
ctx.reply('Intercambiar divisas', CurrencyExchangeKeyboard)
})
wizardsStage.hears(UserInteractionConstants.CURRENCY_QUERY_ACTION, async ctx => {
console.log(`Inside ${UserInteractionConstants.CURRENCY_QUERY_ACTION}`);
const customState: BotState = (ctx as any).customState
if (customState.isAdmin) {
ctx.reply('Consultar divisas', CurrencyQueryKeyboard)
} else if (customState.isSalesman) {
ctx.scene.enter(SceneIDS.QUERY_CURRENCIES_SALESMAN)
}
})
bot.command('query_currencies', ctx => {
const customState: BotState = (ctx as any).customState
if (customState.isAdmin) {
ctx.reply('Consultar divisas', CurrencyQueryKeyboard)
} else if (customState.isSalesman) {
ctx.scene.enter(SceneIDS.QUERY_CURRENCIES_SALESMAN)
}
})
}
I am migrating a long polling bot to webhook using AWS Lambda. I added '@telegraf/session/mongodb' package to store sesion info in my mongodb database.
After I finished setting up my bot everything works fine but the wizard scenes. I started debuguing and it looks like the problem is related to the session middleware. Let me show you my AWS Cloudwatch logs:
As you can see it doesn't print the following message:
That's why my code never gets into the wizard scenes. Let me show you my code because maybe I am missing something
webhookHandle function:
My problem basically is that I don´t know why but the webhook handle function is not waiting for the bot to completely handle the update
I added this to my code and everything works perfectly now:
I added this above the return statement inside the handler function and everything worked now. But it is not an elegant solution and I added 150 ms of billing time to every request, so the question is:
Why do you think it is not waiting for the bot to handle the update?
Let me show you my initBot function
Now inside initCurrenciesRoute function (this is just an example of how it is implemented all routes for each entity)