Packages
ex_gram
0.50.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.58.0
0.57.0
0.56.1
0.56.0
0.55.1
0.55.0
0.54.0
0.53.0
0.52.2
0.52.1
0.52.0
0.51.1
0.51.0
0.50.2
0.50.1
0.50.0
0.41.0
0.40.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.1
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.1
0.8.0
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.5.0-rc6
0.5.0-rc5
0.5.0-rc4
0.5.0-rc3
0.5.0-rc2
Telegram Bot API low level and framework
Current section
Files
Jump to
Current section
Files
lib/ex_gram/updates/webhook.ex
defmodule ExGram.Updates.Webhook do
@moduledoc """
Updates implementation that uses webhook method
"""
use GenServer
require Logger
@posible_updates Map.keys(%ExGram.Model.Update{})
|> List.delete(:__struct__)
|> List.delete(:update_id)
def update(update, token_hash) do
token_hash
|> process_name()
|> GenServer.cast({:update, update})
end
def start_link({:bot, pid, :token, token}) do
name =
token_hash(token)
|> process_name()
GenServer.start_link(__MODULE__, {:ok, pid, token}, name: name)
end
def init({:ok, pid, token}) do
set_webhook(token)
{:ok, {pid, token}}
end
def handle_cast({:update, update}, {pid, token}) do
GenServer.call(pid, {:update, update})
{:noreply, {pid, token}}
end
def handle_info(unknown_message, state) do
Logger.debug("Webhook updates received an unknown message #{inspect(unknown_message)}")
{:noreply, state}
end
defp process_name(token_hash), do: Module.concat(__MODULE__, token_hash)
defp token_hash(token) do
:crypto.hash(:sha, token)
|> Base.url_encode64(padding: true)
end
defp set_webhook(token) do
config = ExGram.Config.get(:ex_gram, :webhook)
params = webhook_params(config)
case config[:url] do
webhook_url when is_binary(webhook_url) ->
case ExGram.set_webhook(
"https://#{webhook_url}/telegram/#{token_hash(token)}",
[{:token, token} | params]
) do
{:ok, _} -> nil
{:error, error} -> Logger.error("Could not set the webhook: #{inspect(error)}")
end
nil ->
Logger.warning(
"The webhook_url is not set in the configuration. Please manually set the webhook using this method: https://core.telegram.org/bots/api#setwebhook"
)
end
end
defp webhook_params(_, params \\ [])
defp webhook_params([], params), do: params
defp webhook_params([{:certificate, path} | tl], params) do
case File.read(path) do
{:ok, _} ->
webhook_params(tl, [{:certificate, {:file, path}} | params])
{:error, reason} ->
Logger.error("Could not read the certificate file from #{path}: #{inspect(reason)}")
webhook_params(tl, params)
end
end
defp webhook_params([{:url, _} | tl], params), do: webhook_params(tl, params)
defp webhook_params([{:max_connections, max_connections} | tl], params)
when is_integer(max_connections) do
webhook_params(tl, [{:max_connections, max_connections} | params])
end
defp webhook_params([{:max_connections, max_connections} | tl], params) do
webhook_params(tl, [{:max_connections, String.to_integer(max_connections)} | params])
end
defp webhook_params([{:allowed_updates, allowed_updates} | tl], params)
when is_list(allowed_updates) do
allowed_updates =
Enum.map(allowed_updates, fn update ->
if String.to_atom(update) in @posible_updates do
update
else
Logger.error("The update #{update} is not a valid update")
nil
end
end)
|> Enum.reject(&is_nil/1)
webhook_params(tl, [{:allowed_updates, allowed_updates} | params])
end
@secret_token_length 1..256
@secret_token_format ~r/^[A-Za-z0-9_-]+$/
defp webhook_params([{:secret_token, secret_token} | tl], params) do
with true <- String.length(secret_token) in @secret_token_length,
true <- String.match?(secret_token, @secret_token_format) do
webhook_params(tl, [{:secret_token, secret_token} | params])
else
_ ->
Logger.error(
"The secret_token must be between 1 to 256 characters. Only characters A-Z, a-z, 0-9, _ and - are allowed."
)
webhook_params(tl, params)
end
end
defp webhook_params([{key, value} | tl], params),
do: webhook_params(tl, [{key, value} | params])
end