1- from telebot import asyncio_filters
2- from telebot .async_telebot import AsyncTeleBot
3-
4- # list of storages, you can use any storage
1+ from telebot import async_telebot , asyncio_filters , types
52from telebot .asyncio_storage import StateMemoryStorage
3+ from telebot .states import State , StatesGroup
4+ from telebot .states .asyncio .context import StateContext
65
7- # new feature for states.
8- from telebot .asyncio_handler_backends import State , StatesGroup
9-
10- # default state storage is statememorystorage
11- bot = AsyncTeleBot ('TOKEN' , state_storage = StateMemoryStorage ())
6+ # Initialize the bot
7+ state_storage = StateMemoryStorage () # don't use this in production; switch to redis
8+ bot = async_telebot .AsyncTeleBot ("TOKEN" , state_storage = state_storage )
129
1310
14- # Just create different statesgroup
11+ # Define states
1512class MyStates (StatesGroup ):
16- name = State () # statesgroup should contain states
17- surname = State ()
13+ name = State ()
1814 age = State ()
15+ color = State ()
16+ hobby = State ()
1917
2018
19+ # Start command handler
20+ @bot .message_handler (commands = ["start" ])
21+ async def start_ex (message : types .Message , state : StateContext ):
22+ await state .set (MyStates .name )
23+ await bot .send_message (
24+ message .chat .id ,
25+ "Hello! What is your first name?" ,
26+ reply_to_message_id = message .message_id ,
27+ )
2128
22- # set_state -> sets a new state
23- # delete_state -> delets state if exists
24- # get_state -> returns state if exists
2529
30+ # Cancel command handler
31+ @bot .message_handler (state = "*" , commands = ["cancel" ])
32+ async def any_state (message : types .Message , state : StateContext ):
33+ await state .delete ()
34+ await bot .send_message (
35+ message .chat .id ,
36+ "Your information has been cleared. Type /start to begin again." ,
37+ reply_to_message_id = message .message_id ,
38+ )
2639
27- @bot .message_handler (commands = ['start' ])
28- async def start_ex (message ):
29- """
30- Start command. Here we are starting state
31- """
32- await bot .set_state (message .from_user .id , MyStates .name , message .chat .id )
33- await bot .send_message (message .chat .id , 'Hi, write me a name' )
34-
35-
36-
37- @bot .message_handler (state = "*" , commands = 'cancel' )
38- async def any_state (message ):
39- """
40- Cancel state
41- """
42- await bot .send_message (message .chat .id , "Your state was cancelled." )
43- await bot .delete_state (message .from_user .id , message .chat .id )
4440
41+ # Handler for name input
4542@bot .message_handler (state = MyStates .name )
46- async def name_get (message ):
47- """
48- State 1. Will process when user's state is MyStates.name.
49- """
50- await bot .send_message (message .chat .id , f'Now write me a surname' )
51- await bot .set_state (message .from_user .id , MyStates .surname , message .chat .id )
52- async with bot .retrieve_data (message .from_user .id , message .chat .id ) as data :
53- data ['name' ] = message .text
54-
55-
56- @bot .message_handler (state = MyStates .surname )
57- async def ask_age (message ):
58- """
59- State 2. Will process when user's state is MyStates.surname.
60- """
61- await bot .send_message (message .chat .id , "What is your age?" )
62- await bot .set_state (message .from_user .id , MyStates .age , message .chat .id )
63- async with bot .retrieve_data (message .from_user .id , message .chat .id ) as data :
64- data ['surname' ] = message .text
65-
66- # result
43+ async def name_get (message : types .Message , state : StateContext ):
44+ await state .set (MyStates .age )
45+ await bot .send_message (
46+ message .chat .id , "How old are you?" , reply_to_message_id = message .message_id
47+ )
48+ await state .add_data (name = message .text )
49+
50+
51+ # Handler for age input
6752@bot .message_handler (state = MyStates .age , is_digit = True )
68- async def ready_for_answer (message ):
69- """
70- State 3. Will process when user's state is MyStates.age.
71- """
72- async with bot .retrieve_data (message .from_user .id , message .chat .id ) as data :
73- await bot .send_message (message .chat .id , "Ready, take a look:\n <b>Name: {name}\n Surname: {surname}\n Age: {age}</b>" .format (name = data ['name' ], surname = data ['surname' ], age = message .text ), parse_mode = "html" )
74- await bot .delete_state (message .from_user .id , message .chat .id )
75-
76- #incorrect number
53+ async def ask_color (message : types .Message , state : StateContext ):
54+ await state .set (MyStates .color )
55+ await state .add_data (age = message .text )
56+
57+ # Define reply keyboard for color selection
58+ keyboard = types .ReplyKeyboardMarkup (row_width = 2 )
59+ colors = ["Red" , "Green" , "Blue" , "Yellow" , "Purple" , "Orange" , "Other" ]
60+ buttons = [types .KeyboardButton (color ) for color in colors ]
61+ keyboard .add (* buttons )
62+
63+ await bot .send_message (
64+ message .chat .id ,
65+ "What is your favorite color? Choose from the options below." ,
66+ reply_markup = keyboard ,
67+ reply_to_message_id = message .message_id ,
68+ )
69+
70+
71+ # Handler for color input
72+ @bot .message_handler (state = MyStates .color )
73+ async def ask_hobby (message : types .Message , state : StateContext ):
74+ await state .set (MyStates .hobby )
75+ await state .add_data (color = message .text )
76+
77+ # Define reply keyboard for hobby selection
78+ keyboard = types .ReplyKeyboardMarkup (row_width = 2 )
79+ hobbies = ["Reading" , "Traveling" , "Gaming" , "Cooking" ]
80+ buttons = [types .KeyboardButton (hobby ) for hobby in hobbies ]
81+ keyboard .add (* buttons )
82+
83+ await bot .send_message (
84+ message .chat .id ,
85+ "What is one of your hobbies? Choose from the options below." ,
86+ reply_markup = keyboard ,
87+ reply_to_message_id = message .message_id ,
88+ )
89+
90+
91+ # Handler for hobby input; use filters to ease validation
92+ @bot .message_handler (
93+ state = MyStates .hobby , text = ["Reading" , "Traveling" , "Gaming" , "Cooking" ]
94+ )
95+ async def finish (message : types .Message , state : StateContext ):
96+ async with state .data () as data :
97+ name = data .get ("name" )
98+ age = data .get ("age" )
99+ color = data .get ("color" )
100+ hobby = message .text # Get the hobby from the message text
101+
102+ # Provide a fun fact based on color
103+ color_facts = {
104+ "Red" : "Red is often associated with excitement and passion." ,
105+ "Green" : "Green is the color of nature and tranquility." ,
106+ "Blue" : "Blue is known for its calming and serene effects." ,
107+ "Yellow" : "Yellow is a cheerful color often associated with happiness." ,
108+ "Purple" : "Purple signifies royalty and luxury." ,
109+ "Orange" : "Orange is a vibrant color that stimulates enthusiasm." ,
110+ "Other" : "Colors have various meanings depending on context." ,
111+ }
112+ color_fact = color_facts .get (
113+ color , "Colors have diverse meanings, and yours is unique!"
114+ )
115+
116+ msg = (
117+ f"Thank you for sharing! Here is a summary of your information:\n "
118+ f"First Name: { name } \n "
119+ f"Age: { age } \n "
120+ f"Favorite Color: { color } \n "
121+ f"Fun Fact about your color: { color_fact } \n "
122+ f"Favorite Hobby: { hobby } "
123+ )
124+
125+ await bot .send_message (
126+ message .chat .id , msg , parse_mode = "html" , reply_to_message_id = message .message_id
127+ )
128+ await state .delete ()
129+
130+
131+ # Handler for incorrect age input
77132@bot .message_handler (state = MyStates .age , is_digit = False )
78- async def age_incorrect (message ):
79- """
80- Will process for wrong input when state is MyState.age
81- """
82- await bot .send_message (message .chat .id , 'Looks like you are submitting a string in the field age. Please enter a number' )
133+ async def age_incorrect (message : types .Message ):
134+ await bot .send_message (
135+ message .chat .id ,
136+ "Please enter a valid number for age." ,
137+ reply_to_message_id = message .message_id ,
138+ )
83139
84- # register filters
85140
141+ # Add custom filters
86142bot .add_custom_filter (asyncio_filters .StateFilter (bot ))
87143bot .add_custom_filter (asyncio_filters .IsDigitFilter ())
144+ bot .add_custom_filter (asyncio_filters .TextMatchFilter ())
145+
146+ # necessary for state parameter in handlers.
147+ from telebot .states .asyncio .middleware import StateMiddleware
88148
149+ bot .setup_middleware (StateMiddleware (bot ))
89150
151+ # Start polling
90152import asyncio
91- asyncio .run (bot .polling ())
153+
154+ asyncio .run (bot .polling ())
0 commit comments