Implementing a MongoDB-based persistence solution for python-telegram-bot

Hey everyone! I’m working on a Telegram bot using python-telegram-bot and I need some help. Right now I’m using ConversationHandler to manage the chat flow. But I want to make it persistent by saving the conversation state in MongoDB.

I’m using mongoengine to talk to my database. I’ve looked at the BasePersistence docs and I know I need to make a custom class called MongoPersistence. I have to override two methods:

  • get_conversations(name)
  • update_conversation(name, key, new_state)

The issue is that I don’t really know what format the dict returned by get_conversations should follow, which makes implementing update_conversation tricky.

Here’s what I’ve got so far:

from telegram.ext import BasePersistence

class MongoPersistence(BasePersistence):
    def __init__(self):
        super().__init__(store_user_data=False, store_chat_data=False, store_bot_data=False)

    def get_conversations(self, name):
        # What goes here?

    def update_conversation(self, name, key, new_state):
        # And here?

Any suggestions on how to implement these methods so that my conversation state is correctly saved to and fetched from MongoDB would be greatly appreciated. Thanks!

hey markseeker, i’ve done this before. for get_conversations, query your mongodb and make a nested dict. outer key = handler name, inner key = (user_id, chat_id) tuple, value = convo state. for update_conversation, use update_one with upsert=True. watch out for serialization issues tho. good luck!

I’ve implemented a similar MongoDB persistence solution for my Telegram bot. Here’s what worked for me:

For get_conversations, I retrieved all conversation documents from MongoDB and constructed a nested dictionary. The outer key was the handler name, and the inner key was a tuple of (user_id, chat_id). The value was the conversation state.

For update_conversation, I used mongoengine’s update_one method with upsert=True. This either updated an existing document or created a new one if it didn’t exist.

One gotcha I encountered was ensuring proper serialization of the conversation state, especially for complex objects. I ended up using pickle to serialize and deserialize the state before storing/retrieving from MongoDB.

Also, don’t forget to implement the flush() method to ensure all pending updates are written to the database when the bot shuts down. This helped prevent data loss in case of unexpected terminations.

Hope this helps point you in the right direction!

I’ve tackled this problem before, and here’s what I found effective:

For get_conversations, query your MongoDB collection for all relevant documents. Then, construct a nested dictionary where the outer key is the handler name and the inner key is a tuple of (user_id, chat_id). The value should be the conversation state.

For update_conversation, use mongoengine’s update_one method with upsert=True. This will update an existing document or create a new one if it doesn’t exist.

A word of caution: be careful with serialization, especially for complex objects. You might want to consider using something like pickle or JSON for serializing and deserializing the state before storing or retrieving from MongoDB.

Don’t forget to implement the flush() method to ensure all pending updates are written to the database when your bot shuts down. This can help prevent data loss in case of unexpected terminations.

Lastly, make sure to handle any potential database errors gracefully to avoid crashing your bot during runtime.