-module(telega@bot). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([set_webhook/1, wait_handler/2, start_registry/5]). -export_type([registry/1, registry_message/0, session_settings/1, context/1, bot_instance_message/1, bot_instance/1, hears/0, handler/1, callback_query_filter/0]). -type registry(VSL) :: {registry, gleam@dict:dict(binary(), gleam@erlang@process:subject(bot_instance_message(VSL))), telega@internal@config:config(), telega@model:user(), session_settings(VSL), list(handler(VSL)), gleam@erlang@process:subject(registry_message()), gleam@erlang@process:subject(gleam@erlang@process:subject(bot_instance_message(VSL)))}. -type registry_message() :: {handle_bot_registry_message, telega@update:update()}. -type session_settings(VSM) :: {session_settings, fun((binary(), VSM) -> {ok, VSM} | {error, binary()}), fun((binary()) -> {ok, VSM} | {error, binary()})}. -type context(VSN) :: {context, binary(), telega@update:update(), telega@model:user(), telega@internal@config:config(), VSN, gleam@erlang@process:subject(bot_instance_message(VSN))}. -type bot_instance_message(VSO) :: bot_instance_message_ok | {bot_instance_message_new, gleam@erlang@process:subject(bot_instance_message(VSO)), telega@update:update()} | {bot_instance_message_wait_handler, handler(VSO)}. -type bot_instance(VSP) :: {bot_instance, binary(), VSP, telega@internal@config:config(), list(handler(VSP)), telega@model:user(), session_settings(VSP), gleam@option:option(handler(VSP)), gleam@erlang@process:subject(bot_instance_message(VSP))}. -type hears() :: {hear_text, binary()} | {hear_texts, list(binary())} | {hear_regex, gleam@regexp:regexp()} | {hear_regexes, list(gleam@regexp:regexp())}. -type handler(VSQ) :: {handle_all, fun((context(VSQ)) -> {ok, VSQ} | {error, binary()})} | {handle_command, binary(), fun((context(VSQ), telega@update:command()) -> {ok, VSQ} | {error, binary()})} | {handle_commands, list(binary()), fun((context(VSQ), telega@update:command()) -> {ok, VSQ} | {error, binary()})} | {handle_text, fun((context(VSQ), binary()) -> {ok, VSQ} | {error, binary()})} | {handle_hears, hears(), fun((context(VSQ), binary()) -> {ok, VSQ} | {error, binary()})} | {handle_callback_query, callback_query_filter(), fun((context(VSQ), binary(), binary()) -> {ok, VSQ} | {error, binary()})}. -type callback_query_filter() :: {callback_query_filter, gleam@regexp:regexp()}. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 53). -spec try_send_update( gleam@erlang@process:subject(bot_instance_message(VTB)), telega@update:update() ) -> {ok, bot_instance_message(VTB)} | {error, gleam@erlang@process:call_error(bot_instance_message(VTB))}. try_send_update(Registry_item, Update) -> gleam@erlang@process:try_call( Registry_item, fun(_capture) -> {bot_instance_message_new, _capture, Update} end, 1000 ). -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 132). -spec set_webhook(telega@internal@config:config()) -> {ok, boolean()} | {error, binary()}. set_webhook(Config) -> telega@api:set_webhook( erlang:element(5, Config), {set_webhook_parameters, <<<<(erlang:element(2, Config))/binary, "/"/utf8>>/binary, (erlang:element(3, Config))/binary>>, none, none, none, none, {some, erlang:element(4, Config)}} ). -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 179). -spec wait_handler(context(VTT), handler(VTT)) -> {ok, VTT} | {error, binary()}. wait_handler(Ctx, Handler) -> gleam@erlang@process:send( erlang:element(7, Ctx), {bot_instance_message_wait_handler, Handler} ), {ok, erlang:element(6, Ctx)}. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 187). -spec new_context(bot_instance(VTY), telega@update:update()) -> context(VTY). new_context(Bot, Update) -> {context, erlang:element(2, Bot), Update, erlang:element(6, Bot), erlang:element(4, Bot), erlang:element(3, Bot), erlang:element(9, Bot)}. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 209). -spec get_session_key(telega@update:update()) -> {ok, binary()} | {error, binary()}. get_session_key(Update) -> case Update of {command_update, Chat_id, _, _} -> {ok, erlang:integer_to_binary(Chat_id)}; {text_update, Chat_id@1, _, _} -> {ok, erlang:integer_to_binary(Chat_id@1)}; {callback_query_update, From_id, _} -> {ok, erlang:integer_to_binary(From_id)}; {unknown_update, _} -> {error, <<"Unknown update type don't allow to get session key"/utf8>>} end. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 219). -spec get_session(session_settings(VUD), telega@update:update()) -> {ok, VUD} | {error, binary()}. get_session(Session_settings, Update) -> gleam@result:'try'( get_session_key(Update), fun(Key) -> _pipe = (erlang:element(3, Session_settings))(Key), gleam@result:map_error( _pipe, fun(E) -> <<"Failed to get session:\n "/utf8, (gleam@string:inspect(E))/binary>> end ) end ). -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 349). -spec hears_check(binary(), hears()) -> boolean(). hears_check(Text, Hear) -> case Hear of {hear_text, Str} -> Text =:= Str; {hear_texts, Strs} -> gleam@list:contains(Strs, Text); {hear_regex, Re} -> gleam@regexp:check(Re, Text); {hear_regexes, Regexes} -> gleam@list:any( Regexes, fun(_capture) -> gleam@regexp:check(_capture, Text) end ) end. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 389). -spec do_handle(bot_instance(VUR), telega@update:update(), handler(VUR)) -> gleam@option:option({ok, VUR} | {error, binary()}). do_handle(Bot, Update, Handler) -> case {Handler, Update} of {{handle_all, Handle}, _} -> {some, Handle(new_context(Bot, Update))}; {{handle_text, Handle@1}, {text_update, _, Text, _}} -> {some, Handle@1(new_context(Bot, Update), Text)}; {{handle_hears, Hear, Handle@2}, {text_update, _, Text@1, _}} -> case hears_check(Text@1, Hear) of true -> {some, Handle@2(new_context(Bot, Update), Text@1)}; false -> none end; {{handle_command, Command, Handle@3}, {command_update, _, Update_command, _}} -> case erlang:element(3, Update_command) =:= Command of true -> {some, Handle@3(new_context(Bot, Update), Update_command)}; false -> none end; {{handle_commands, Commands, Handle@4}, {command_update, _, Update_command@1, _}} -> case gleam@list:contains( Commands, erlang:element(3, Update_command@1) ) of true -> {some, Handle@4(new_context(Bot, Update), Update_command@1)}; false -> none end; {{handle_callback_query, Filter, Handle@5}, {callback_query_update, _, Raw}} -> case erlang:element(7, Raw) of {some, Data} -> case gleam@regexp:check(erlang:element(2, Filter), Data) of true -> {some, Handle@5( new_context(Bot, Update), Data, erlang:element(2, Raw) )}; false -> none end; none -> none end; {_, _} -> none end. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 429). -spec loop_handlers( bot_instance(VUX), telega@update:update(), list(handler(VUX)) ) -> {ok, VUX} | {error, binary()}. loop_handlers(Bot, Update, Handlers) -> case Handlers of [Handler | Rest] -> case do_handle(Bot, Update, Handler) of {some, {ok, New_session}} -> loop_handlers( begin _record = Bot, {bot_instance, erlang:element(2, _record), New_session, erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record), erlang:element(9, _record)} end, Update, Rest ); {some, {error, E}} -> {error, <<<<<<"Failed to handle message "/utf8, (gleam@string:inspect(Update))/binary>>/binary, ":\n"/utf8>>/binary, E/binary>>}; none -> loop_handlers(Bot, Update, Rest) end; [] -> (erlang:element(2, erlang:element(7, Bot)))( erlang:element(2, Bot), erlang:element(3, Bot) ) end. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 297). -spec handle_bot_instance_message(bot_instance_message(VUN), bot_instance(VUN)) -> gleam@otp@actor:next(any(), bot_instance(VUN)). handle_bot_instance_message(Message, Bot) -> case Message of {bot_instance_message_new, Client, Message@1} -> case erlang:element(8, Bot) of {some, Handler} -> case do_handle(Bot, Message@1, Handler) of {some, {ok, New_session}} -> gleam@otp@actor:send( Client, bot_instance_message_ok ), gleam@otp@actor:continue( begin _record = Bot, {bot_instance, erlang:element(2, _record), New_session, erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), none, erlang:element(9, _record)} end ); {some, {error, E}} -> telega@log:error( <<"Failed to handle update:\n"/utf8, E/binary>> ), {stop, normal}; none -> gleam@otp@actor:send( Client, bot_instance_message_ok ), gleam@otp@actor:continue(Bot) end; none -> case loop_handlers(Bot, Message@1, erlang:element(5, Bot)) of {ok, New_session@1} -> gleam@otp@actor:send( Client, bot_instance_message_ok ), gleam@otp@actor:continue( begin _record@1 = Bot, {bot_instance, erlang:element(2, _record@1), New_session@1, erlang:element(4, _record@1), erlang:element(5, _record@1), erlang:element(6, _record@1), erlang:element(7, _record@1), erlang:element(8, _record@1), erlang:element(9, _record@1)} end ); {error, E@1} -> telega@log:error( <<"Failed to handle update:\n"/utf8, E@1/binary>> ), {stop, normal} end end; {bot_instance_message_wait_handler, Handler@1} -> gleam@otp@actor:continue( begin _record@2 = Bot, {bot_instance, erlang:element(2, _record@2), erlang:element(3, _record@2), erlang:element(4, _record@2), erlang:element(5, _record@2), erlang:element(6, _record@2), erlang:element(7, _record@2), {some, Handler@1}, erlang:element(9, _record@2)} end ); bot_instance_message_ok -> gleam@otp@actor:continue(Bot) end. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 229). -spec start_bot_instance( registry(VUH), telega@update:update(), binary(), gleam@erlang@process:subject(gleam@erlang@process:subject(bot_instance_message(VUH))) ) -> {ok, gleam@erlang@process:subject(bot_instance_message(VUH))} | {error, gleam@otp@actor:start_error()}. start_bot_instance(Registry, Update, Session_key, Parent_subject) -> gleam@otp@actor:start_spec( {spec, fun() -> Actor_subj = gleam@erlang@process:new_subject(), gleam@erlang@process:send(Parent_subject, Actor_subj), Selector = begin _pipe = gleam_erlang_ffi:new_selector(), gleam@erlang@process:selecting( _pipe, Actor_subj, fun gleam@function:identity/1 ) end, case get_session(erlang:element(5, Registry), Update) of {ok, Session} -> _pipe@1 = {bot_instance, Session_key, Session, erlang:element(3, Registry), erlang:element(6, Registry), erlang:element(4, Registry), erlang:element(5, Registry), none, Actor_subj}, {ready, _pipe@1, Selector}; {error, E} -> {failed, <<"Failed to init bot instance:\n"/utf8, E/binary>>} end end, 10000, fun handle_bot_instance_message/2} ). -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 82). -spec add_bot_instance(registry(VTH), binary(), telega@update:update()) -> gleam@otp@actor:next(any(), registry(VTH)). add_bot_instance(Registry, Session_key, Update) -> Registry_actor = gleam@otp@supervisor:supervisor( fun(_) -> start_bot_instance( Registry, Update, Session_key, erlang:element(8, Registry) ) end ), _assert_subject = gleam@otp@supervisor:start( fun(_capture) -> gleam@otp@supervisor:add(_capture, Registry_actor) end ), {ok, _} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"telega/bot"/utf8>>, function => <<"add_bot_instance"/utf8>>, line => 97}) end, Bot_subject_result = begin _pipe = gleam_erlang_ffi:'receive'(erlang:element(8, Registry), 1000), gleam@result:map_error( _pipe, fun(E) -> <<"Failed to start bot instance:\n"/utf8, (gleam@string:inspect(E))/binary>> end ) end, case Bot_subject_result of {ok, Bot_subject} -> case try_send_update(Bot_subject, Update) of {ok, _} -> gleam@otp@actor:continue( begin _record = Registry, {registry, gleam@dict:insert( erlang:element(2, Registry), Session_key, Bot_subject ), erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record)} end ); {error, E@1} -> telega@log:error( <<"Failed to send message to bot instance: "/utf8, (gleam@string:inspect(E@1))/binary>> ), gleam@otp@actor:continue(Registry) end; {error, E@2} -> telega@log:error(E@2), gleam@otp@actor:continue(Registry) end. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 57). -spec handle_registry_message(registry_message(), registry(VTE)) -> gleam@otp@actor:next(any(), registry(VTE)). handle_registry_message(Message, Registry) -> case Message of {handle_bot_registry_message, Message@1} -> case get_session_key(Message@1) of {ok, Session_key} -> case gleam_stdlib:map_get( erlang:element(2, Registry), Session_key ) of {ok, Registry_item} -> case try_send_update(Registry_item, Message@1) of {ok, _} -> gleam@otp@actor:continue(Registry); {error, _} -> add_bot_instance( Registry, Session_key, Message@1 ) end; {error, nil} -> add_bot_instance(Registry, Session_key, Message@1) end; {error, E} -> telega@log:error( <<"Failed to get session key: "/utf8, (gleam@string:inspect(E))/binary>> ), gleam@otp@actor:continue(Registry) end end. -file("/Users/bondiano/workspace/telega-gleam/src/telega/bot.gleam", 146). -spec start_registry( telega@internal@config:config(), list(handler(VTM)), session_settings(VTM), gleam@erlang@process:subject(gleam@erlang@process:subject(registry_message())), telega@model:user() ) -> {ok, gleam@erlang@process:subject(registry_message())} | {error, gleam@otp@actor:start_error()}. start_registry(Config, Handlers, Session_settings, Root_subject, Bot_info) -> gleam@otp@actor:start_spec( {spec, fun() -> Registry_subject = gleam@erlang@process:new_subject(), Bot_instances_subject = gleam@erlang@process:new_subject(), gleam@erlang@process:send(Root_subject, Registry_subject), Selector = begin _pipe = gleam_erlang_ffi:new_selector(), gleam@erlang@process:selecting( _pipe, Registry_subject, fun gleam@function:identity/1 ) end, _pipe@1 = {registry, maps:new(), Config, Bot_info, Session_settings, Handlers, Registry_subject, Bot_instances_subject}, {ready, _pipe@1, Selector} end, 10000, fun handle_registry_message/2} ).