Current section
Files
Jump to
Current section
Files
src/telega@bot.erl
-module(telega@bot).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/telega/bot.gleam").
-export([start/8, cancel_conversation/2, start_chat_instance/1, next_session/2, get_session/2, handle_update/2, wait_handler/4]).
-export_type([bot/2, chat_instance_args/2, bot_message/0, chat_instance_message/2, continuation/2, chat_instance/2, context/2, session_settings/2, callback_query_filter/0, hears/0, handler/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.
?MODULEDOC(
" Core bot actor and chat instance management.\n"
"\n"
" This module implements the actor-based architecture for handling Telegram updates.\n"
" It contains the `Bot` actor (the central dispatcher) and `ChatInstance` actors\n"
" (one per unique `{chat_id}:{from_id}` combination).\n"
"\n"
" ## Supervision tree\n"
"\n"
" Both the `Bot` actor and `ChatInstance` actors run inside a supervision tree\n"
" created by `telega.init()` or `telega.init_for_polling()`:\n"
"\n"
" ```text\n"
" TelegaRootSupervisor (static_supervisor, OneForOne)\n"
" ├── ChatInstances (factory_supervisor, Transient children)\n"
" │ ├── ChatInstance {chat1:user1}\n"
" │ ├── ChatInstance {chat2:user2}\n"
" │ └── ...\n"
" ├── Bot actor (worker, Permanent)\n"
" └── Polling worker (worker, Permanent) — only for polling mode\n"
" ```\n"
"\n"
" - The `Bot` actor is a `Permanent` worker — it always restarts on crash.\n"
" - `ChatInstance` actors are `Transient` — they restart only on abnormal exit,\n"
" not on normal shutdown. On restart a `ChatInstance` re-registers itself in\n"
" the ETS registry, overwriting the stale subject.\n"
" - The `Bot` creates new `ChatInstance` actors via `factory_supervisor.start_child`,\n"
" which ensures they are supervised from the moment they start.\n"
"\n"
" ## Handler pattern\n"
"\n"
" All handlers follow this signature:\n"
"\n"
" ```gleam\n"
" fn handler(ctx: Context(session, error), data: Type) -> Result(Context(session, error), error)\n"
" ```\n"
"\n"
" Always return the updated context — it carries the (potentially modified) session.\n"
"\n"
" ## Conversation API\n"
"\n"
" The `wait_handler` function and the `Handler` type enable multi-message\n"
" conversations: the chat instance suspends its main handler and waits for a\n"
" specific update type. See `telega.wait_text`, `telega.wait_command`, etc.\n"
).
-opaque bot(ADUM, ADUN) :: {bot,
gleam@erlang@process:subject(bot_message()),
telega@internal@config:config(),
telega@model@types:user(),
fun((context(ADUM, ADUN), ADUN) -> {ok, nil} | {error, ADUN}),
session_settings(ADUM, ADUN),
fun((context(ADUM, ADUN), telega@update:update()) -> {ok,
context(ADUM, ADUN)} |
{error, ADUN}),
telega@internal@registry:registry(chat_instance_message(ADUM, ADUN)),
gleam@otp@factory_supervisor:supervisor(chat_instance_args(ADUM, ADUN), gleam@erlang@process:subject(chat_instance_message(ADUM, ADUN)))}.
-type chat_instance_args(ADUO, ADUP) :: {chat_instance_args,
binary(),
telega@internal@config:config(),
session_settings(ADUO, ADUP),
fun((context(ADUO, ADUP), ADUP) -> {ok, nil} | {error, ADUP}),
fun((context(ADUO, ADUP), telega@update:update()) -> {ok,
context(ADUO, ADUP)} |
{error, ADUP}),
telega@model@types:user(),
telega@internal@registry:registry(chat_instance_message(ADUO, ADUP))}.
-opaque bot_message() :: {cancel_conversation_bot_message, binary()} |
{handle_update_bot_message,
telega@update:update(),
gleam@erlang@process:subject(boolean())}.
-opaque chat_instance_message(ADUQ, ADUR) :: {handle_new_chat_instance_message,
telega@update:update(),
gleam@erlang@process:subject(boolean())} |
{wait_handler_chat_instance_message,
handler(ADUQ, ADUR),
gleam@option:option(handler(ADUQ, ADUR)),
gleam@option:option(integer())}.
-type continuation(ADUS, ADUT) :: {continuation,
handler(ADUS, ADUT),
gleam@option:option(handler(ADUS, ADUT)),
gleam@option:option(gleam@time@timestamp:timestamp())}.
-type chat_instance(ADUU, ADUV) :: {chat_instance,
binary(),
ADUU,
telega@internal@config:config(),
session_settings(ADUU, ADUV),
gleam@erlang@process:subject(chat_instance_message(ADUU, ADUV)),
gleam@option:option(continuation(ADUU, ADUV)),
fun((context(ADUU, ADUV), telega@update:update()) -> {ok,
context(ADUU, ADUV)} |
{error, ADUV}),
fun((context(ADUU, ADUV), ADUV) -> {ok, nil} | {error, ADUV}),
telega@model@types:user()}.
-type context(ADUW, ADUX) :: {context,
binary(),
telega@update:update(),
telega@internal@config:config(),
ADUW,
gleam@erlang@process:subject(chat_instance_message(ADUW, ADUX)),
gleam@option:option(gleam@time@timestamp:timestamp()),
gleam@option:option(binary()),
telega@model@types:user()}.
-type session_settings(ADUY, ADUZ) :: {session_settings,
fun((binary(), ADUY) -> {ok, ADUY} | {error, ADUZ}),
fun((binary()) -> {ok, gleam@option:option(ADUY)} | {error, ADUZ}),
fun(() -> ADUY)}.
-type callback_query_filter() :: {callback_query_filter, gleam@regexp:regexp()}.
-type hears() :: {hear_text, binary()} |
{hear_texts, list(binary())} |
{hear_regex, gleam@regexp:regexp()} |
{hear_regexes, list(gleam@regexp:regexp())}.
-type handler(ADVA, ADVB) :: {handle_all,
fun((context(ADVA, ADVB), telega@update:update()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_command,
binary(),
fun((context(ADVA, ADVB), telega@update:command()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_commands,
list(binary()),
fun((context(ADVA, ADVB), telega@update:command()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_text,
fun((context(ADVA, ADVB), binary()) -> {ok, context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_hears,
hears(),
fun((context(ADVA, ADVB), binary()) -> {ok, context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_message,
fun((context(ADVA, ADVB), telega@model@types:message()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_voice,
fun((context(ADVA, ADVB), telega@model@types:voice()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_audio,
fun((context(ADVA, ADVB), telega@model@types:audio()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_video,
fun((context(ADVA, ADVB), telega@model@types:video()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_photos,
fun((context(ADVA, ADVB), list(telega@model@types:photo_size())) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_web_app_data,
fun((context(ADVA, ADVB), telega@model@types:web_app_data()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_callback_query,
callback_query_filter(),
fun((context(ADVA, ADVB), binary(), binary()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})} |
{handle_chat_member,
fun((context(ADVA, ADVB), telega@model@types:chat_member_updated()) -> {ok,
context(ADVA, ADVB)} |
{error, ADVB})}.
-file("src/telega/bot.gleam", 564).
-spec build_session_key(telega@update:update()) -> binary().
build_session_key(Update) ->
<<<<(erlang:integer_to_binary(erlang:element(3, Update)))/binary, ":"/utf8>>/binary,
(erlang:integer_to_binary(erlang:element(2, Update)))/binary>>.
-file("src/telega/bot.gleam", 186).
-spec handle_update_bot_message(
bot(any(), any()),
telega@update:update(),
gleam@erlang@process:subject(boolean())
) -> {ok, nil} | {error, telega@error:telega_error()}.
handle_update_bot_message(Bot, Update, Reply_with) ->
Key = build_session_key(Update),
case telega@internal@registry:get(erlang:element(8, Bot), Key) of
{some, Chat_subject} ->
_pipe = gleam@otp@actor:send(
Chat_subject,
{handle_new_chat_instance_message, Update, Reply_with}
),
{ok, _pipe};
none ->
Args = {chat_instance_args,
Key,
erlang:element(3, Bot),
erlang:element(6, Bot),
erlang:element(5, Bot),
erlang:element(7, Bot),
erlang:element(4, Bot),
erlang:element(8, Bot)},
gleam@result:'try'(
begin
_pipe@1 = gleam@otp@factory_supervisor:start_child(
erlang:element(9, Bot),
Args
),
gleam@result:map_error(
_pipe@1,
fun(Field@0) -> {chat_instance_start_error, Field@0} end
)
end,
fun(Started) ->
_pipe@2 = gleam@otp@actor:send(
erlang:element(3, Started),
{handle_new_chat_instance_message, Update, Reply_with}
),
{ok, _pipe@2}
end
)
end.
-file("src/telega/bot.gleam", 168).
-spec bot_loop(bot(AEHG, AEHH), bot_message()) -> gleam@otp@actor:next(bot(AEHG, AEHH), any()).
bot_loop(Bot, Message) ->
case Message of
{handle_update_bot_message, Update, Reply_with} ->
case handle_update_bot_message(Bot, Update, Reply_with) of
{ok, _} ->
gleam@otp@actor:continue(Bot);
{error, Error} ->
telega@internal@log:error_d(
<<"Error in handler: "/utf8>>,
Error
),
gleam@otp@actor:stop()
end;
{cancel_conversation_bot_message, Key} ->
telega@internal@registry:unregister(erlang:element(8, Bot), Key),
gleam@otp@actor:continue(Bot)
end.
-file("src/telega/bot.gleam", 122).
-spec start(
telega@internal@registry:registry(chat_instance_message(ADVW, ADVX)),
telega@internal@config:config(),
telega@model@types:user(),
fun((context(ADVW, ADVX), telega@update:update()) -> {ok,
context(ADVW, ADVX)} |
{error, ADVX}),
session_settings(ADVW, ADVX),
fun((context(ADVW, ADVX), ADVX) -> {ok, nil} | {error, ADVX}),
gleam@otp@factory_supervisor:supervisor(chat_instance_args(ADVW, ADVX), gleam@erlang@process:subject(chat_instance_message(ADVW, ADVX))),
gleam@option:option(gleam@erlang@process:name(bot_message()))
) -> {ok, gleam@otp@actor:started(gleam@erlang@process:subject(bot_message()))} |
{error, gleam@otp@actor:start_error()}.
start(
Registry,
Config,
Bot_info,
Router_handler,
Session_settings,
Catch_handler,
Chat_factory,
Name
) ->
Self = gleam@erlang@process:new_subject(),
Bot = {bot,
Self,
Config,
Bot_info,
Catch_handler,
Session_settings,
Router_handler,
Registry,
Chat_factory},
Builder = begin
_pipe = gleam@otp@actor:new(Bot),
gleam@otp@actor:on_message(_pipe, fun bot_loop/2)
end,
Builder@1 = case Name of
{some, N} ->
gleam@otp@actor:named(Builder, N);
none ->
Builder
end,
gleam@otp@actor:start(Builder@1).
-file("src/telega/bot.gleam", 161).
?DOC(" Stops waiting for any handler for specific key (chat_id)\n").
-spec cancel_conversation(bot(any(), any()), binary()) -> nil.
cancel_conversation(Bot, Key) ->
gleam@otp@actor:send(
erlang:element(2, Bot),
{cancel_conversation_bot_message, Key}
).
-file("src/telega/bot.gleam", 526).
-spec new_context(chat_instance(ADYK, ADYL), telega@update:update()) -> context(ADYK, ADYL).
new_context(Chat, Update) ->
{context,
erlang:element(2, Chat),
Update,
erlang:element(4, Chat),
erlang:element(3, Chat),
erlang:element(6, Chat),
none,
none,
erlang:element(10, Chat)}.
-file("src/telega/bot.gleam", 686).
-spec do_handle(
context(AELB, AELC),
telega@update:update(),
handler(AELB, AELC)
) -> gleam@option:option({ok, context(AELB, AELC)} | {error, AELC}).
do_handle(Context, Update, Handler) ->
case {Handler, Update} of
{{handle_all, Handler@1}, _} ->
_pipe = Context,
_pipe@1 = Handler@1(_pipe, Update),
{some, _pipe@1};
{{handle_text, Handler@2}, {text_update, _, _, Text, _, _}} ->
_pipe@2 = Context,
_pipe@3 = Handler@2(_pipe@2, Text),
{some, _pipe@3};
{{handle_hears, _, Handler@3}, {text_update, _, _, Text@1, _, _}} ->
_pipe@4 = Context,
_pipe@5 = Handler@3(_pipe@4, Text@1),
{some, _pipe@5};
{{handle_command, _, Handler@4},
{command_update, _, _, Update_command, _, _}} ->
_pipe@6 = Context,
_pipe@7 = Handler@4(_pipe@6, Update_command),
{some, _pipe@7};
{{handle_commands, _, Handler@5},
{command_update, _, _, Update_command@1, _, _}} ->
_pipe@8 = Context,
_pipe@9 = Handler@5(_pipe@8, Update_command@1),
{some, _pipe@9};
{{handle_callback_query, _, Handler@6},
{callback_query_update, _, _, Query, _}} ->
gleam@option:map(
erlang:element(7, Query),
fun(Data) ->
Handler@6(Context, Data, erlang:element(2, Query))
end
);
{{handle_message, Handler@7}, {message_update, _, _, Message, _}} ->
_pipe@10 = Context,
_pipe@11 = Handler@7(_pipe@10, Message),
{some, _pipe@11};
{{handle_chat_member, Handler@8},
{chat_member_update, _, _, Chat_member_updated, _}} ->
_pipe@12 = Context,
_pipe@13 = Handler@8(_pipe@12, Chat_member_updated),
{some, _pipe@13};
{{handle_voice, Handler@9}, {voice_update, _, _, Voice, _, _}} ->
_pipe@14 = Context,
_pipe@15 = Handler@9(_pipe@14, Voice),
{some, _pipe@15};
{{handle_audio, Handler@10}, {audio_update, _, _, Audio, _, _}} ->
_pipe@16 = Context,
_pipe@17 = Handler@10(_pipe@16, Audio),
{some, _pipe@17};
{{handle_video, Handler@11}, {video_update, _, _, Video, _, _}} ->
_pipe@18 = Context,
_pipe@19 = Handler@11(_pipe@18, Video),
{some, _pipe@19};
{{handle_web_app_data, Handler@12},
{web_app_update, _, _, Web_app_data, _, _}} ->
_pipe@20 = Context,
_pipe@21 = Handler@12(_pipe@20, Web_app_data),
{some, _pipe@21};
{_, _} ->
none
end.
-file("src/telega/bot.gleam", 406).
-spec do_handle_continuation(
context(ADYA, ADYB),
continuation(ADYA, ADYB),
telega@update:update(),
gleam@erlang@process:subject(boolean()),
chat_instance(ADYA, ADYB)
) -> gleam@otp@actor:next(chat_instance(ADYA, ADYB), any()).
do_handle_continuation(Context, Continuation, Update, Reply_with, Chat) ->
case do_handle(Context, Update, erlang:element(2, Continuation)) of
{some, {ok, {context, _, _, _, New_session, _, _, _, _}}} ->
case (erlang:element(2, erlang:element(5, Chat)))(
erlang:element(2, Chat),
New_session
) of
{ok, Persisted_session} ->
gleam@otp@actor:send(Reply_with, true),
gleam@otp@actor:continue(
{chat_instance,
erlang:element(2, Chat),
Persisted_session,
erlang:element(4, Chat),
erlang:element(5, Chat),
erlang:element(6, Chat),
none,
erlang:element(8, Chat),
erlang:element(9, Chat),
erlang:element(10, Chat)}
);
{error, E} ->
case (erlang:element(9, Chat))(Context, E) of
{ok, _} ->
gleam@otp@actor:send(Reply_with, false),
gleam@otp@actor:continue(Chat);
{error, E@1} ->
telega@internal@log:error_d(
<<"Error in session persistence after continuation: "/utf8>>,
E@1
),
gleam@otp@actor:stop()
end
end;
{some, {error, E@2}} ->
case (erlang:element(9, Chat))(Context, E@2) of
{ok, _} ->
gleam@otp@actor:send(Reply_with, false),
gleam@otp@actor:continue(Chat);
{error, E@3} ->
telega@internal@log:error_d(
<<"Error in catch handler: "/utf8>>,
E@3
),
gleam@otp@actor:stop()
end;
none ->
case erlang:element(3, Continuation) of
{some, Handler} ->
case do_handle(Context, Update, Handler) of
{some,
{ok, {context, _, _, _, New_session@1, _, _, _, _}}} ->
case (erlang:element(2, erlang:element(5, Chat)))(
erlang:element(2, Chat),
New_session@1
) of
{ok, Persisted_session@1} ->
gleam@otp@actor:send(Reply_with, true),
gleam@otp@actor:continue(
{chat_instance,
erlang:element(2, Chat),
Persisted_session@1,
erlang:element(4, Chat),
erlang:element(5, Chat),
erlang:element(6, Chat),
erlang:element(7, Chat),
erlang:element(8, Chat),
erlang:element(9, Chat),
erlang:element(10, Chat)}
);
{error, E@4} ->
case (erlang:element(9, Chat))(Context, E@4) of
{ok, _} ->
gleam@otp@actor:send(
Reply_with,
false
),
gleam@otp@actor:continue(Chat);
{error, E@5} ->
telega@internal@log:error_d(
<<"Error in session persistence after handle_else: "/utf8>>,
E@5
),
gleam@otp@actor:stop()
end
end;
{some, {error, E@6}} ->
case (erlang:element(9, Chat))(Context, E@6) of
{ok, _} ->
gleam@otp@actor:send(Reply_with, false),
gleam@otp@actor:continue(Chat);
{error, E@7} ->
telega@internal@log:error_d(
<<"Error in catch else handler: "/utf8>>,
E@7
),
gleam@otp@actor:stop()
end;
none ->
gleam@otp@actor:send(Reply_with, false),
gleam@otp@actor:continue(Chat)
end;
none ->
gleam@otp@actor:send(Reply_with, false),
gleam@otp@actor:continue(Chat)
end
end.
-file("src/telega/bot.gleam", 329).
-spec do_handle_new_chat_instance_message(
context(ADXR, ADXS),
chat_instance(ADXR, ADXS),
telega@update:update(),
gleam@erlang@process:subject(boolean())
) -> gleam@otp@actor:next(chat_instance(ADXR, ADXS), any()).
do_handle_new_chat_instance_message(Context, Chat, Update, Reply_with) ->
case erlang:element(7, Chat) of
{some, Continuation} ->
case erlang:element(4, Continuation) of
{some, Ttl} ->
case gleam@time@timestamp:compare(
Ttl,
gleam@time@timestamp:system_time()
) of
lt ->
do_handle_new_chat_instance_message(
Context,
{chat_instance,
erlang:element(2, Chat),
erlang:element(3, Chat),
erlang:element(4, Chat),
erlang:element(5, Chat),
erlang:element(6, Chat),
none,
erlang:element(8, Chat),
erlang:element(9, Chat),
erlang:element(10, Chat)},
Update,
Reply_with
);
_ ->
do_handle_continuation(
Context,
Continuation,
Update,
Reply_with,
Chat
)
end;
none ->
do_handle_continuation(
Context,
Continuation,
Update,
Reply_with,
Chat
)
end;
none ->
case (erlang:element(8, Chat))(Context, Update) of
{ok, {context, _, _, _, New_session, _, _, _, _}} ->
case (erlang:element(2, erlang:element(5, Chat)))(
erlang:element(2, Chat),
New_session
) of
{ok, Persisted_session} ->
gleam@otp@actor:send(Reply_with, true),
gleam@otp@actor:continue(
{chat_instance,
erlang:element(2, Chat),
Persisted_session,
erlang:element(4, Chat),
erlang:element(5, Chat),
erlang:element(6, Chat),
erlang:element(7, Chat),
erlang:element(8, Chat),
erlang:element(9, Chat),
erlang:element(10, Chat)}
);
{error, E} ->
case (erlang:element(9, Chat))(Context, E) of
{ok, _} ->
gleam@otp@actor:send(Reply_with, false),
gleam@otp@actor:continue(Chat);
{error, E@1} ->
telega@internal@log:error_d(
<<"Error in session persistence: "/utf8>>,
E@1
),
gleam@otp@actor:stop()
end
end;
{error, E@2} ->
case (erlang:element(9, Chat))(Context, E@2) of
{ok, _} ->
gleam@otp@actor:send(Reply_with, false),
gleam@otp@actor:continue(Chat);
{error, E@3} ->
telega@internal@log:error_d(
<<"Error in catch handler: "/utf8>>,
E@3
),
gleam@otp@actor:stop()
end
end
end.
-file("src/telega/bot.gleam", 306).
-spec loop_chat_instance(
chat_instance(ADXL, ADXM),
chat_instance_message(ADXL, ADXM)
) -> gleam@otp@actor:next(chat_instance(ADXL, ADXM), any()).
loop_chat_instance(Chat, Message) ->
case Message of
{handle_new_chat_instance_message, Update, Reply_with} ->
do_handle_new_chat_instance_message(
new_context(Chat, Update),
Chat,
Update,
Reply_with
);
{wait_handler_chat_instance_message, Handler, Handle_else, Timeout} ->
_pipe@2 = {chat_instance,
erlang:element(2, Chat),
erlang:element(3, Chat),
erlang:element(4, Chat),
erlang:element(5, Chat),
erlang:element(6, Chat),
begin
_pipe@1 = {continuation,
Handler,
Handle_else,
begin
gleam@option:map(
Timeout,
fun(Timeout@1) ->
_pipe = gleam@time@timestamp:system_time(),
gleam@time@timestamp:add(
_pipe,
gleam@time@duration:seconds(Timeout@1)
)
end
)
end},
{some, _pipe@1}
end,
erlang:element(8, Chat),
erlang:element(9, Chat),
erlang:element(10, Chat)},
gleam@otp@actor:continue(_pipe@2)
end.
-file("src/telega/bot.gleam", 266).
?DOC(
" Start a chat instance. Used as the template function for factory_supervisor.\n"
" Self-registers in the registry on start (handles both first start and restart after crash).\n"
).
-spec start_chat_instance(chat_instance_args(ADXE, ADXF)) -> {ok,
gleam@otp@actor:started(gleam@erlang@process:subject(chat_instance_message(ADXE, ADXF)))} |
{error, gleam@otp@actor:start_error()}.
start_chat_instance(Args) ->
Session@1 = case (erlang:element(3, erlang:element(4, Args)))(
erlang:element(2, Args)
) of
{ok, {some, Session}} ->
Session;
{ok, none} ->
(erlang:element(4, erlang:element(4, Args)))();
{error, Error} ->
telega@internal@log:warning(
<<<<<<"Failed to get session for key "/utf8,
(erlang:element(2, Args))/binary>>/binary,
", falling back to default: "/utf8>>/binary,
(gleam@string:inspect(Error))/binary>>
),
(erlang:element(4, erlang:element(4, Args)))()
end,
_pipe@2 = gleam@otp@actor:new_with_initialiser(
10,
fun(Subject) ->
Chat_instance = {chat_instance,
erlang:element(2, Args),
Session@1,
erlang:element(3, Args),
erlang:element(4, Args),
Subject,
none,
erlang:element(6, Args),
erlang:element(5, Args),
erlang:element(7, Args)},
telega@internal@registry:register(
erlang:element(8, Args),
erlang:element(2, Args),
Subject
),
_pipe = gleam@otp@actor:initialised(Chat_instance),
_pipe@1 = gleam@otp@actor:returning(_pipe, Subject),
{ok, _pipe@1}
end
),
_pipe@3 = gleam@otp@actor:on_message(_pipe@2, fun loop_chat_instance/2),
gleam@otp@actor:start(_pipe@3).
-file("src/telega/bot.gleam", 557).
-spec next_session(context(ADYR, ADYS), ADYR) -> {ok, context(ADYR, ADYS)} |
{error, ADYS}.
next_session(Ctx, Session) ->
{ok,
{context,
erlang:element(2, Ctx),
erlang:element(3, Ctx),
erlang:element(4, Ctx),
Session,
erlang:element(6, Ctx),
erlang:element(7, Ctx),
erlang:element(8, Ctx),
erlang:element(9, Ctx)}}.
-file("src/telega/bot.gleam", 568).
-spec get_session(session_settings(ADZA, ADZB), telega@update:update()) -> {ok,
gleam@option:option(ADZA)} |
{error, ADZB}.
get_session(Session_settings, Update) ->
_pipe = Update,
_pipe@1 = build_session_key(_pipe),
(erlang:element(3, Session_settings))(_pipe@1).
-file("src/telega/bot.gleam", 579).
?DOC(false).
-spec handle_update(
gleam@erlang@process:subject(bot_message()),
telega@update:update()
) -> boolean().
handle_update(Bot_subject, Update) ->
gleam@erlang@process:call_forever(
Bot_subject,
fun(_capture) -> {handle_update_bot_message, Update, _capture} end
).
-file("src/telega/bot.gleam", 673).
?DOC(
" Pass any handler to start waiting\n"
"\n"
" `or` - calls if there are any other updates\n"
" `timeout` - the conversation will be canceled after this timeout\n"
).
-spec wait_handler(
context(ADZK, ADZL),
handler(ADZK, ADZL),
gleam@option:option(handler(ADZK, ADZL)),
gleam@option:option(integer())
) -> {ok, context(ADZK, ADZL)} | {error, ADZL}.
wait_handler(Ctx, Handler, Handle_else, Timeout) ->
gleam@otp@actor:send(
erlang:element(6, Ctx),
{wait_handler_chat_instance_message, Handler, Handle_else, Timeout}
),
{ok, Ctx}.