Current section
Files
Jump to
Current section
Files
src/telega.erl
-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(
<<<<Prefix@1/binary, "received update: "/utf8>>/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(
<<<<Prefix@1/binary, "handler failed: "/utf8>>/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(
<<<<<<Prefix@1/binary, "handler completed in "/utf8>>/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).