rockneurotiko/ex_gram

[Bot answer] Token not included in api requests for answers

thehabbos007 opened this issue · 4 comments

I set up a test project https://github.com/thehabbos007/exgram_error_example
The test project listens for a /start command, and needs a TELEGRAM_TOKEN environment variable at runtime.

The problem seems to be, that when I call answer in a given context from a message, the following error occurs (note, I use tesla with gun)

20:43:20.777 [info]  POST https://api.telegram.org/bot/sendMessage -> 404 (163.433 ms)
20:43:20.777 [debug]
>>> REQUEST >>>
Content-Type: application/json
%{chat_id: 392938231, text: "Hi!"}

<<< RESPONSE <<<
%{description: "Not Found", error_code: 404, ok: false}

The message is sent, but the token is not included in the post request.

With some tinkering around, it seems that moving the token fetching down in the macro fixes the problem, since some tokens are filtered away.

token = ExGram.Token.fetch(ops)
debug = Keyword.get(ops, :debug, false)
# Remove not valids
ops = Keyword.take(ops, unquote(opt_par))

However, this will likely cause problems.

I believe this is caused by the bot being registered in the bot registry without a token, so it matches on this case

{nil, bot} ->
registry = Keyword.get(ops, :registry, @registry)
[{_, token} | _] = Registry.lookup(registry, bot)
token

and then returns no actual token.

To confirm, looking into the registry returns

iex(1)> Registry.lookup(Registry.ExGram, :bot_example)
[{#PID<0.229.0>, nil}]

So I think this can be traced all the way back to how each bot is registered in the supervision tree, if a user of the framework does not specify a token, this will end up failing (i am assuming).

Maybe we should try to think up some defaults? Perhaps checking if the token is set in the init of the bot supervisor and default it to the config if not? I am still a newbie in elixir, so I'm open to ideas 😄

All the methods on ExGram can be called in three ways:

  • ExGram.get_me() -> This will use the token configured in config :ex_gram, token: "token"
  • ExGram.get_me(token: token) -> This will use that token
  • ExGram.get_me(bot: :my_bot) -> This will search in the registry the token for the bot

The "fast" responses that uses the context (answer, answer_callback, edit, ...) uses the third way, so it will try to use the bot's token.

To specify the bot's token, you have to specify it at startup (https://github.com/thehabbos007/exgram_error_example/blob/master/lib/bot_example/application.ex#L7)

In your example it would be something like:

token = ExGram.Config.get(:ex_gram, :token)
children = [
  ExGram,
  {BotExample.Bot, [method: :polling, token: token]}
]

Why whithout that was working some methods? If no token specified, the first get_me, delete_webhook and the get_updates will be called without anything, so it uses the token configured. If you specify the token on startup it will use that token.

It was a problem of documentation (probably)?
Maybe the token should be mandatory?

Ah, yes I see thank you!
I think as long as it is clear we should supply a token in startup, that should be fine.

I don't think there's a problem in the documentation, iy was just me that thought that if i specify the token in config, i shouldn't have to specify it at startup.

Should we log an error in the case that no token can be fetched?

Sure! I'll add a log when trying to fetch a token by bot name and there are no token configured.

The reasoning behind specify the token per bot on startup is that you can have multiple bots running on the same node 😄

Yes, and that makes perfect sense. Running a single bot shouldn't have influence over that functionality :)