0

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))
2
  • maybe you should use telegram.ext.JobQueue to run function periodically without using while-loop and without sleep() Commented Sep 3, 2022 at 1:28
  • if you resolved problem then you could show your code as answer - and later you may mark you answer as accepted. This will be readable information that problem was resolved. Commented Sep 3, 2022 at 12:38

3 Answers 3

4

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)
Sign up to request clarification or add additional context in comments.

2 Comments

great example on job_queue, definitely solved my problem
Just a small note, you'd need to do: pip install "python-telegram-bot[job-queue]" Source: docs.python-telegram-bot.org/en/v21.9/… Quoting: If you want to use this class, you must install PTB with the optional requirement job-queue
0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.