olexnzarov / telegraf-session-mongodb

MongoDB session middleware for Telegraf
25 stars 14 forks source link

Cannot store session object when using await #3

Closed expelliamus closed 4 years ago

expelliamus commented 4 years ago

Hi,

first of all thanks for this library. I have configured the session in this way:

const Telegraf = require('telegraf');
const I18n = require('telegraf-i18n');
const path = require('path');
const { TelegrafMongoSession } = require('telegraf-session-mongodb');
const { MongoClient } = require('mongodb');

// Middlewares
const { MainMenu } = require('../middlewares/menu/main-menu');

class MembershipBot {

    constructor(token) {
        this.bot = new Telegraf(token);

        this.bot.catch(error => {
            console.error(`Bot error: ${error}`);
        });
    }

    async init() {
        let session;
        this.bot.use((...args) => session.middleware(...args));

        MongoClient.connect(process.env.DATABASE_URL, {
            useNewUrlParser: true,
            useUnifiedTopology: true
        }).then((client) => {
            const db = client.db();
            session = new TelegrafMongoSession(db, {
                collectionName: 'sessions',
                sessionName: 'session'
            });
            this.bot.startPolling();
        });
    }

    async start() {
        await this.init();
        this.bot.startPolling();
    }
}

exports.MembershipBot = MembershipBot;

I'm facing a strange issue when I do this:

ctx.session.optionsMessage = await ctx.replyWithMarkdown(
        ctx.i18n.t('planMenu'),
        Markup.inlineKeyboard(buttons, { columns: 1 }).extra(),
    );

essentially the session doesn't store the optionsMessage object, but if I do this:

ctx.session.test = true;

I can see the record stored in data, I did something wrong or there is an issue?

thanks.

olexnzarov commented 4 years ago

Hey.

This package is designed to work with async handlers. Problem is definitely not in there.

I think it does not work in your case because of the middleware order. Middlewares should be added before the handlers in order for them to work, like this:

bot.on(...) // sessions will not work here
bot.use(...); // let's say this is our session middleware
bot.on(...); // sessions will work here
bot.command(...); // sessions will work here

Here's an example that I just tested:

bot.use(async (_, next) => {
  console.log('middleware before');
  await next();
});

bot.command('/test', () => console.log('command'));

bot.use(async (_, next) => {
  console.log('middleware after');
  await next();
});

Output was:

middleware before
command

I hope this helped you.

Sxela commented 3 years ago

Hi! I'm having the same issue here, and bot.on() is placed after bot.use(session(db)). For example, i have this code:

bot.on('text', async (ctx) => {
      ctx.session.msg0 = 'wowow'
      ctx.reply('woot').then(res=>ctx.session.msg1 = res)
      const msg = await ctx.reply('woot')

      ctx.session.msg2 = msg.message_id
      ctx.session.msg3 = 'wowow'
    })

Only msg0 is saved to the db, other 3 are accessible in this function's scope, but not afterwards.