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
5
2
from telebot .asyncio_storage import StateMemoryStorage
3
+ from telebot .states import State , StatesGroup
4
+ from telebot .states .asyncio .context import StateContext
6
5
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 )
12
9
13
10
14
- # Just create different statesgroup
11
+ # Define states
15
12
class MyStates (StatesGroup ):
16
- name = State () # statesgroup should contain states
17
- surname = State ()
13
+ name = State ()
18
14
age = State ()
15
+ color = State ()
16
+ hobby = State ()
19
17
20
18
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
+ )
21
28
22
- # set_state -> sets a new state
23
- # delete_state -> delets state if exists
24
- # get_state -> returns state if exists
25
29
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
+ )
26
39
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 )
44
40
41
+ # Handler for name input
45
42
@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
67
52
@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
77
132
@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
+ )
83
139
84
- # register filters
85
140
141
+ # Add custom filters
86
142
bot .add_custom_filter (asyncio_filters .StateFilter (bot ))
87
143
bot .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
88
148
149
+ bot .setup_middleware (StateMiddleware (bot ))
89
150
151
+ # Start polling
90
152
import asyncio
91
- asyncio .run (bot .polling ())
153
+
154
+ asyncio .run (bot .polling ())
0 commit comments