-module(telega@flow@handler). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/telega/flow/handler.gleam"). -export([text_step/3, text_step_with/3, message_step/2, message_step_with/2, create_resume_handler/1, create_resume_handler_with_keyboard/2, create_text_handler/1]). -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(" Built-in step handlers and resume handler factories.\n"). -file("src/telega/flow/handler.gleam", 18). ?DOC(" Create a text input step\n"). -spec text_step(binary(), binary(), BLNG) -> fun((telega@bot:context(BLNH, BLNI, BLNJ), telega@flow@types:flow_instance()) -> {ok, {telega@bot:context(BLNH, BLNI, BLNJ), telega@flow@types:flow_action(BLNG), telega@flow@types:flow_instance()}} | {error, BLNI}). text_step(Prompt, Data_key, Next_step) -> fun(Ctx, Instance_val) -> case telega@flow@instance:get_wait_result(Instance_val) of {text_input, Value} -> Instance_val@1 = telega@flow@instance:store_data( Instance_val, Data_key, Value ), {ok, {Ctx, {next, Next_step}, Instance_val@1}}; pending -> case telega@reply:with_text(Ctx, Prompt) of {ok, _} -> {ok, {Ctx, wait, Instance_val}}; {error, _} -> {ok, {Ctx, cancel, Instance_val}} end; _ -> case telega@reply:with_text(Ctx, Prompt) of {ok, _} -> {ok, {Ctx, wait, Instance_val}}; {error, _} -> {ok, {Ctx, cancel, Instance_val}} end end end. -file("src/telega/flow/handler.gleam", 63). ?DOC( " Like `text_step`, but the prompt is computed per update from the `Context`\n" " and the flow instance instead of being fixed when the flow is built.\n" "\n" " Use this when the prompt depends on something only known at update time —\n" " most commonly the active locale for internationalization. `text_step` bakes\n" " its prompt in at flow-construction time (startup), which is too early to know\n" " the user's language; `text_step_with` resolves it on every prompt instead.\n" "\n" " ```gleam\n" " builder.add_step(\n" " Date,\n" " handler.text_step_with(\n" " fn(ctx, _instance) { i18n.t(ctx, \"book.ask_date\", []) },\n" " \"booking_date\",\n" " Time,\n" " ),\n" " )\n" " ```\n" ). -spec text_step_with( fun((telega@bot:context(BLNO, BLNP, BLNQ), telega@flow@types:flow_instance()) -> binary()), binary(), BLNU ) -> fun((telega@bot:context(BLNO, BLNP, BLNQ), telega@flow@types:flow_instance()) -> {ok, {telega@bot:context(BLNO, BLNP, BLNQ), telega@flow@types:flow_action(BLNU), telega@flow@types:flow_instance()}} | {error, BLNP}). text_step_with(Prompt, Data_key, Next_step) -> fun(Ctx, Instance_val) -> case telega@flow@instance:get_wait_result(Instance_val) of {text_input, Value} -> Instance_val@1 = telega@flow@instance:store_data( Instance_val, Data_key, Value ), {ok, {Ctx, {next, Next_step}, Instance_val@1}}; _ -> case telega@reply:with_text(Ctx, Prompt(Ctx, Instance_val)) of {ok, _} -> {ok, {Ctx, wait, Instance_val}}; {error, _} -> {ok, {Ctx, cancel, Instance_val}} end end end. -file("src/telega/flow/handler.gleam", 86). ?DOC(" Create a message display step\n"). -spec message_step( fun((telega@flow@types:flow_instance()) -> binary()), gleam@option:option(BLNZ) ) -> fun((telega@bot:context(BLOB, BLOC, BLOD), telega@flow@types:flow_instance()) -> {ok, {telega@bot:context(BLOB, BLOC, BLOD), telega@flow@types:flow_action(BLNZ), telega@flow@types:flow_instance()}} | {error, BLOC}). message_step(Message_fn, Next_step) -> fun(Ctx, Instance_val) -> Message = Message_fn(Instance_val), case telega@reply:with_text(Ctx, Message) of {ok, _} -> case Next_step of {some, Step} -> {ok, {Ctx, {next, Step}, Instance_val}}; none -> {ok, {Ctx, {complete, erlang:element( 3, erlang:element(6, Instance_val) )}, Instance_val}} end; {error, _} -> {ok, {Ctx, cancel, Instance_val}} end end. -file("src/telega/flow/handler.gleam", 116). ?DOC( " Like `message_step`, but the message is computed from the `Context` (in\n" " addition to the flow instance), enabling localization.\n" "\n" " ```gleam\n" " builder.add_step(\n" " Welcome,\n" " handler.message_step_with(\n" " fn(ctx, _instance) { i18n.t(ctx, \"book.welcome\", []) },\n" " option.Some(Date),\n" " ),\n" " )\n" " ```\n" ). -spec message_step_with( fun((telega@bot:context(BLOI, BLOJ, BLOK), telega@flow@types:flow_instance()) -> binary()), gleam@option:option(BLOO) ) -> fun((telega@bot:context(BLOI, BLOJ, BLOK), telega@flow@types:flow_instance()) -> {ok, {telega@bot:context(BLOI, BLOJ, BLOK), telega@flow@types:flow_action(BLOO), telega@flow@types:flow_instance()}} | {error, BLOJ}). message_step_with(Message_fn, Next_step) -> fun(Ctx, Instance_val) -> Message = Message_fn(Ctx, Instance_val), case telega@reply:with_text(Ctx, Message) of {ok, _} -> case Next_step of {some, Step} -> {ok, {Ctx, {next, Step}, Instance_val}}; none -> {ok, {Ctx, {complete, erlang:element( 3, erlang:element(6, Instance_val) )}, Instance_val}} end; {error, _} -> {ok, {Ctx, cancel, Instance_val}} end end. -file("src/telega/flow/handler.gleam", 178). -spec resume_handler(telega@flow@types:flow(any(), BLQS, BLQT, BLQU)) -> fun((telega@bot:context(BLQS, BLQT, BLQU), telega@update:update()) -> {ok, telega@bot:context(BLQS, BLQT, BLQU)} | {error, BLQT}). resume_handler(Flow) -> fun(Ctx, Upd) -> case Upd of {callback_query_update, _, _, Query, _} -> Data = gleam@option:unwrap( erlang:element(7, Query), <<""/utf8>> ), Token@1 = case gleam@string:split(Data, <<":"/utf8>>) of [_, Token | _] -> Token; _ -> Data end, Resume_data = maps:from_list( [{<<"callback_data"/utf8>>, Data}, {<<"__wait_result"/utf8>>, telega@flow@instance:encode_callback_wait_result( Data )}] ), telega@flow@engine:resume_with_token( Flow, Ctx, Token@1, {some, Resume_data} ); _ -> {ok, Ctx} end end. -file("src/telega/flow/handler.gleam", 136). ?DOC(" Create a router handler for resuming flows from callback queries\n"). -spec create_resume_handler(telega@flow@types:flow(any(), BLOV, BLOW, BLOX)) -> fun((telega@bot:context(BLOV, BLOW, BLOX), telega@update:update()) -> {ok, telega@bot:context(BLOV, BLOW, BLOX)} | {error, BLOW}). create_resume_handler(Flow) -> resume_handler(Flow). -file("src/telega/flow/handler.gleam", 205). -spec resume_handler_with_keyboard( telega@flow@types:flow(any(), BLRI, BLRJ, BLRK), telega@keyboard:keyboard_callback_data(binary()) ) -> fun((telega@bot:context(BLRI, BLRJ, BLRK), telega@update:update()) -> {ok, telega@bot:context(BLRI, BLRJ, BLRK)} | {error, BLRJ}). resume_handler_with_keyboard(Flow, Callback_data) -> fun(Ctx, Upd) -> case Upd of {callback_query_update, _, _, Query, _} -> Data = gleam@option:unwrap( erlang:element(7, Query), <<""/utf8>> ), Wait_result_value = telega@flow@instance:encode_callback_wait_result( Data ), Resume_data = maps:from_list( [{<<"callback_data"/utf8>>, Data}, {<<"__wait_result"/utf8>>, Wait_result_value}] ), case telega@keyboard:unpack_callback(Data, Callback_data) of {ok, Callback} -> telega@flow@engine:resume_with_token( Flow, Ctx, erlang:element(2, Callback), {some, Resume_data} ); {error, _} -> Token@1 = case gleam@string:split(Data, <<":"/utf8>>) of [_, Token | _] -> Token; _ -> Data end, telega@flow@engine:resume_with_token( Flow, Ctx, Token@1, {some, Resume_data} ) end; _ -> {ok, Ctx} end end. -file("src/telega/flow/handler.gleam", 144). ?DOC(" Create a router handler for resuming flows from callback queries with keyboard parsing\n"). -spec create_resume_handler_with_keyboard( telega@flow@types:flow(any(), BLPL, BLPM, BLPN), telega@keyboard:keyboard_callback_data(binary()) ) -> fun((telega@bot:context(BLPL, BLPM, BLPN), telega@update:update()) -> {ok, telega@bot:context(BLPL, BLPM, BLPN)} | {error, BLPM}). create_resume_handler_with_keyboard(Flow, Callback_data) -> resume_handler_with_keyboard(Flow, Callback_data). -file("src/telega/flow/handler.gleam", 153). ?DOC(" Create a text handler for resuming flows\n"). -spec create_text_handler(telega@flow@types:flow(any(), BLQC, BLQD, BLQE)) -> fun((telega@bot:context(BLQC, BLQD, BLQE), telega@update:update()) -> {ok, telega@bot:context(BLQC, BLQD, BLQE)} | {error, BLQD}). create_text_handler(Flow) -> fun(Ctx, Upd) -> case Upd of {text_update, From_id, Chat_id, Text, _, _} -> case (erlang:element(5, erlang:element(7, Flow)))( From_id, Chat_id ) of {ok, [Inst | _]} when erlang:element(8, Inst) =/= none -> Data = maps:from_list([{<<"user_input"/utf8>>, Text}]), telega@flow@engine:resume_with_token( Flow, Ctx, gleam@option:unwrap( erlang:element(8, Inst), <<""/utf8>> ), {some, Data} ); _ -> {ok, Ctx} end; _ -> {ok, Ctx} end end.