-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathcustom_states.py
157 lines (127 loc) · 5.31 KB
/
custom_states.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from telebot import async_telebot, asyncio_filters, types
from telebot.asyncio_storage import StateMemoryStorage
from telebot.states import State, StatesGroup
from telebot.states.asyncio.context import StateContext
from telebot.types import ReplyParameters
# Initialize the bot
state_storage = StateMemoryStorage() # don't use this in production; switch to redis
bot = async_telebot.AsyncTeleBot("TOKEN", state_storage=state_storage)
# Define states
class MyStates(StatesGroup):
name = State()
age = State()
color = State()
hobby = State()
# Start command handler
@bot.message_handler(commands=["start"])
async def start_ex(message: types.Message, state: StateContext):
await state.set(MyStates.name)
await bot.send_message(
message.chat.id,
"Hello! What is your first name?",
reply_parameters=ReplyParameters(message_id=message.message_id),
)
# Cancel command handler
@bot.message_handler(state="*", commands=["cancel"])
async def any_state(message: types.Message, state: StateContext):
await state.delete()
await bot.send_message(
message.chat.id,
"Your information has been cleared. Type /start to begin again.",
reply_parameters=ReplyParameters(message_id=message.message_id),
)
# Handler for name input
@bot.message_handler(state=MyStates.name)
async def name_get(message: types.Message, state: StateContext):
await state.set(MyStates.age)
await bot.send_message(
message.chat.id, "How old are you?",
reply_parameters=ReplyParameters(message_id=message.message_id),
)
await state.add_data(name=message.text)
# Handler for age input
@bot.message_handler(state=MyStates.age, is_digit=True)
async def ask_color(message: types.Message, state: StateContext):
await state.set(MyStates.color)
await state.add_data(age=message.text)
# Define reply keyboard for color selection
keyboard = types.ReplyKeyboardMarkup(row_width=2)
colors = ["Red", "Green", "Blue", "Yellow", "Purple", "Orange", "Other"]
buttons = [types.KeyboardButton(color) for color in colors]
keyboard.add(*buttons)
await bot.send_message(
message.chat.id,
"What is your favorite color? Choose from the options below.",
reply_markup=keyboard,
reply_parameters=ReplyParameters(message_id=message.message_id),
)
# Handler for color input
@bot.message_handler(state=MyStates.color)
async def ask_hobby(message: types.Message, state: StateContext):
await state.set(MyStates.hobby)
await state.add_data(color=message.text)
# Define reply keyboard for hobby selection
keyboard = types.ReplyKeyboardMarkup(row_width=2)
hobbies = ["Reading", "Traveling", "Gaming", "Cooking"]
buttons = [types.KeyboardButton(hobby) for hobby in hobbies]
keyboard.add(*buttons)
await bot.send_message(
message.chat.id,
"What is one of your hobbies? Choose from the options below.",
reply_markup=keyboard,
reply_parameters=ReplyParameters(message_id=message.message_id),
)
# Handler for hobby input; use filters to ease validation
@bot.message_handler(
state=MyStates.hobby, text=["Reading", "Traveling", "Gaming", "Cooking"]
)
async def finish(message: types.Message, state: StateContext):
async with state.data() as data:
name = data.get("name")
age = data.get("age")
color = data.get("color")
hobby = message.text # Get the hobby from the message text
# Provide a fun fact based on color
color_facts = {
"Red": "Red is often associated with excitement and passion.",
"Green": "Green is the color of nature and tranquility.",
"Blue": "Blue is known for its calming and serene effects.",
"Yellow": "Yellow is a cheerful color often associated with happiness.",
"Purple": "Purple signifies royalty and luxury.",
"Orange": "Orange is a vibrant color that stimulates enthusiasm.",
"Other": "Colors have various meanings depending on context.",
}
color_fact = color_facts.get(
color, "Colors have diverse meanings, and yours is unique!"
)
msg = (
f"Thank you for sharing! Here is a summary of your information:\n"
f"First Name: {name}\n"
f"Age: {age}\n"
f"Favorite Color: {color}\n"
f"Fun Fact about your color: {color_fact}\n"
f"Favorite Hobby: {hobby}"
)
await bot.send_message(
message.chat.id, msg, parse_mode="html",
reply_parameters=ReplyParameters(message_id=message.message_id),
)
await state.delete()
# Handler for incorrect age input
@bot.message_handler(state=MyStates.age, is_digit=False)
async def age_incorrect(message: types.Message):
await bot.send_message(
message.chat.id,
"Please enter a valid number for age.",
reply_parameters=ReplyParameters(message_id=message.message_id),
)
# Add custom filters
bot.add_custom_filter(asyncio_filters.StateFilter(bot))
bot.add_custom_filter(asyncio_filters.IsDigitFilter())
bot.add_custom_filter(asyncio_filters.TextMatchFilter())
# necessary for state parameter in handlers.
from telebot.states.asyncio.middleware import StateMiddleware
bot.setup_middleware(StateMiddleware(bot))
# Start polling
import asyncio
asyncio.run(bot.polling())