Search code examples
pythonherokutelegrampython-telegram-bot

Python Telegram Bot Queue not Running on Heroku


from telegram.ext import Updater, CommandHandler
from telegram import bot, ParseMode
import os
import datetime
import pytz
import logging
from dotenv import load_dotenv
from flask import Flask
load_dotenv()

TOKEN = os.environ.get('API_KEY')
CHAT_ID = os.environ.get('CHAT_ID')
PORT = int(os.environ.get('PORT', '8443'))

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)


def daily_job(update, context):
    """ Running on Mon, Tue, Wed, Thu, Fri = tuple(range(5)) """
    sport = datetime.time(15, 12, 10, 000000, tzinfo=pytz.timezone('America/Chicago'))
    trading = datetime.time(15, 13, 10, 000000, tzinfo=pytz.timezone('America/Chicago'))
    forex = datetime.time(15, 14, 10, 000000, tzinfo=pytz.timezone('America/Chicago'))
    print("Time its supposed to post sport", sport)
    print("Time its supposed to post trading", trading)
    print("Time its supposed to post forex", forex)
    context.bot.send_message(chat_id=CHAT_ID, text='Activating daily notification!')
    context.job_queue.run_daily(purchase_forex(update, context), forex, days=tuple(range(7)), context=update)
    context.job_queue.run_daily(purchase_sports(update, context), sport, days=tuple(range(7)), context=update)
    context.job_queue.run_daily(purchase_trading(update, context), trading, days=tuple(range(7)), context=update)

def purchase_forex(update, context):
    print('running forex')
    context.bot.send_message(chat_id=CHAT_ID, text="Daily Forex", parse_mode=ParseMode.HTML)

def purchase_sports(update, context):
    print('running sports')
    context.bot.send_message(chat_id=CHAT_ID, text="Daily Text", parse_mode=ParseMode.HTML)

def purchase_trading(update, context):
    print('running trading')
    context.bot.send_message(chat_id=CHAT_ID, text="Daily Trading Text", parse_mode=ParseMode.HTML)

def error(update, context):
    """Log Errors caused by Updates."""
    logger.warning('Update "%s" caused error "%s"', update, context.error)





def main():

    u = Updater(TOKEN, use_context=True)
    u.dispatcher.add_handler(CommandHandler('start', daily_job, pass_job_queue=True))
    u.dispatcher.add_error_handler(error)

    # Start the Bot
    u.start_webhook(listen="0.0.0.0",
                          port=PORT,
                          url_path=TOKEN,
                          webhook_url="https://<appname>.herokuapp.com/" + TOKEN)


    # Run the bot until you press Ctrl-C or the process receives SIGINT,
    # SIGTERM or SIGABRT. This should be used most of the time, since
    # start_polling() is non-blocking and will stop the bot gracefully.
    u.idle()

if __name__ == '__main__':
    main()

Running this code on heroku doesn't give me what I expect

2021-09-28T20:11:36.231963+00:00 app[web.1]: Time its supposed to post forex 15:14:10 2021-09-28T20:11:36.457226+00:00 app[web.1]: running forex

But after this, it doesn't run any of the other functions, and it always posts the forex chat as soon as the /start command is done. Really, I'm looking for a way to get the /start command to run properly and to get that command to run on each reboot so I don't have to keep going back and manually doing it


Solution

  • Regarding your first problem: you're using run_daily wrong. As explained in the wiki article and in the documentation, the first argument needs to be a function. Instead you pass purchase_forex(update, context), which is the return value of purchase_forex, which is None. Also the function that you pass must accept exactly one argument, not two. Please make sure to read the wiki article, the documentation and probably also this example to better understand how the JobQueue works in PTB.

    About scheduling the jobs without a need to call the /start command: the job queue is available as u.job_queue and as u.dispatcher.job_queue (both are the same object as context.job_queue. so you can do the scheduling right in your main.


    Disclaimer: I'm currently the maintainer of python-telegram-bot.