Automatically edit last Telegram bot message after expiration period

Question:

I’m trying to figure out how I can set an "expiration timer" on a message sent by a Telegram bot, containing a few buttons.

Long story short, there’s a function which selects a random picture from a folder, then sends it to a group, and in a separate message it sends an InlineKeyboard object with some buttons for the picture to be rated

def send_stuff(context: CallbackContext):
  job = context.job

  keyboard = [ 
    [   
        InlineKeyboardButton("NEVER", callback_data="NEVER"),
        InlineKeyboardButton("UNLIKELY", callback_data="UNLIKELY")
    ],  
    [   
        InlineKeyboardButton("MEH", callback_data="MEH"),
        InlineKeyboardButton("MAYBE", callback_data="MAYBE")
    ],  
    [   
        InlineKeyboardButton("YES", callback_data="YES"),
        InlineKeyboardButton("ABSOLUTELY", callback_data="ABSOLUTELY")
    ],  
    [   
        InlineKeyboardButton("RATHER NOT SAY", callback_data="UNKNOWN")
    ]   
  ]

  reply_markup = InlineKeyboardMarkup(keyboard)

  context.bot.send_photo(job.context, photo=open(PATH+thefile, 'rb'))
  context.bot.send_message(job.context, text='RATE', reply_markup=reply_markup)

This function is being run by a run_daily job:

def start(update: Update, context: CallbackContext):
  job = context.job
  chat_id = update.message.chat_id

  context.job_queue.run_daily(
    send_stuff,
    datetime.time(13, 45, 00, 000000, tzinfo=pytz.timezone('Europe/Bucharest')),
    days=tuple(range(7)),
    context=chat_id,
    name='j1'
  )

Then there is a handler for the user input, which edits the last message sent by the bot:

def main_handler(update: Update, context: CallbackContext):
  update.callback_query.answer()

  if update.callback_query.data is not None:
    user_input = update.callback_query.data

    update.effective_message.edit_text('VERDICT: ' + user_input)

What I’m trying to do is set some kind of "expiration" on the message containing the inline keyboard buttons, such that if there is no click by a user in say… 4 hours, it automatically edits itself into something like "NO ANSWER GIVEN".

I’m not super experienced with bots, and looking through the documentation of the telegram bot libraries I have not been able to find a way to do it.

Any suggestions are appreciated.

Thanks!

Asked By: lambdacore

||

Answers:

You apparently already know how to use PTBs JobQueue, so I’m sure that you can figure out how to schedule a new job from within the send_stuff function that edits the sent message 🙂 All you need for that is context.job_queue.run_once and the return value of context.bot.send_message(job.context, text='RATE', reply_markup=reply_markup).


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

Answered By: CallMeStag

Thanks to user @CallMeStag I implemented the following solution.

def send_stuff(context: CallbackContext):
  job = context.job

  keyboard = [ 
    [   
        InlineKeyboardButton("NEVER", callback_data="NEVER"),
        InlineKeyboardButton("UNLIKELY", callback_data="UNLIKELY")
    ],  
    [   
        InlineKeyboardButton("MEH", callback_data="MEH"),
        InlineKeyboardButton("MAYBE", callback_data="MAYBE")
    ],  
    [   
        InlineKeyboardButton("YES", callback_data="YES"),
        InlineKeyboardButton("ABSOLUTELY", callback_data="ABSOLUTELY")
    ],  
    [   
        InlineKeyboardButton("RATHER NOT SAY", callback_data="UNKNOWN")
    ]   
  ]

  reply_markup = InlineKeyboardMarkup(keyboard)

  context.bot.send_photo(job.context, photo=open(PATH+thefile, 'rb'))
  # return values of send_message are saved in the 'msg' var
  msg context.bot.send_message(job.context, text='RATE', reply_markup=reply_markup)

  # the following job is created every time the send_stuff function is called
  context.job_queue.run_once(
    callback=cleanup,
    when=5,
    context=msg,
    name='cleanup'
  )

# the function called by the job
def cleanup(context: CallbackContext):
  job = context.job

  context.bot.edit_message_text(
    chat_id=job.context.chat.id,
    text='NO ANSWER PROVIDED',
    message_id=job.context.message_id
  )
Answered By: lambdacore