data_type=str) sticker.add_custom_handler(sticker_handler, "This is not a sticker!") image = State("image", "This is an *image* handler", data_type=str) image.add_custom_handler(image_handler, "This is not an image!") video = State("video", "This is a *video* handler", data_type=str) video.add_custom_handler(video_handler, "This is not a video!") end = State("end", "This is the *end* with a *recap*\n\n@@@", back_button=False) end.add_action(print_recap) # ---- CONVERSATION conv = Conversation(sticker, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_routes(sticker, default=image) conv.add_routes(image, default=video, back=sticker) conv.add_routes(video, default=end, back=image) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context) # MAIN --------------------------------------------------------------------------------
log = State("log", "In this state there is a *hidden task* with a terminal log") log.add_action(log_action) log.add_keyboard(["Next"]) # this will send a message while the main task is running log.set_long_task("Computing...") force = State("force", "This state has an *advanced features*, check out the code!") force.add_keyboard(["Next", "Go to a random state"]) force.add_operation_buttons({1: go_to_random}) end = State("end", "This is the *end*.") # ---- CONVERSATION conv = Conversation(simple, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_routes(simple, default=riddle) conv.add_routes(riddle, default=dynamic, back=simple) conv.add_routes(dynamic, default=log, back=riddle) conv.add_routes(log, default=force, back=dynamic) conv.add_routes(force, default=end, back=log) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context)
second.add_keyboard(["Next"]) third = State("third") third.add_keyboard(["Next"]) end = State("end") # ---- CONVERSATION texts = { "first": "This is the message for the *first* state!", "second": "Another text specified in the *dictionary*..", "third": "You can define texts in an _external file_\nFormat supported: *JSON*, *YAML* or *TOML*.", "end": "This is the *end*.", } # it can be also a file (specified via filename) in json, yaml or toml conv = Conversation(first, end_state=end, state_messages=texts) conv.set_defaults(params={"parse_mode": "Markdown"}) conv.add_routes(first, default=second) conv.add_routes(second, default=third, back=first) conv.add_routes(third, default=end, back=second) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context) # MAIN --------------------------------------------------------------------------------
gender = State("gender", "Select your *gender*", back_button="< Another back") gender.add_keyboard(["Male", "Female", "Other"]) age = State("age", "Enter your <b>age</b>", parse_mode="html") age.add_text(r"\d{1,2}", "Enter a *valid* age") underage = State("consent", "Drop the _responsibility_ on your parents?") underage.add_keyboard(["Yes", "Abort"]) comment = State("comment", "Do you want to enter additional comment?", data_type=comment_type) comment.add_keyboard(["Nope"]) comment.add_text() end = State("end", "@@@", back_button=False) end.add_action(recap) # ---- CONVERSATION conv = Conversation(name, end_state=end) conv.set_defaults( params={ "parse_mode": "Markdown", "disable_web_page_preview": True }, func=add_timestamp, back_button="< Back", ) conv.add_routes(name, default=gender) conv.add_routes(gender, default=age, back=name) conv.add_routes(age, routes={i: underage for i in range(19)}, default=comment, back=gender)
operation.add_action(show_counter) operation.add_operation_buttons([add_counter, sub_counter]) # same as a dict -> operation.add_button_operations({0: add_counter, 1: sub_counter}) end = State("end", "This is the *end*.") # ---- DYNAMIC def keyboard_dynamic_routes(tdata): # need to return a tuple: Routes, Default, back state_value = tdata.sdata.get("dynamic") return (None, static_dict if state_value is None else custom, None) # ---- CONVERSATION conv = Conversation(static, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}) conv.add_routes(static, default=static_dict) # same as -> conv.add_routes(static, routes={0: static_dict}) conv.add_routes(static_dict, routes={42: static, 99: dynamic}, back=static) dynamic.add_dynamic_routes(keyboard_dynamic_routes) conv.add_routes(custom, default=operation) conv.add_routes(operation, routes={2: end}, back=custom) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context)
bomb = State("bomb", "_KABOOOOM!?!_", back_button=False) bomb.add_keyboard(["Begin"]) password = State( "password", "This state will send a message that will *autodestroy* itself in 2 seconds", ) password.add_action(defuse_bomb) password.add_keyboard(["Next", "Show password"], (1, 1)) password.add_operation_buttons({1: show_password}) end = State("end", "This is the *end*.") # ---- CONVERSATION conv = Conversation(simple, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_routes(log, default=run) conv.add_routes(run, default=run_continue) conv.add_routes(run_continue, routes={3: password}, default=run_continue) conv.add_routes(password, routes={0: end}, back=run) conv.add_routes(bomb, default=simple) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context)
strange.add_action(show_current_element) strange.add_keyboard(["Next"]) preserve = State( "preserve", "This dynamic list *preserve the index*, trying to go back\n\nCurrent: *@@@*", ) preserve.add_dynamic_list(simple_list, preserve_index=True) preserve.add_action(show_current_element) preserve.add_keyboard(["Next"]) end = State("end", "This is the *end*.", back_button=False) # ---- CONVERSATION conv = Conversation(simple, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_routes(simple, routes={0: showall}, default=simple) conv.add_routes(showall, routes={0: strange}, default=showall, back=simple) conv.add_routes(strange, routes={0: preserve}, default=strange, back=showall) conv.add_routes(preserve, routes={0: end}, default=preserve, back=strange) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context)
"opponent", "I want to go against the <i>default</i>.. Go <u>HTML</u>!", parse_mode="html", disable_web_page_preview=False, back_button="My back button :ç", ) # Every arguments here override the Conversation defaults opponent.add_keyboard(["Next"]) sheep = State("sheep", "Another *default* State, 2nd _sheep_..") sheep.add_keyboard(["Next"]) end = State("end", "This is the *end*.", back_button=False) # ---- CONVERSATION conv = Conversation(simple, end_state=end) conv.set_defaults( params={"parse_mode": "Markdown", "disable_web_page_preview": True}, func=set_timestamp, back_button="Back", ) conv.add_routes(simple, default=opponent) conv.add_routes(opponent, default=sheep, back=simple) conv.add_routes(sheep, default=end, back=opponent) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context):
sequence = State( "sequence", "Insert the *sequence*:\n`toast, toast, flower, ballon`\n\n@@@") sequence.add_dynamic_keyboard(sequence_keyboard) sequence.add_action(sequence_action) sequence.add_operation_buttons([ lambda x: x.add("seq", "f"), lambda x: x.add("seq", "b"), lambda x: x.add("seq", "t"), lambda x: x.save(seq=x.udata.get("seq")[:-1]), ]) end = State("end", "This is the *end*.") # ---- CONVERSATION conv = Conversation(simple, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_routes(simple, default=count) conv.add_routes(count, default=count, routes={0: sequence}) conv.add_routes(sequence, default=sequence, routes={4: end}) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context) # MAIN --------------------------------------------------------------------------------
age.add_text(r'\d{1,2}', 'Enter a *valid* age') underage = State( 'consent', 'Do you know that the responsibility will fall on your parents?', back=True) underage.add_keyboard(['Yes', 'Abort']) comment = State('comment', 'Do you want to enter additional comment?', type=comment_type, back=True) comment.add_keyboard(['Nope']) comment.add_text() end = State('end', '@@@', parse_mode=MARKDOWN) end.add_action(recap) # Conversation example = Conversation(name, end_state=end) example.add_state([gender, age, underage, comment]) example.add_routes(name, default=gender) example.add_routes(gender, default=age, back=name) example.add_routes(age, routes={i: underage for i in range(19)}, default=comment, back=gender) example.add_routes(underage, routes={0: comment, 1: end}, back=age) example.add_routes(comment, default=end, back=age) # Handler autoconv = AutoConvHandler(example, STATE, back_button='Back') def autoconv_command(update, context):
back_button=False) simple.add_keyboard(["Next"]) add = State("add", "Add a new authorized *user*") add.add_text(r"^\d{5,}$", "Must be a valid *Telegram ID* (5+ digits)") users = State("users", "*Auth users list*\n\n@@@") users.add_keyboard(["Next"]) users.add_action(get_users_list) users.add_refresh_auth(new_users_list) # this will update the auth users list end = State("end", "This is the *end*.", back_button=False) # ---- CONVERSATION conv = Conversation(simple, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_authorized_users([18528224], no_auth) # provide your telegram ID in the list above conv.add_routes(simple, default=add) conv.add_routes(add, default=users, back=simple) conv.add_routes(users, default=end, back=add) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context)
help_state.add_keyboard(["Menu"]) simple = State( "simple", "Another *useless* state\nyou can use /help anytime", back_button=False ) simple.add_keyboard(["Next"]) restart = State( "restart", "You can also use /help here!\nRemember also to *restart* with /restart" ) restart.add_keyboard(["Next"]) end = State("end", "This is the *end*.", back_button=False) # ---- CONVERSATION conv = Conversation(simple, end_state=end) conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_routes(simple, default=restart) conv.add_routes(restart, default=end, back=simple) conv.add_routes(help_state, default=simple) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) # you need to define a placeholder (STATE in this case) in order to work def autoconv_command(update, context): return autoconv.manage_conversation(update, context)
errors.add_keyboard(["Menu"]) errors.add_action(error_handler) menu = State("menu", "Choose carefully, something is _broken_...", back_button=False) menu.add_keyboard(["Safe state", "Sus state"]) divisonbyzero = State("division", "I want to divide 42 by 0... result=@@@") divisonbyzero.add_action(lambda _: 42 / 0) divisonbyzero.add_keyboard(["Next"]) end = State("end", "This is the *end*.", back_button=False) # ---- CONVERSATION conv = Conversation(menu, end_state=end, fallback_state=errors) # a Conversation will run forever, except if it has an end State # error state is a State that catches all the exceptions in autoconv conv.set_defaults(params={"parse_mode": "Markdown"}, back_button="Back") conv.add_routes(errors, default=menu) conv.add_routes(menu, routes={0: end, 1: divisonbyzero}) conv.add_routes(divisonbyzero, default=end, back=menu) # ---- HANDLER autoconv = AutoConvHandler(conv, STATE) def autoconv_command(update, context): return autoconv.manage_conversation(update, context)