Packages
ex_gram
0.7.1
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/adapter/http.ex
defmodule ExGram.Adapter.Http do
@behaviour ExGram.Adapter
use Maxwell.Builder, ~w(get post)a
@base_url "https://api.telegram.org"
middleware(Maxwell.Middleware.BaseUrl, ExGram.Config.get(:ex_gram, :base_url, @base_url))
middleware(Maxwell.Middleware.Headers, %{"Content-Type" => "application/json"})
middleware(Maxwell.Middleware.Opts, connect_timeout: 5000, recv_timeout: 30000)
middleware(Maxwell.Middleware.Json,
encode_func: &ExGram.Adapter.Http.custom_encode/1,
decode_func: &ExGram.Adapter.Http.custom_decode/1
)
adapter(Maxwell.Adapter.Hackney)
def custom_encode(x), do: ExGram.Encoder.encode(x)
def custom_decode(x), do: ExGram.Encoder.decode(x, keys: :atoms)
@impl ExGram.Adapter
def request(verb, path, body) do
where = where_body(verb)
new()
|> put_path(path)
|> add_body(where, body)
|> do_request(verb)
|> post_request()
end
defp post_request({:ok, %Maxwell.Conn{status: status} = conn}) when status in 200..299 do
{:ok, Maxwell.Conn.get_resp_body(conn, :result)}
end
defp post_request({:ok, conn}) do
body = Maxwell.Conn.get_resp_body(conn) |> encode()
{:error, %ExGram.Error{code: :response_status_not_match, message: body}}
end
defp post_request({:error, reason, conn}) do
error = Maxwell.Error.exception({__MODULE__, reason, conn})
{:error, %ExGram.Error{code: error.status, message: error.message}}
end
defp post_request({:error, reason}) do
{:error, %ExGram.Error{code: reason}}
end
defp do_request(conn, verb) do
apply(ExGram.Adapter.Http, verb, [conn])
end
defp add_body(conn, where, body) do
apply(Maxwell.Conn, where, [conn, encode_body(body)])
end
defp where_body(:post), do: :put_req_body
defp where_body(_), do: :put_query_string
defp encode_body(body) do
if is_map(body) do
body
|> Enum.map(fn {key, value} -> {key, encode(value)} end)
|> Enum.into(%{})
else
body
end
end
defp encode(%{__struct__: _} = x) do
x
|> Map.from_struct()
|> filter_map
|> ExGram.Encoder.encode!()
end
defp encode(x) when is_map(x) or is_list(x), do: ExGram.Encoder.encode!(x)
defp encode(x), do: x
defp filter_map(%{__struct__: _} = m) do
m |> Map.from_struct() |> filter_map
end
defp filter_map(m) when is_map(m) do
m
|> Enum.filter(fn {_key, value} -> not is_nil(value) end)
|> Enum.map(fn {key, value} ->
cond do
is_list(value) ->
{key, Enum.map(value, &filter_map/1)}
is_map(value) ->
{key, filter_map(value)}
true ->
{key, value}
end
end)
|> Enum.into(%{})
end
defp filter_map(m) when is_list(m), do: Enum.map(m, &filter_map/1)
defp filter_map(m), do: m
end