visciang / telegram

Telegram library for the Elixir language
MIT License
204 stars 27 forks source link

`Telegram.ChatBot` behaviour doesn't currently handle inline mode #176

Open lnr0626 opened 1 week ago

lnr0626 commented 1 week ago

Howdy,

I'm working on a bot where I'd like to take advantage of the semi-persistent state provided by Telegram.ChatBot but also support inline mode. Currently when I enable inline mode for the bot it just discards all of the updates that telegram sends because there's no chat id associated with them. I'm happy to take a stab at adding support for this, but wanted to run the concept by you before writing code.

Currently Telegram.Bot.ChatBot.Chat.Session.Server emits the following logs when an inline mode query is typed in some chat:

[debug] process_update: %{"inline_query" => %{"chat_type" => "private", "from" => <user-object that's sending the request>, "id" => "<query-identifier>", "offset" => "<offset for results to send>", "query" => "<query-text>"}, "update_id" => <update-id>}
[info] Dropped update without chat <same object as above>

There's some more info here: https://core.telegram.org/bots/api#inline-mode

At a high level, I feel like it could be reasonable to treat the inline query similar to a chat - i.e. spin up a new instance of the bot, call init, handle_update, etc. like it already does; and just treat the inline query identifier as the chat id instead of trying to find a chat.

Once again, I'm happy to throw up a PR with some changes to support this just wanted to get on the same page as you first :)

visciang commented 1 week ago

Hey @lnr0626, got the point.

Yes, I think your analysis is correct and points in the right direction.

I'm thinking about the inline query interaction. Let me explain, but bear with me if I'm a bit rusty on some telegram features.

If my memories are right inline queries are just a simple "one-off" requests-response interaction with a BOT, so they do not establish a real chat but just ask for something and get an answer. This is my feeling given there isn't a chat it in the protocol, but just an inline query id to reply back from the BOT.

If this is right then this one-off interaction with a statefull bot could be modeled as a transient chat that lives just that interaction. It means, as you said, spawning a new chat session to answer the inline query and then release the session immediately.

May I ask you to dig a bit into it to validate that? One interesting test could be to send an inline query to a NON-statefull BOT (it should answer) then send another inline query from the same private chat and checks the id of the two requests. They should have different ids.

lnr0626 commented 1 week ago

That's correct - each inline query gets it's own id, for example:

@bot_name t
@bot_name th
@bot_name the

results in 3 different ids. This is also true when the bot paginates it's responses (i.e. it answers with a non-empty next offset and telegram handles iterating through the pages to display all results, each of the follow-on requests will have a different query id)

Given that, modelling it as a transient chat makes sense to me