skip to Main Content

I’m using python-telegram-bot library
I’m trying to create telegram bot that works like anki. It add word and translation from user to database and later ask user to write translation of the word. I’m trying to send the user words for which he should write a translation. I have problems with this.
In main.py I can’t run asynchronously application.run_polling() that run telegram bot and send_messages.setup(application.bot) from send_messages.py that run while true loop for sending words.
I was trying different ways to solve my problem like asyncio event loop or asyncio.create_task() but that don’t work.
The code below only runs send_messages.setup(application.bot) with while true loop and prevents application.run_polling() from executing

main.py

import logging
import os

import telegram.ext as tg_ext

from bot import handlers, send_messages


TOKEN = os.getenv('TOKEN')

logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO,
)
logger = logging.getLogger(__name__)


def main() -> None:
    application = tg_ext.ApplicationBuilder().token(TOKEN).build()

    handlers.setup_handlers(application)
    send_messages.setup(application.bot)

    application.run_polling()


if __name__ == '__main__':
    main()

send_messages.py

import telegram.ext as tg_ext

import asyncio

from database import db


async def send_words(bot: tg_ext.Application.bot) -> None:
    """Sends words to the user to write a translation."""
    while True:
        words = db.get_words_to_remember()

        for word in words:
            word_eng = word[0].word
            user = word[1]

            await bot.send_message(
                user.chat_id, f'Enter translation: {word_eng}')
            db.change_is_waiting(user)

        await asyncio.sleep(60)


def setup(bot: tg_ext.Application.bot) -> None:
    asyncio.run(send_words(bot))

3

Answers


  1. Chosen as BEST ANSWER

    It could be solved by telegram.ext.JobQueue that allow to perform tasks periodically with a running telegram bot
    Corrected code:
    main.py

    import logging
    import os
    
    import telegram.ext as tg_ext
    
    from bot import handlers, send_messages
    
    TOKEN = os.getenv('TOKEN')
    
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        level=logging.INFO,
    )
    logger = logging.getLogger(__name__)
    
    
    def main() -> None:
        application = tg_ext.ApplicationBuilder().token(TOKEN).build()
        job_queue = application.job_queue
    
        job_queue.run_repeating(send_messages.setup, interval=60, first=10)
        handlers.setup_handlers(application)
    
        application.run_polling()
    
    
    if __name__ == '__main__':
        main()
    

    send_messages.py

    import telegram.ext as tg_ext
    
    from database import db
    
    
    async def send_words(bot: tg_ext.Application.bot) -> None:
        """Sends words to the user to write a translation."""
        words = db.get_words_to_remember()
    
        for word in words:
            word_eng = word[0].word
            user = word[1]
    
            await bot.send_message(user.chat_id, f'Enter translation: {word_eng}')
            db.change_is_waiting(user)
    
    
    async def setup(context: tg_ext.CallbackContext) -> None:
        await send_words(context.bot)
    

  2. It is not possible to run a function which is not async concurrently in the same thread. You need to either use a different thread to run application.run_polling() or use a ThreadPoolExecutor, which in turn will use a different thread under the hood.

    See https://docs.python.org/3/library/threading.html for python threading docs and examples.

    See https://stackoverflow.com/a/51051980/4542928 for an example of ThreadPoolExecutor.

    Login or Signup to reply.
  3. IMO the overall design looks like it could be improved. Specifically I’m thinking of ConversationHandler – see also the example. This should allow you to send words to the user, wait for the translation, then send the next word etc.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search