Current section

Files

Jump to
telega src telega@api.erl
Raw

src/telega@api.erl

-module(telega@api).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([set_webhook/1, get_webhook_info/1, delete_webhook/1, delete_webhook_and_drop_updates/1, log_out/1, close/1, reply_with_parameters/2, reply/2, reply_with_markup/3, set_my_commands/3, delete_my_commands/2, get_my_commands/2, send_dice/2, get_me/1, answer_callback_query/2, edit_message_text/2]).
-export_type([telegram_api_request/0, api_response/1]).
-type telegram_api_request() :: {telegram_api_post_request,
binary(),
binary(),
gleam@option:option(list({binary(), binary()}))} |
{telegram_api_get_request,
binary(),
gleam@option:option(list({binary(), binary()}))}.
-type api_response(TKF) :: {api_response, boolean(), TKF}.
-spec build_url(telega@config:config(), binary()) -> binary().
build_url(Configuration, Path) ->
<<<<<<(telega@config:get_tg_api_url(Configuration))/binary,
(telega@config:get_token(Configuration))/binary>>/binary,
"/"/utf8>>/binary,
Path/binary>>.
-spec new_post_request(
telega@config:config(),
binary(),
binary(),
gleam@option:option(list({binary(), binary()}))
) -> telegram_api_request().
new_post_request(Config, Path, Body, Query) ->
{telegram_api_post_request, build_url(Config, Path), Body, Query}.
-spec new_get_request(
telega@config:config(),
binary(),
gleam@option:option(list({binary(), binary()}))
) -> telegram_api_request().
new_get_request(Config, Path, Query) ->
{telegram_api_get_request, build_url(Config, Path), Query}.
-spec set_query(
gleam@http@request:request(binary()),
gleam@option:option(list({binary(), binary()}))
) -> gleam@http@request:request(binary()).
set_query(Api_request, Query) ->
case Query of
none ->
Api_request;
{some, Query@1} ->
gleam@http@request:set_query(Api_request, Query@1)
end.
-spec api_to_request(telegram_api_request()) -> {ok,
gleam@http@request:request(binary())} |
{error, binary()}.
api_to_request(Api_request) ->
_pipe@6 = case Api_request of
{telegram_api_get_request, Url, Query} ->
_pipe = gleam@http@request:to(Url),
_pipe@1 = gleam@result:map(
_pipe,
fun(_capture) ->
gleam@http@request:set_method(_capture, get)
end
),
gleam@result:map(
_pipe@1,
fun(_capture@1) -> set_query(_capture@1, Query) end
);
{telegram_api_post_request, Url@1, Body, Query@1} ->
_pipe@2 = gleam@http@request:to(Url@1),
_pipe@3 = gleam@result:map(
_pipe@2,
fun(_capture@2) ->
gleam@http@request:set_body(_capture@2, Body)
end
),
_pipe@4 = gleam@result:map(
_pipe@3,
fun(_capture@3) ->
gleam@http@request:set_method(_capture@3, post)
end
),
_pipe@5 = gleam@result:map(
_pipe@4,
fun(_capture@4) ->
gleam@http@request:set_header(
_capture@4,
<<"Content-Type"/utf8>>,
<<"application/json"/utf8>>
)
end
),
gleam@result:map(
_pipe@5,
fun(_capture@5) -> set_query(_capture@5, Query@1) end
)
end,
gleam@result:replace_error(
_pipe@6,
<<"Failed to convert API request to HTTP request"/utf8>>
).
-spec response_decoder(
fun((gleam@dynamic:dynamic_()) -> {ok, TNG} |
{error, list(gleam@dynamic:decode_error())})
) -> fun((gleam@dynamic:dynamic_()) -> {ok, api_response(TNG)} |
{error, list(gleam@dynamic:decode_error())}).
response_decoder(Result_decoder) ->
gleam@dynamic:decode2(
fun(Field@0, Field@1) -> {api_response, Field@0, Field@1} end,
gleam@dynamic:field(<<"ok"/utf8>>, fun gleam@dynamic:bool/1),
gleam@dynamic:field(<<"result"/utf8>>, Result_decoder)
).
-spec map_resonse(
{ok, gleam@http@response:response(binary())} | {error, binary()},
fun((gleam@dynamic:dynamic_()) -> {ok, TNA} |
{error, list(gleam@dynamic:decode_error())})
) -> {ok, TNA} | {error, binary()}.
map_resonse(Response, Result_decoder) ->
_pipe = Response,
_pipe@4 = gleam@result:map(
_pipe,
fun(Response@1) -> _pipe@1 = response_decoder(Result_decoder),
_pipe@2 = gleam@json:decode(erlang:element(4, Response@1), _pipe@1),
_pipe@3 = gleam@result:replace_error(
_pipe@2,
<<"Failed to decode response: "/utf8,
(erlang:element(4, Response@1))/binary>>
),
gleam@result:map(
_pipe@3,
fun(Response@2) -> erlang:element(3, Response@2) end
) end
),
gleam@result:flatten(_pipe@4).
-spec send_with_retry(gleam@http@request:request(binary()), integer()) -> {ok,
gleam@http@response:response(binary())} |
{error, gleam@dynamic:dynamic_()}.
send_with_retry(Api_request, Retries) ->
Response = gleam@httpc:send(Api_request),
case Retries of
0 ->
Response;
_ ->
case Response of
{ok, Response@1} ->
case erlang:element(2, Response@1) of
429 ->
telega@log:warn(
<<"Telegram API throttling, HTTP 429 'Too Many Requests'"/utf8>>
),
gleam_erlang_ffi:sleep(1000),
send_with_retry(Api_request, Retries - 1);
_ ->
{ok, Response@1}
end;
{error, _} ->
gleam_erlang_ffi:sleep(1000),
send_with_retry(Api_request, Retries - 1)
end
end.
-spec fetch(telegram_api_request(), telega@config:config()) -> {ok,
gleam@http@response:response(binary())} |
{error, binary()}.
fetch(Api_request, Configuration) ->
gleam@result:'try'(
api_to_request(Api_request),
fun(Api_request@1) ->
Retry_count = telega@config:get_max_retry_attempts(Configuration),
_pipe = send_with_retry(Api_request@1, Retry_count),
gleam@result:map_error(
_pipe,
fun(Error) ->
telega@log:info(
<<"Api request failed with error:"/utf8,
(gleam@string:inspect(Error))/binary>>
),
_pipe@1 = gleam@dynamic:string(Error),
gleam@result:unwrap(
_pipe@1,
<<"Failed to send request"/utf8>>
)
end
)
end
).
-spec set_webhook(telega@config:config()) -> {ok, boolean()} | {error, binary()}.
set_webhook(Config) ->
Webhook_url = <<<<(telega@config:get_server_url(Config))/binary, "/"/utf8>>/binary,
(telega@config:get_webhook_path(Config))/binary>>,
Query = [{<<"url"/utf8>>, Webhook_url},
{<<"secret_token"/utf8>>, telega@config:get_secret_token(Config)}],
_pipe = new_get_request(Config, <<"setWebhook"/utf8>>, {some, Query}),
_pipe@1 = fetch(_pipe, Config),
map_resonse(_pipe@1, fun gleam@dynamic:bool/1).
-spec get_webhook_info(telega@config:config()) -> {ok,
telega@model:webhook_info()} |
{error, binary()}.
get_webhook_info(Config) ->
_pipe = new_get_request(Config, <<"getWebhookInfo"/utf8>>, none),
_pipe@1 = fetch(_pipe, Config),
map_resonse(_pipe@1, fun telega@model:decode_webhook_info/1).
-spec delete_webhook(telega@config:config()) -> {ok, boolean()} |
{error, binary()}.
delete_webhook(Config) ->
_pipe = new_get_request(Config, <<"deleteWebhook"/utf8>>, none),
_pipe@1 = fetch(_pipe, Config),
map_resonse(_pipe@1, fun gleam@dynamic:bool/1).
-spec delete_webhook_and_drop_updates(telega@config:config()) -> {ok, boolean()} |
{error, binary()}.
delete_webhook_and_drop_updates(Config) ->
_pipe = new_get_request(
Config,
<<"deleteWebhook"/utf8>>,
{some, [{<<"drop_pending_updates"/utf8>>, <<"true"/utf8>>}]}
),
_pipe@1 = fetch(_pipe, Config),
map_resonse(_pipe@1, fun gleam@dynamic:bool/1).
-spec log_out(telega@config:config()) -> {ok, boolean()} | {error, binary()}.
log_out(Config) ->
_pipe = new_get_request(Config, <<"logOut"/utf8>>, none),
_pipe@1 = fetch(_pipe, Config),
map_resonse(_pipe@1, fun gleam@dynamic:bool/1).
-spec close(telega@config:config()) -> {ok, boolean()} | {error, binary()}.
close(Config) ->
_pipe = new_get_request(Config, <<"close"/utf8>>, none),
_pipe@1 = fetch(_pipe, Config),
map_resonse(_pipe@1, fun gleam@dynamic:bool/1).
-spec reply_with_parameters(
telega@config:config(),
telega@model:send_message_parameters()
) -> {ok, telega@model:message()} | {error, binary()}.
reply_with_parameters(Config, Parameters) ->
Body_json = telega@model:encode_send_message_parameters(Parameters),
_pipe = new_post_request(
Config,
<<"sendMessage"/utf8>>,
gleam@json:to_string(Body_json),
none
),
_pipe@1 = fetch(_pipe, Config),
map_resonse(_pipe@1, fun telega@model:decode_message/1).
-spec reply(telega@bot:context(any()), binary()) -> {ok, telega@model:message()} |
{error, binary()}.
reply(Ctx, Text) ->
reply_with_parameters(
erlang:element(4, Ctx),
telega@model:new_send_message_parameters(
{stringed, erlang:element(2, Ctx)},
Text
)
).
-spec reply_with_markup(
telega@bot:context(any()),
binary(),
telega@model:reply_markup()
) -> {ok, telega@model:message()} | {error, binary()}.
reply_with_markup(Ctx, Text, Reply_markup) ->
reply_with_parameters(
erlang:element(4, Ctx),
begin
_pipe = telega@model:new_send_message_parameters(
{stringed, erlang:element(2, Ctx)},
Text
),
telega@model:set_send_message_parameters_reply_markup(
_pipe,
Reply_markup
)
end
).
-spec set_my_commands(
telega@config:config(),
list(telega@model:bot_command()),
gleam@option:option(telega@model:bot_command_parameters())
) -> {ok, boolean()} | {error, binary()}.
set_my_commands(Config, Commands, Parameters) ->
Parameters@1 = begin
_pipe = gleam@option:unwrap(
Parameters,
telega@model:default_botcommand_parameters()
),
telega@model:encode_botcommand_parameters(_pipe)
end,
Body_json = gleam@json:object(
[{<<"commands"/utf8>>,
gleam@json:array(
Commands,
fun(Command) ->
gleam@json:object(
[{<<"command"/utf8>>,
gleam@json:string(
erlang:element(2, Command)
)},
{<<"description"/utf8>>,
gleam@json:string(
erlang:element(3, Command)
)} |
Parameters@1]
)
end
)}]
),
_pipe@1 = new_post_request(
Config,
<<"setMyCommands"/utf8>>,
gleam@json:to_string(Body_json),
none
),
_pipe@2 = fetch(_pipe@1, Config),
map_resonse(_pipe@2, fun gleam@dynamic:bool/1).
-spec delete_my_commands(
telega@config:config(),
gleam@option:option(telega@model:bot_command_parameters())
) -> {ok, boolean()} | {error, binary()}.
delete_my_commands(Config, Parameters) ->
Parameters@1 = begin
_pipe = gleam@option:unwrap(
Parameters,
telega@model:default_botcommand_parameters()
),
telega@model:encode_botcommand_parameters(_pipe)
end,
Body_json = gleam@json:object(Parameters@1),
_pipe@1 = new_post_request(
Config,
<<"deleteMyCommands"/utf8>>,
gleam@json:to_string(Body_json),
none
),
_pipe@2 = fetch(_pipe@1, Config),
map_resonse(_pipe@2, fun gleam@dynamic:bool/1).
-spec get_my_commands(
telega@config:config(),
gleam@option:option(telega@model:bot_command_parameters())
) -> {ok, list(telega@model:bot_command())} | {error, binary()}.
get_my_commands(Config, Parameters) ->
Parameters@1 = begin
_pipe = gleam@option:unwrap(
Parameters,
telega@model:default_botcommand_parameters()
),
telega@model:encode_botcommand_parameters(_pipe)
end,
Body_json = gleam@json:object(Parameters@1),
_pipe@1 = new_post_request(
Config,
<<"getMyCommands"/utf8>>,
gleam@json:to_string(Body_json),
none
),
_pipe@2 = fetch(_pipe@1, Config),
map_resonse(_pipe@2, fun telega@model:decode_bot_command/1).
-spec send_dice(
telega@bot:context(any()),
gleam@option:option(telega@model:send_dice_parameters())
) -> {ok, telega@model:message()} | {error, binary()}.
send_dice(Ctx, Parameters) ->
Body_json = begin
_pipe = Parameters,
_pipe@1 = gleam@option:lazy_unwrap(
_pipe,
fun() ->
telega@model:new_send_dice_parameters(
{stringed, erlang:element(2, Ctx)}
)
end
),
telega@model:encode_send_dice_parameters(_pipe@1)
end,
_pipe@2 = new_post_request(
erlang:element(4, Ctx),
<<"sendDice"/utf8>>,
gleam@json:to_string(Body_json),
none
),
_pipe@3 = fetch(_pipe@2, erlang:element(4, Ctx)),
map_resonse(_pipe@3, fun telega@model:decode_message/1).
-spec get_me(telega@bot:context(any())) -> {ok, telega@model:user()} |
{error, binary()}.
get_me(Ctx) ->
_pipe = new_get_request(erlang:element(4, Ctx), <<"getMe"/utf8>>, none),
_pipe@1 = fetch(_pipe, erlang:element(4, Ctx)),
map_resonse(_pipe@1, fun telega@model:decode_user/1).
-spec answer_callback_query(
telega@bot:context(any()),
telega@model:answer_callback_query_parameters()
) -> {ok, boolean()} | {error, binary()}.
answer_callback_query(Ctx, Parameters) ->
Body_json = telega@model:encode_answer_callback_query_parameters(Parameters),
_pipe = new_post_request(
erlang:element(4, Ctx),
<<"answerCallbackQuery"/utf8>>,
gleam@json:to_string(Body_json),
none
),
_pipe@1 = fetch(_pipe, erlang:element(4, Ctx)),
map_resonse(_pipe@1, fun gleam@dynamic:bool/1).
-spec edit_message_text(
telega@bot:context(any()),
telega@model:edit_message_text_parameters()
) -> {ok, telega@model:edit_message_text_result()} | {error, binary()}.
edit_message_text(Ctx, Parameters) ->
Body_json = telega@model:encode_edit_message_text_parameters(Parameters),
_pipe = new_post_request(
erlang:element(4, Ctx),
<<"editMessageText"/utf8>>,
gleam@json:to_string(Body_json),
none
),
_pipe@1 = fetch(_pipe, erlang:element(4, Ctx)),
map_resonse(_pipe@1, fun telega@model:decode_edit_message_text_result/1).