def video_handler(tdata): video = tdata.update.message.video if not video: return None return video.file_unique_id def print_recap(tdata): return "\n".join(f"{key}: *{value}*" for key, value in tdata.sdata.items()) # ---- STATES sticker = State("sticker", "This is a *sticker* handler", back_button=False, 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
def go_to_random(tdata): # you can use force state (from tdata.autoconv) to force a state # it works in operations button and in action too random_state = choice(tdata.autoconv.conversation.state_list) print(f"> Going to {random_state}") tdata.context.user_data.get("data").clear() tdata.autoconv.force_state(random_state, tdata.update) # always use EXIT_SIGNAL to interrupt autoconv # if you don't use EXIT_SIGNAL, Autoconv will continue as normal (not intended) return tdata.autoconv.EXIT_SIGNAL # ---- STATES simple = State( "simple", "This is a *simple* action.\nCurrent timestamp: *@@@*\n\nAnswer is `footsteps`", back_button=False, ) # the action will replace the @@@ in the State message with its return value simple.add_action(current_timestamp) simple.add_keyboard(["Next"]) riddle = State( "riddle", "Try a *riddle*..\n_The more you take, the more you leave behind. What am I?_\n\nYour answer: *@@@*", data_type=str, ) riddle.add_text(r"^(?i)footsteps$", "*Wrong*!") riddle.add_action(riddle_answer) riddle.add_dynamic_keyboard(riddle_keyboard)
update.message.reply_text( f"Welcome *{update.message.from_user.first_name}*!\n\nTry /example.", parse_mode="Markdown", ) def handle_text(update, context): update.message.delete() # --------------------------------- Example AutoConv ---------------------------------- STATE = range(1) # ---- STATES first = State("first", back_button=False) first.add_keyboard(["Next"]) second = State("second") 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*.",
return "" if data == "0" else data def recap(tdata): if (ma := 18 - tdata.sdata.get("age")) > 0 and tdata.sdata.get( "consent") == "Abort": return f"Come back when you'll have your *parents consent* or in *{ma}* years." return "\n".join([f"{k.title()}: *{v}*" for k, v in tdata.sdata.items()]) def add_timestamp(text): return f"({datetime.now():%H:%M})\n\n{text}" # ---- STATES name = State("name", "Enter your *name*.", data_type=str, back_button=False) name.add_text() 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)
# change the value of the counter counter = tdata.udata.get("counter") value = 1 if add else -1 tdata.context.user_data.update({"counter": counter + value}) def sub_counter(tdata): change_counter(tdata, False) def add_counter(tdata): change_counter(tdata, True) # ---- STATES static = State("static", "This State has a *simple static keyboard*.") static.add_keyboard(["Next"]) static_dict = State( "static_dict", "This is another static keyboard, but defined with a *dictionary*.") static_dict.add_keyboard({42: "Go back", 99: "Next"}) dynamic = State("dynamic", "This is a *dynamic keyboard* changed by a custom function.") dynamic.add_dynamic_keyboard(dynamic_keyboard) custom = State( "custom", "This is the most powerful, but dangerous keyboard..\nthe *custom* one.") custom.add_custom_keyboard(custom_keyboard)
tdata.autoconv.stop_timed_function("bomb") # if you are fast enough you can stop the console log tdata.autoconv.stop_timed_function(function=print_name) def show_password(tdata): # you can pass every kwargs you want tdata.autoconv.send_autodestroy_message( "The *password* is `pink-elephant-42`!", 2, parse_mode="Markdown" ) # ---- STATES simple = State( "simple", "This is simple *timer*!\nIn *3 seconds* you will redirect to the next state..", back_button=False, ) simple.add_action(go_to_next) log = State("log", "In this state in 5 seconds you will receive a *console log*") log.add_action(log_values) log.add_keyboard(["Next"]) run = State( "run", "_Run Barry, run!_\nThe bomb will *explode* in 3 seconds..", back_button=False, ) run.add_action(bomb_explosion) run.add_keyboard(["Run"])
def labels_list(tdata): return ["First", "Second", "Another", "More", "Ops"] def show_current_element(tdata): return tdata.udata.get("list_el") # same as -> return tdata.udata.get("list")[tdata.udata.get("list_i")] def last_elem_keyboard(tdata): i = tdata.udata.get("list_i") return i == 4 and ["Next"] or [] # ---- STATES simple = State("simple", "This is the *current* element\n\n*@@@*", back_button=False) simple.add_dynamic_list(simple_list) simple.add_action(show_current_element) simple.add_keyboard(["Next"]) showall = State( "showall", "This is the *current* element\nTo go in the next State, go to _Ops_...\n\n*@@@*", ) showall.add_dynamic_list(simple_list, all_elements=True, labels=labels_list, max_row=2) showall.add_action(show_current_element) showall.add_dynamic_keyboard(last_elem_keyboard) strange = State("strange", "This is the *current* element\n\n*@@@*") strange.add_dynamic_list(simple_list, start=3, left_button="<<!", right_button="next?") strange.add_action(show_current_element)
# --------------------------------- Example AutoConv ---------------------------------- STATE = range(1) # ---- FUNCS def set_timestamp(message): current_timestamp = datetime.timestamp(datetime.now()) return f"Now: {int(current_timestamp)}\n\n{message}" # ---- STATES simple = State( "simple", "This is a *simple* state with all the default\nLike the web preview for [links](https://github.com/Mortafix/AutoConv-Telegram-Python)", back_button=False, ) # I need to set back_button to False beacause I set a default back button in the Conversation simple.add_keyboard(["Next"]) opponent = State( "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"])
seq = tdata.get_or_set("seq", "") return ", ".join(map(lambda x: names.get(x), seq)) def sequence_keyboard(tdata): seq = tdata.udata.get("seq") if seq == "ttfb": return {4: "Next"} if len(seq) > 0: return ["Flower", "Ballon", "Toast", "Delete"] return ["Flower", "Ballon", "Toast"] # ---- STATES simple = State("simple", "In this state, I'm going to *save* some value", back_button=False) simple.add_action(save_variables) simple.add_keyboard(["Next"]) count = State("count", "Insert a number to *increment* the counter\n\nCounter: *@@@*") count.add_action(count_action) count.add_text(r"^\d+(?<!0)$", "Insert a _valid_ number") count.add_keyboard(["Next"]) sequence = State( "sequence", "Insert the *sequence*:\n`toast, toast, flower, ballon`\n\n@@@") sequence.add_dynamic_keyboard(sequence_keyboard) sequence.add_action(sequence_action)
def comment_type(data): return '' if data == '0' else data def recap(update, context): data = context.user_data.get(update.effective_chat.id).get('data') if (ma := 18 - data.get('age')) > 0 and data.get('consent') == 'Abort': return f'Come back when you\'ll have your *parents consent* or in *{ma}* years.' return '\n'.join([ f'{k.title()}: *{v}*' for k, v in context.user_data.get( update.effective_chat.id).get('data').items() ]) # State name = State('name', 'Enter your *name*.', type=str, parse_mode=MARKDOWN) name.add_text() gender = State('gender', 'Select your *gender*', parse_mode=MARKDOWN, back=True) gender.add_keyboard(['Male', 'Female', 'Other']) age = State('age', 'Enter your *age*', parse_mode=MARKDOWN, back=True) 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?',
def new_users_list(tdata): new_user = tdata.sdata.get("add") return tdata.users + [new_user] def get_users_list(tdata): # action happens before the refresh auth, so here we have the pre-refresh list new_user = tdata.sdata.get("add") new_list = tdata.users + [new_user] return "\n".join(map(str, new_list)) # ---- STATES no_auth = State("no_auth", "This is a state for the *no authorized* users..") no_auth.add_action(log_user) no_auth.add_keyboard(["Retry"]) simple = State("simple", "If you see this state, you are *authorized*.. _Yay_!!", 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)
def new_users_list(tdata): new_user = tdata.sdata.get("add") return tdata.users + [new_user] def get_users_list(tdata): # action happens before the refresh auth, so here we have the pre-refresh list new_user = tdata.sdata.get("add") new_list = tdata.users + [new_user] return "\n".join(map(str, new_list)) # ---- STATES help_state = State("help", "Nice *Help*.. or maybe not!", back_button=False) 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
# --------------------------------- Example AutoConv ---------------------------------- STATE = range(1) # ---- FUNCS def error_handler(tdata): print(f"Error: {tdata.exception}") return str(tdata.exception) # ---- STATES errors = State("error", "Opsie, it seems an *error* occured..\n\n`@@@`", back_button=False) 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)