-
Notifications
You must be signed in to change notification settings - Fork 9
Description
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)
}
})
}