Reputation: 121
I successfully open a web app using an in-line button from my Telegram bot. When the "work" is complete in the web app, it persists the data to a DB via an API call and then closes itself (the web app) using Telegram.WebApp.close(). Upon the closing of the Web app my bot then needs to automatically refresh some information shown in the private chat from where the web app was launched.
Question: How can my bot know that the web app has been closed? Or how can I send a "notification" from the web app to the bot to let it know that it should refresh the data.
Supposedly I should be using answerWebAppQuery but search as I may, I cannot find any examples of how to use this. The closest example I could find is "In our case, we need to send data via answerWebAppQuery, without any servers, using the bot API: https://api.telegram.org/${yourBotToken}/answerWebAppQuery, options. You will need query_id from initData to send data using this approach.". I tried it and it just gives a 404 error.
I would appreciate any help or pointers to where I can find the info I need.
Upvotes: 6
Views: 4499
Reputation: 117
Here's how I worked around it using a MySQL database, as such a basic thing seems impossible using only the Telegram bot API. My app already requires a database so this does not cause significant overhead.
cursor.lastrowid
:query = "INSERT INTO HITS (user_id) VALUES (%s)"
cursor.execute(query, (user_id))
conn.commit()
hit_id = (cursor.lastrowid)
As far as race conditions are concerned, to the best of my knowledge cursor.lastrowid
should be thread-safe and specific to the cursor used to execute the insert operation. So, even if another session adds a hit concurrently, cursor.lastrowid
should return the correct ID for the respective thread or process.
btn_message = await update.message.reply_text(
"example text",
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
"example button",
web_app=WebAppInfo(url=f"https://mywebsite.com/app?hit_id={hit_id}")
)
]
]
),
)
query = "UPDATE HITS SET message_id = %s, chat_id = %s WHERE user_id = %s AND hit_id = %s"
cursor.execute(query, (btn_message.message_id, btn_message.chat_id, user_id, hit_id))
conn.commit()
@app.route("/end_interaction", methods=["POST"])
async def end_interaction():
hit_id = request.json["hit_id"]
user_id = request.json["user_id"]
query = (
"SELECT chat_id, message_id FROM HITS WHERE user_id = %s AND hit_id = %s"
)
cursor.execute(query, (user_id, hit_id))
chat_id, message_id = cursor.fetchone()
bot = Bot(TELEGRAM_BOT_TOKEN)
await bot.edit_message_text(chat_id=chat_id, message_id=message_id, text="Done")
await bot.edit_message_reply_markup(
chat_id=chat_id, message_id=message_id, reply_markup=None
)
@0stone0 's answer is not entirely relevant as popupClosed
is for extra pop-ups over the web app, and also it's on the web app side, so it wouldn't be possible to use it anyway as the web app is closed.
Upvotes: 0
Reputation: 44172
The answerWebAppQuery
is ment to "set the result of an interaction with a Web App", you won't be able to use that to detect closing the webApp.
Looking at the Telegram WebApp change-log, Bot API 6.2
implements the popupClose
event:
August 12, 2022
Bot API 6.2
- Added the field
isClosingConfirmationEnabled
and the methodsenableClosingConfirmation
, disableClosingConfirmation,showPopup
,showAlert
,showConfirm
to the class WebApp.- Added the field
is_premium
to the classWebAppUser
.- Added the event
popupClosed
.
The Events available for Web Apps shows the following:
popupClosed
Bot API 6.2+
Occurrs when the opened popup is closed.
eventHandler
receives an object with the single fieldbutton_id
– the value of the fieldid
of the pressed button. If no buttons were pressed, the fieldbutton_id
will benull
.
So you should be able to capture the close of the WebApp, and then trigger the bot to refresh the data
Upvotes: 0