-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/2, set_my_commands/3, delete_my_commands/2, get_my_commands/2, send_dice/2, get_me/1]). -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(PHL) :: {api_response, boolean(), PHL}. -spec build_url(telega@bot:bot(), binary()) -> binary(). build_url(Bot, Path) -> <<<<<<(telega@bot:get_tg_api_url(Bot))/binary, (telega@bot:get_token(Bot))/binary>>/binary, "/"/utf8>>/binary, Path/binary>>. -spec new_post_request( telega@bot:bot(), binary(), binary(), gleam@option:option(list({binary(), binary()})) ) -> telegram_api_request(). new_post_request(Bot, Path, Body, Query) -> {telegram_api_post_request, build_url(Bot, Path), Body, Query}. -spec new_get_request( telega@bot:bot(), binary(), gleam@option:option(list({binary(), binary()})) ) -> telegram_api_request(). new_get_request(Bot, Path, Query) -> {telegram_api_get_request, build_url(Bot, 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:map_error( _pipe@6, fun(_) -> <<"Failed to convert API request to HTTP request"/utf8>> end ). -spec response_decoder( fun((gleam@dynamic:dynamic_()) -> {ok, PKF} | {error, list(gleam@dynamic:decode_error())}) ) -> fun((gleam@dynamic:dynamic_()) -> {ok, api_response(PKF)} | {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, PJZ} | {error, list(gleam@dynamic:decode_error())}) ) -> {ok, PJZ} | {error, binary()}. map_resonse(Response, Result_decoder) -> _pipe = Response, _pipe@3 = gleam@result:map( _pipe, fun(Response@1) -> {response, _, _, Body} = Response@1, Decode = response_decoder(Result_decoder), _pipe@1 = gleam@json:decode(Body, Decode), _pipe@2 = gleam@result:map_error( _pipe@1, fun(_) -> <<"Failed to decode response: "/utf8, Body/binary>> end ), gleam@result:map( _pipe@2, fun(Response@2) -> erlang:element(3, Response@2) end ) end ), gleam@result:flatten(_pipe@3). -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@bot:bot()) -> {ok, gleam@http@response:response(binary())} | {error, binary()}. fetch(Api_request, Bot) -> gleam@result:'try'( api_to_request(Api_request), fun(Api_request@1) -> Retry_count = telega@bot:get_max_retry_attempts(Bot), _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@bot:bot()) -> {ok, boolean()} | {error, binary()}. set_webhook(Bot) -> Webhook_url = <<<<(telega@bot:get_server_url(Bot))/binary, "/"/utf8>>/binary, (telega@bot:get_webhook_path(Bot))/binary>>, Query = [{<<"url"/utf8>>, Webhook_url}, {<<"secret_token"/utf8>>, telega@bot:get_secret_token(Bot)}], _pipe = new_get_request(Bot, <<"setWebhook"/utf8>>, {some, Query}), _pipe@1 = fetch(_pipe, Bot), map_resonse(_pipe@1, fun gleam@dynamic:bool/1). -spec get_webhook_info(telega@bot:bot()) -> {ok, telega@model:webhook_info()} | {error, binary()}. get_webhook_info(Bot) -> _pipe = new_get_request(Bot, <<"getWebhookInfo"/utf8>>, none), _pipe@1 = fetch(_pipe, Bot), map_resonse(_pipe@1, fun telega@model:decode_webhook_info/1). -spec delete_webhook(telega@bot:bot()) -> {ok, boolean()} | {error, binary()}. delete_webhook(Bot) -> _pipe = new_get_request(Bot, <<"deleteWebhook"/utf8>>, none), _pipe@1 = fetch(_pipe, Bot), map_resonse(_pipe@1, fun gleam@dynamic:bool/1). -spec delete_webhook_and_drop_updates(telega@bot:bot()) -> {ok, boolean()} | {error, binary()}. delete_webhook_and_drop_updates(Bot) -> _pipe = new_get_request( Bot, <<"deleteWebhook"/utf8>>, {some, [{<<"drop_pending_updates"/utf8>>, <<"true"/utf8>>}]} ), _pipe@1 = fetch(_pipe, Bot), map_resonse(_pipe@1, fun gleam@dynamic:bool/1). -spec log_out(telega@bot:bot()) -> {ok, boolean()} | {error, binary()}. log_out(Bot) -> _pipe = new_get_request(Bot, <<"logOut"/utf8>>, none), _pipe@1 = fetch(_pipe, Bot), map_resonse(_pipe@1, fun gleam@dynamic:bool/1). -spec close(telega@bot:bot()) -> {ok, boolean()} | {error, binary()}. close(Bot) -> _pipe = new_get_request(Bot, <<"close"/utf8>>, none), _pipe@1 = fetch(_pipe, Bot), map_resonse(_pipe@1, fun gleam@dynamic:bool/1). -spec reply(telega@bot:context(any()), binary()) -> {ok, telega@model:message()} | {error, binary()}. reply(Ctx, Text) -> _pipe@1 = new_post_request( erlang:element(3, Ctx), <<"sendMessage"/utf8>>, begin _pipe = gleam@json:object( [{<<"chat_id"/utf8>>, gleam@json:int( erlang:element( 2, erlang:element( 8, erlang:element(3, erlang:element(2, Ctx)) ) ) )}, {<<"text"/utf8>>, gleam@json:string(Text)}] ), gleam@json:to_string(_pipe) end, none ), _pipe@2 = fetch(_pipe@1, erlang:element(3, Ctx)), map_resonse(_pipe@2, fun telega@model:decode_message/1). -spec set_my_commands( telega@bot:context(any()), list(telega@model:bot_command()), gleam@option:option(telega@model:bot_command_parameters()) ) -> {ok, boolean()} | {error, binary()}. set_my_commands(Ctx, Commands, Parameters) -> Parameters@1 = begin _pipe = gleam@option:unwrap( Parameters, telega@model:new_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( erlang:element(3, Ctx), <<"setMyCommands"/utf8>>, gleam@json:to_string(Body_json), none ), _pipe@2 = fetch(_pipe@1, erlang:element(3, Ctx)), map_resonse(_pipe@2, fun gleam@dynamic:bool/1). -spec delete_my_commands( telega@bot:context(any()), gleam@option:option(telega@model:bot_command_parameters()) ) -> {ok, boolean()} | {error, binary()}. delete_my_commands(Ctx, Parameters) -> Parameters@1 = begin _pipe = gleam@option:unwrap( Parameters, telega@model:new_botcommand_parameters() ), telega@model:encode_botcommand_parameters(_pipe) end, Body_json = gleam@json:object(Parameters@1), _pipe@1 = new_post_request( erlang:element(3, Ctx), <<"deleteMyCommands"/utf8>>, gleam@json:to_string(Body_json), none ), _pipe@2 = fetch(_pipe@1, erlang:element(3, Ctx)), map_resonse(_pipe@2, fun gleam@dynamic:bool/1). -spec get_my_commands( telega@bot:context(any()), gleam@option:option(telega@model:bot_command_parameters()) ) -> {ok, list(telega@model:bot_command())} | {error, binary()}. get_my_commands(Ctx, Parameters) -> Parameters@1 = begin _pipe = gleam@option:unwrap( Parameters, telega@model:new_botcommand_parameters() ), telega@model:encode_botcommand_parameters(_pipe) end, Body_json = gleam@json:object(Parameters@1), _pipe@1 = new_post_request( erlang:element(3, Ctx), <<"getMyCommands"/utf8>>, gleam@json:to_string(Body_json), none ), _pipe@2 = fetch(_pipe@1, erlang:element(3, Ctx)), 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( erlang:element( 2, erlang:element( 8, erlang:element(3, erlang:element(2, Ctx)) ) ) ) end ), telega@model:encode_send_dice_parameters(_pipe@1) end, _pipe@2 = new_post_request( erlang:element(3, Ctx), <<"sendDice"/utf8>>, gleam@json:to_string(Body_json), none ), _pipe@3 = fetch(_pipe@2, erlang:element(3, 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(3, Ctx), <<"getMe"/utf8>>, none), _pipe@1 = fetch(_pipe, erlang:element(3, Ctx)), map_resonse(_pipe@1, fun telega@model:decode_user/1).