Skip to content

Commit

Permalink
Updated examples
Browse files Browse the repository at this point in the history
  • Loading branch information
coder2020official committed Jul 21, 2024
1 parent adae7a9 commit d33db85
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 164 deletions.
169 changes: 95 additions & 74 deletions examples/asynchronous_telebot/custom_states.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,112 @@
from telebot import asyncio_filters
from telebot.async_telebot import AsyncTeleBot

# list of storages, you can use any storage
from telebot import async_telebot
from telebot import asyncio_filters, types
from telebot.states import State, StatesGroup
from telebot.states.aio.context import StateContext
from telebot.asyncio_storage import StateMemoryStorage

# new feature for states.
from telebot.asyncio_handler_backends import State, StatesGroup

# default state storage is statememorystorage
bot = AsyncTeleBot('TOKEN', state_storage=StateMemoryStorage())

# Initialize the bot
state_storage = StateMemoryStorage() # don't use this in production; switch to redis
bot = async_telebot.AsyncTeleBot("TOKEN", state_storage=state_storage)

# Just create different statesgroup
# Define states
class MyStates(StatesGroup):
name = State() # statesgroup should contain states
surname = State()
name = State()
age = State()
color = State()
hobby = State()



# set_state -> sets a new state
# delete_state -> delets state if exists
# get_state -> returns state if exists


# Start command handler
@bot.message_handler(commands=['start'])
async def start_ex(message):
"""
Start command. Here we are starting state
"""
await bot.set_state(message.from_user.id, MyStates.name, message.chat.id)
await bot.send_message(message.chat.id, 'Hi, write me a name')



@bot.message_handler(state="*", commands='cancel')
async def any_state(message):
"""
Cancel state
"""
await bot.send_message(message.chat.id, "Your state was cancelled.")
await bot.delete_state(message.from_user.id, message.chat.id)
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_to_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_to_message_id=message.message_id)

# Handler for name input
@bot.message_handler(state=MyStates.name)
async def name_get(message):
"""
State 1. Will process when user's state is MyStates.name.
"""
await bot.send_message(message.chat.id, f'Now write me a surname')
await bot.set_state(message.from_user.id, MyStates.surname, message.chat.id)
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
data['name'] = message.text


@bot.message_handler(state=MyStates.surname)
async def ask_age(message):
"""
State 2. Will process when user's state is MyStates.surname.
"""
await bot.send_message(message.chat.id, "What is your age?")
await bot.set_state(message.from_user.id, MyStates.age, message.chat.id)
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
data['surname'] = message.text

# result
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_to_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 ready_for_answer(message):
"""
State 3. Will process when user's state is MyStates.age.
"""
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
await bot.send_message(message.chat.id, "Ready, take a look:\n<b>Name: {name}\nSurname: {surname}\nAge: {age}</b>".format(name=data['name'], surname=data['surname'], age=message.text), parse_mode="html")
await bot.delete_state(message.from_user.id, message.chat.id)

#incorrect number
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_to_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_to_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_to_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):
"""
Will process for wrong input when state is MyState.age
"""
await bot.send_message(message.chat.id, 'Looks like you are submitting a string in the field age. Please enter a number')

# register filters
async def age_incorrect(message: types.Message):
await bot.send_message(message.chat.id, 'Please enter a valid number for age.', reply_to_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.aio.middleware import StateMiddleware
bot.setup_middleware(StateMiddleware(bot))

# Start polling
import asyncio
asyncio.run(bot.polling())
asyncio.run(bot.polling())
186 changes: 96 additions & 90 deletions examples/custom_states.py
Original file line number Diff line number Diff line change
@@ -1,106 +1,112 @@
import telebot # telebot

from telebot import custom_filters
from telebot.handler_backends import State, StatesGroup #States

# States storage
import telebot
from telebot import custom_filters, types
from telebot.states import State, StatesGroup
from telebot.states.sync.context import StateContext
from telebot.storage import StateMemoryStorage

# Initialize the bot
state_storage = StateMemoryStorage() # don't use this in production; switch to redis
bot = telebot.TeleBot("TOKEN", state_storage=state_storage,
use_class_middlewares=True)

# Starting from version 4.4.0+, we support storages.
# StateRedisStorage -> Redis-based storage.
# StatePickleStorage -> Pickle-based storage.
# For redis, you will need to install redis.
# Pass host, db, password, or anything else,
# if you need to change config for redis.
# Pickle requires path. Default path is in folder .state-saves.
# If you were using older version of pytba for pickle,
# you need to migrate from old pickle to new by using
# StatePickleStorage().convert_old_to_new()



# Now, you can pass storage to bot.
state_storage = StateMemoryStorage() # you can init here another storage

bot = telebot.TeleBot("TOKEN",
state_storage=state_storage)


# States group.
# Define states
class MyStates(StatesGroup):
# Just name variables differently
name = State() # creating instances of State class is enough from now
surname = State()
name = State()
age = State()
color = State()
hobby = State()




# Start command handler
@bot.message_handler(commands=['start'])
def start_ex(message):
"""
Start command. Here we are starting state
"""
bot.set_state(message.from_user.id, MyStates.name, message.chat.id)
bot.send_message(message.chat.id, 'Hi, write me a name')


# Any state
def start_ex(message: types.Message, state: StateContext):
state.set(MyStates.name)
bot.send_message(message.chat.id, 'Hello! What is your first name?', reply_to_message_id=message.message_id)

# Cancel command handler
@bot.message_handler(state="*", commands=['cancel'])
def any_state(message):
"""
Cancel state
"""
bot.send_message(message.chat.id, "Your state was cancelled.")
bot.delete_state(message.from_user.id, message.chat.id)
def any_state(message: types.Message, state: StateContext):
state.delete()
bot.send_message(message.chat.id, 'Your information has been cleared. Type /start to begin again.', reply_to_message_id=message.message_id)

# Handler for name input
@bot.message_handler(state=MyStates.name)
def name_get(message):
"""
State 1. Will process when user's state is MyStates.name.
"""
bot.send_message(message.chat.id, 'Now write me a surname')
bot.set_state(message.from_user.id, MyStates.surname, message.chat.id)
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
data['name'] = message.text


@bot.message_handler(state=MyStates.surname)
def ask_age(message):
"""
State 2. Will process when user's state is MyStates.surname.
"""
bot.send_message(message.chat.id, "What is your age?")
bot.set_state(message.from_user.id, MyStates.age, message.chat.id)
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
data['surname'] = message.text

# result
def name_get(message: types.Message, state: StateContext):
state.set(MyStates.age)
bot.send_message(message.chat.id, "How old are you?", reply_to_message_id=message.message_id)
state.add_data(name=message.text)

# Handler for age input
@bot.message_handler(state=MyStates.age, is_digit=True)
def ready_for_answer(message):
"""
State 3. Will process when user's state is MyStates.age.
"""
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
msg = ("Ready, take a look:\n<b>"
f"Name: {data['name']}\n"
f"Surname: {data['surname']}\n"
f"Age: {message.text}</b>")
bot.send_message(message.chat.id, msg, parse_mode="html")
bot.delete_state(message.from_user.id, message.chat.id)

#incorrect number
def ask_color(message: types.Message, state: StateContext):
state.set(MyStates.color)
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)

bot.send_message(message.chat.id, "What is your favorite color? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id)

# Handler for color input
@bot.message_handler(state=MyStates.color)
def ask_hobby(message: types.Message, state: StateContext):
state.set(MyStates.hobby)
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)

bot.send_message(message.chat.id, "What is one of your hobbies? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id)

# Handler for hobby input
@bot.message_handler(state=MyStates.hobby, text=['Reading', 'Traveling', 'Gaming', 'Cooking'])
def finish(message: types.Message, state: StateContext):
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}")

bot.send_message(message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id)
state.delete()

# Handler for incorrect age input
@bot.message_handler(state=MyStates.age, is_digit=False)
def age_incorrect(message):
"""
Wrong response for MyStates.age
"""
bot.send_message(message.chat.id, 'Looks like you are submitting a string in the field age. Please enter a number')

# register filters
def age_incorrect(message: types.Message):
bot.send_message(message.chat.id, 'Please enter a valid number for age.', reply_to_message_id=message.message_id)

# Add custom filters
bot.add_custom_filter(custom_filters.StateFilter(bot))
bot.add_custom_filter(custom_filters.IsDigitFilter())
bot.add_custom_filter(custom_filters.TextMatchFilter())

# necessary for state parameter in handlers.
from telebot.states.sync.middleware import StateMiddleware
bot.setup_middleware(StateMiddleware(bot))

bot.infinity_polling(skip_pending=True)
# Start polling
bot.infinity_polling()

0 comments on commit d33db85

Please sign in to comment.