-module(telega). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([is_webhook_path/2, is_secret_token_valid/2, get_api_config/1, new/4, handle_all/2, wait_any/2, handle_command/3, wait_command/3, handle_commands/3, wait_commands/3, handle_text/2, wait_text/2, handle_hears/3, wait_hears/3, handle_callback_query/3, wait_callback_query/3, with_catch_handler/2, log_context/3, with_session_settings/4, set_drop_pending_updates/2, set_max_connections/2, set_ip_address/2, set_allowed_updates/2, set_certificate/2, init/1, init_nil_session/1, handle_update/2]). -export_type([telega/2, telega_builder/2]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -opaque telega(AOXF, AOXG) :: {telega, telega@internal@config:config(), telega@model:user(), gleam@erlang@process:subject(telega@bot:bot_message())} | {gleam_phantom, AOXF, AOXG}. -opaque telega_builder(AOXH, AOXI) :: {telega_builder, telega@internal@config:config(), list(telega@bot:handler(AOXH, AOXI)), gleam@option:option(telega@bot:session_settings(AOXH, AOXI)), gleam@option:option(gleam@erlang@process:subject(telega@bot:bot_message())), gleam@option:option(fun((telega@bot:context(AOXH, AOXI), AOXI) -> {ok, nil} | {error, AOXI})), gleam@option:option(boolean()), gleam@option:option(integer()), gleam@option:option(binary()), gleam@option:option(list(binary())), gleam@option:option(telega@model:file())}. -file("src/telega.gleam", 48). ?DOC( " Check if a path is the webhook path for the bot.\n" "\n" " Useful if you plan to implement own adapter.\n" ). -spec is_webhook_path(telega(any(), any()), binary()) -> boolean(). is_webhook_path(Telega, Path) -> erlang:element(3, erlang:element(2, Telega)) =:= Path. -file("src/telega.gleam", 55). ?DOC( " Check if a secret token is valid.\n" "\n" " Useful if you plan to implement own adapter.\n" ). -spec is_secret_token_valid(telega(any(), any()), binary()) -> boolean(). is_secret_token_valid(Telega, Token) -> erlang:element(4, erlang:element(2, Telega)) =:= Token. -file("src/telega.gleam", 60). ?DOC(" Helper to get the config for API requests.\n"). -spec get_api_config(telega(any(), any())) -> telega@client:telegram_client(). get_api_config(Telega) -> erlang:element(5, erlang:element(2, Telega)). -file("src/telega.gleam", 65). ?DOC(" Create a new Telega instance.\n"). -spec new(binary(), binary(), binary(), gleam@option:option(binary())) -> telega_builder(any(), any()). new(Token, Server_url, Webhook_path, Secret_token) -> Url = telega@internal@utils:normalize_url(Server_url), Webhook_path@1 = telega@internal@utils:normalize_webhook_path(Webhook_path), {telega_builder, telega@internal@config:new(Token, Url, Webhook_path@1, Secret_token), [], none, none, none, none, none, none, none, none}. -file("src/telega.gleam", 89). ?DOC(" Handles all messages.\n"). -spec handle_all( telega_builder(AOYA, AOYB), fun((telega@bot:context(AOYA, AOYB)) -> {ok, telega@bot:context(AOYA, AOYB)} | {error, AOYB}) ) -> telega_builder(AOYA, AOYB). handle_all(Builder, Handler) -> _record = Builder, {telega_builder, erlang:element(2, _record), [{handle_all, Handler} | erlang:element(3, Builder)], erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 100). ?DOC( " Stops bot message handling from current chat and waits for any message.\n" "\n" " See [conversation]\n" ). -spec wait_any( telega@bot:context(AOYL, AOYM), fun((telega@bot:context(AOYL, AOYM)) -> {ok, telega@bot:context(AOYL, AOYM)} | {error, AOYM}) ) -> {ok, telega@bot:context(AOYL, AOYM)} | {error, any()}. wait_any(Ctx, Continue) -> telega@bot:wait_handler(Ctx, {handle_all, Continue}). -file("src/telega.gleam", 109). ?DOC(" Handles a specific command.\n"). -spec handle_command( telega_builder(AOYW, AOYX), binary(), fun((telega@bot:context(AOYW, AOYX), telega@update:command()) -> {ok, telega@bot:context(AOYW, AOYX)} | {error, AOYX}) ) -> telega_builder(AOYW, AOYX). handle_command(Builder, Command, Handler) -> _record = Builder, {telega_builder, erlang:element(2, _record), [{handle_command, Command, Handler} | erlang:element(3, Builder)], erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 124). ?DOC( " Stops bot message handling from current chat and waits for a specific command.\n" "\n" " See [conversation]\n" ). -spec wait_command( telega@bot:context(AOZH, AOZI), binary(), fun((telega@bot:context(AOZH, AOZI), telega@update:command()) -> {ok, telega@bot:context(AOZH, AOZI)} | {error, AOZI}) ) -> {ok, telega@bot:context(AOZH, AOZI)} | {error, any()}. wait_command(Ctx, Command, Continue) -> telega@bot:wait_handler(Ctx, {handle_command, Command, Continue}). -file("src/telega.gleam", 134). ?DOC(" Handles multiple commands.\n"). -spec handle_commands( telega_builder(AOZS, AOZT), list(binary()), fun((telega@bot:context(AOZS, AOZT), telega@update:command()) -> {ok, telega@bot:context(AOZS, AOZT)} | {error, AOZT}) ) -> telega_builder(AOZS, AOZT). handle_commands(Builder, Commands, Handler) -> _record = Builder, {telega_builder, erlang:element(2, _record), [{handle_commands, Commands, Handler} | erlang:element(3, Builder)], erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 149). ?DOC( " Stops bot message handling from current chat and waits for a specific command.\n" "\n" " See [conversation]\n" ). -spec wait_commands( telega@bot:context(APAE, APAF), list(binary()), fun((telega@bot:context(APAE, APAF), telega@update:command()) -> {ok, telega@bot:context(APAE, APAF)} | {error, APAF}) ) -> {ok, telega@bot:context(APAE, APAF)} | {error, any()}. wait_commands(Ctx, Commands, Continue) -> telega@bot:wait_handler(Ctx, {handle_commands, Commands, Continue}). -file("src/telega.gleam", 159). ?DOC(" Handles text messages.\n"). -spec handle_text( telega_builder(APAQ, APAR), fun((telega@bot:context(APAQ, APAR), binary()) -> {ok, telega@bot:context(APAQ, APAR)} | {error, APAR}) ) -> telega_builder(APAQ, APAR). handle_text(Builder, Handler) -> _record = Builder, {telega_builder, erlang:element(2, _record), [{handle_text, Handler} | erlang:element(3, Builder)], erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 170). ?DOC( " Stops bot message handling from current chat and waits for a text message.\n" "\n" " See [conversation]\n" ). -spec wait_text( telega@bot:context(APBB, APBC), fun((telega@bot:context(APBB, APBC), binary()) -> {ok, telega@bot:context(APBB, APBC)} | {error, APBC}) ) -> {ok, telega@bot:context(APBB, APBC)} | {error, any()}. wait_text(Ctx, Continue) -> telega@bot:wait_handler(Ctx, {handle_text, Continue}). -file("src/telega.gleam", 179). ?DOC(" Handles messages that match the given `Hears`.\n"). -spec handle_hears( telega_builder(APBM, APBN), telega@bot:hears(), fun((telega@bot:context(APBM, APBN), binary()) -> {ok, telega@bot:context(APBM, APBN)} | {error, APBN}) ) -> telega_builder(APBM, APBN). handle_hears(Builder, Hears, Handler) -> _record = Builder, {telega_builder, erlang:element(2, _record), [{handle_hears, Hears, Handler} | erlang:element(3, Builder)], erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 194). ?DOC( " Stops bot message handling from current chat and waits for a message that matches the given `Hears`.\n" "\n" " See [conversation]\n" ). -spec wait_hears( telega@bot:context(APBX, APBY), telega@bot:hears(), fun((telega@bot:context(APBX, APBY), binary()) -> {ok, telega@bot:context(APBX, APBY)} | {error, APBY}) ) -> {ok, telega@bot:context(APBX, APBY)} | {error, any()}. wait_hears(Ctx, Hears, Continue) -> telega@bot:wait_handler(Ctx, {handle_hears, Hears, Continue}). -file("src/telega.gleam", 205). ?DOC( " Handles messages from inline keyboard callback.\n" "\n" " See [conversation]\n" ). -spec handle_callback_query( telega_builder(APCD, APCE), telega@bot:callback_query_filter(), fun((telega@bot:context(APCD, APCE), binary(), binary()) -> {ok, telega@bot:context(APCD, APCE)} | {error, APCE}) ) -> telega_builder(APCD, APCE). handle_callback_query(Builder, Filter, Handler) -> _record = Builder, {telega_builder, erlang:element(2, _record), [{handle_callback_query, Filter, Handler} | erlang:element(3, Builder)], erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 219). ?DOC( " Wait for a callback query and continue with the given function.\n" "\n" " See [conversation]\n" ). -spec wait_callback_query( telega@bot:context(APCJ, APCK), telega@bot:callback_query_filter(), fun((telega@bot:context(APCJ, APCK), binary(), binary()) -> {ok, telega@bot:context(APCJ, APCK)} | {error, APCK}) ) -> {ok, telega@bot:context(APCJ, APCK)} | {error, any()}. wait_callback_query(Ctx, Filter, Continue) -> telega@bot:wait_handler(Ctx, {handle_callback_query, Filter, Continue}). -file("src/telega.gleam", 231). ?DOC( " Set a catch handler for all handlers.\n" "\n" " If handler returns `Error`, the chat instance will be stopped and the error will be logged\n" " The default handler is `fn(_) -> Ok(Nil)`, which will do nothing if handler returns an error\n" ). -spec with_catch_handler( telega_builder(APCP, APCQ), fun((telega@bot:context(APCP, APCQ), APCQ) -> {ok, nil} | {error, APCQ}) ) -> telega_builder(APCP, APCQ). with_catch_handler(Builder, Catch_handler) -> _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), {some, Catch_handler}, erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 239). ?DOC(" Log the message and error message if the handler fails.\n"). -spec log_context( telega@bot:context(APCW, APCX), binary(), fun(() -> {ok, telega@bot:context(APCW, APCX)} | {error, APCX}) ) -> {ok, telega@bot:context(APCW, APCX)} | {error, APCX}. log_context(Ctx, Prefix, Handler) -> Id = telega@internal@utils:random_string(5), Prefix@1 = <<<<<<<<"["/utf8, Prefix/binary>>/binary, ":"/utf8>>/binary, Id/binary>>/binary, "] "/utf8>>, telega@internal@log:info( <<<>/binary, (telega@bot:update_to_string(erlang:element(3, Ctx)))/binary>> ), Start_time = gleam@time@timestamp:system_time(), Result = begin _pipe = Handler(), gleam@result:map_error( _pipe, fun(E) -> telega@internal@log:error( <<<>/binary, (gleam@string:inspect(E))/binary>> ), E end ) end, End_time = gleam@time@timestamp:system_time(), Time = begin _pipe@1 = Start_time, _pipe@2 = gleam@time@timestamp:difference(_pipe@1, End_time), _pipe@3 = gleam@time@duration:to_seconds(_pipe@2), gleam_stdlib:float_to_string(_pipe@3) end, telega@internal@log:info( <<<<<>/binary, Time/binary>>/binary, " seconds"/utf8>> ), Result. -file("src/telega.gleam", 269). ?DOC(" Construct a session settings.\n"). -spec with_session_settings( telega_builder(APQD, APQE), fun((binary(), APQD) -> {ok, APQD} | {error, APQE}), fun((binary()) -> {ok, gleam@option:option(APQD)} | {error, APQE}), fun(() -> APQD) ) -> telega_builder(APQD, APQE). with_session_settings(Builder, Persist_session, Get_session, Default_session) -> _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), {some, {session_settings, Persist_session, Get_session, Default_session}}, erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 304). ?DOC(" Set the drop pending updates flag as set webhook parameter.\n"). -spec set_drop_pending_updates(telega_builder(APDO, APDP), boolean()) -> telega_builder(APDO, APDP). set_drop_pending_updates(Builder, Drop_pending_updates) -> _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), {some, Drop_pending_updates}, erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 312). ?DOC(" Set the max connections as set webhook parameter.\n"). -spec set_max_connections(telega_builder(APDT, APDU), integer()) -> telega_builder(APDT, APDU). set_max_connections(Builder, Max_connections) -> _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), {some, Max_connections}, erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 320). ?DOC(" Set the ip address as set webhook parameter.\n"). -spec set_ip_address(telega_builder(APDY, APDZ), binary()) -> telega_builder(APDY, APDZ). set_ip_address(Builder, Ip_address) -> _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), {some, Ip_address}, erlang:element(10, _record), erlang:element(11, _record)}. -file("src/telega.gleam", 328). ?DOC(" Set the allowed updates as set webhook parameter.\n"). -spec set_allowed_updates(telega_builder(APED, APEE), list(binary())) -> telega_builder(APED, APEE). set_allowed_updates(Builder, Allowed_updates) -> _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), {some, Allowed_updates}, erlang:element(11, _record)}. -file("src/telega.gleam", 336). ?DOC(" Set the certificate as set webhook parameter.\n"). -spec set_certificate(telega_builder(APEJ, APEK), telega@model:file()) -> telega_builder(APEJ, APEK). set_certificate(Builder, Certificate) -> _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), {some, Certificate}}. -file("src/telega.gleam", 346). ?DOC( " Initialize a Telega instance.\n" " This function should be called **only** after all handlers are added to the builder.\n" " It will set the webhook and start handling messages.\n" ). -spec init(telega_builder(any(), any())) -> {ok, telega(any(), any())} | {error, telega@error:telega_error()}. init(Builder) -> gleam@result:'try'( telega@api:set_webhook( erlang:element(5, erlang:element(2, Builder)), {set_webhook_parameters, <<<<(erlang:element(2, erlang:element(2, Builder)))/binary, "/"/utf8>>/binary, (erlang:element(3, erlang:element(2, Builder)))/binary>>, erlang:element(11, Builder), erlang:element(8, Builder), erlang:element(9, Builder), erlang:element(10, Builder), erlang:element(7, Builder), {some, erlang:element(4, erlang:element(2, Builder))}} ), fun(Is_ok) -> gleam@bool:guard( not Is_ok, {error, set_webhook_error}, fun() -> gleam@result:'try'( telega@api:get_me( erlang:element(5, erlang:element(2, Builder)) ), fun(Bot_info) -> Session_settings = gleam@option:to_result( erlang:element(4, Builder), no_session_settings_error ), gleam@result:'try'( Session_settings, fun(Session_settings@1) -> gleam@result:'try'( telega@internal@registry:start(), fun(Registry_subject) -> Catch_handler = gleam@option:lazy_unwrap( erlang:element(6, Builder), fun() -> fun(_, _) -> {ok, nil} end end ), gleam@result:'try'( telega@bot:start( Registry_subject, erlang:element(2, Builder), Bot_info, erlang:element(3, Builder), Session_settings@1, Catch_handler ), fun(Bot_subject) -> {ok, {telega, erlang:element( 2, Builder ), Bot_info, Bot_subject}} end ) end ) end ) end ) end ) end ). -file("src/telega.gleam", 287). ?DOC( " Initialize a Telega instance with a `Nil` session.\n" " Useful when you don't need to persist the session.\n" ). -spec init_nil_session(telega_builder(nil, any())) -> {ok, telega(any(), any())} | {error, telega@error:telega_error()}. init_nil_session(Builder) -> Persist_session = fun(_, _) -> {ok, nil} end, Get_session = fun(_) -> {ok, {some, nil}} end, Default_session = fun() -> nil end, _pipe = begin _record = Builder, {telega_builder, erlang:element(2, _record), erlang:element(3, _record), {some, {session_settings, Persist_session, Get_session, Default_session}}, erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record), erlang:element(10, _record), erlang:element(11, _record)} end, init(_pipe). -file("src/telega.gleam", 385). ?DOC(" Handle an update from the Telegram API.\n"). -spec handle_update(telega(any(), any()), telega@update:update()) -> {ok, boolean()} | {error, gleam@erlang@process:call_error(any())}. handle_update(Telega, Update) -> telega@bot:handle_update(erlang:element(4, Telega), Update).