mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
States Update
This commit is contained in:
parent
124b07ee44
commit
8045ad56ea
@ -1,14 +1,22 @@
|
|||||||
import telebot
|
import telebot
|
||||||
from telebot import asyncio_filters
|
from telebot import asyncio_filters
|
||||||
from telebot.async_telebot import AsyncTeleBot
|
from telebot.async_telebot import AsyncTeleBot
|
||||||
|
|
||||||
|
# list of storages, you can use any storage
|
||||||
|
from telebot.asyncio_storage import StateRedisStorage,StateMemoryStorage,StatePickleStorage
|
||||||
|
|
||||||
|
# new feature for states.
|
||||||
|
from telebot.asyncio_handler_backends import State, StatesGroup
|
||||||
|
|
||||||
bot = AsyncTeleBot('TOKEN')
|
bot = AsyncTeleBot('TOKEN')
|
||||||
|
|
||||||
|
|
||||||
|
# Just create different statesgroup
|
||||||
|
class MyStates(StatesGroup):
|
||||||
|
name = State() # statesgroup should contain states
|
||||||
|
surname = State()
|
||||||
|
age = State()
|
||||||
|
|
||||||
class MyStates:
|
|
||||||
name = 1
|
|
||||||
surname = 2
|
|
||||||
age = 3
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +25,7 @@ async def start_ex(message):
|
|||||||
"""
|
"""
|
||||||
Start command. Here we are starting state
|
Start command. Here we are starting state
|
||||||
"""
|
"""
|
||||||
await bot.set_state(message.from_user.id, MyStates.name)
|
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')
|
await bot.send_message(message.chat.id, 'Hi, write me a name')
|
||||||
|
|
||||||
|
|
||||||
@ -28,7 +36,7 @@ async def any_state(message):
|
|||||||
Cancel state
|
Cancel state
|
||||||
"""
|
"""
|
||||||
await bot.send_message(message.chat.id, "Your state was cancelled.")
|
await bot.send_message(message.chat.id, "Your state was cancelled.")
|
||||||
await bot.delete_state(message.from_user.id)
|
await bot.delete_state(message.from_user.id, message.chat.id)
|
||||||
|
|
||||||
@bot.message_handler(state=MyStates.name)
|
@bot.message_handler(state=MyStates.name)
|
||||||
async def name_get(message):
|
async def name_get(message):
|
||||||
@ -36,8 +44,8 @@ async def name_get(message):
|
|||||||
State 1. Will process when user's state is 1.
|
State 1. Will process when user's state is 1.
|
||||||
"""
|
"""
|
||||||
await bot.send_message(message.chat.id, f'Now write me a surname')
|
await bot.send_message(message.chat.id, f'Now write me a surname')
|
||||||
await bot.set_state(message.from_user.id, MyStates.surname)
|
await bot.set_state(message.from_user.id, MyStates.surname, message.chat.id)
|
||||||
async with bot.retrieve_data(message.from_user.id) as data:
|
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||||
data['name'] = message.text
|
data['name'] = message.text
|
||||||
|
|
||||||
|
|
||||||
@ -47,16 +55,16 @@ async def ask_age(message):
|
|||||||
State 2. Will process when user's state is 2.
|
State 2. Will process when user's state is 2.
|
||||||
"""
|
"""
|
||||||
await bot.send_message(message.chat.id, "What is your age?")
|
await bot.send_message(message.chat.id, "What is your age?")
|
||||||
await bot.set_state(message.from_user.id, MyStates.age)
|
await bot.set_state(message.from_user.id, MyStates.age, message.chat.id)
|
||||||
async with bot.retrieve_data(message.from_user.id) as data:
|
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||||
data['surname'] = message.text
|
data['surname'] = message.text
|
||||||
|
|
||||||
# result
|
# result
|
||||||
@bot.message_handler(state=MyStates.age, is_digit=True)
|
@bot.message_handler(state=MyStates.age, is_digit=True)
|
||||||
async def ready_for_answer(message):
|
async def ready_for_answer(message):
|
||||||
async with bot.retrieve_data(message.from_user.id) as data:
|
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.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)
|
await bot.delete_state(message.from_user.id, message.chat.id)
|
||||||
|
|
||||||
#incorrect number
|
#incorrect number
|
||||||
@bot.message_handler(state=MyStates.age, is_digit=False)
|
@bot.message_handler(state=MyStates.age, is_digit=False)
|
||||||
|
@ -1,14 +1,39 @@
|
|||||||
import telebot
|
import telebot # telebot
|
||||||
|
|
||||||
from telebot import custom_filters
|
from telebot import custom_filters
|
||||||
|
from telebot.handler_backends import State, StatesGroup #States
|
||||||
|
|
||||||
bot = telebot.TeleBot("")
|
# States storage
|
||||||
|
from telebot.storage import StateRedisStorage, StatePickleStorage, StateMemoryStorage
|
||||||
|
|
||||||
|
|
||||||
class MyStates:
|
# Beginning from version 4.4.0+, we support storages.
|
||||||
name = 1
|
# StateRedisStorage -> Redis-based storage.
|
||||||
surname = 2
|
# StatePickleStorage -> Pickle-based storage.
|
||||||
age = 3
|
# 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.
|
||||||
|
class MyStates(StatesGroup):
|
||||||
|
# Just name variables differently
|
||||||
|
name = State() # creating instances of State class is enough from now
|
||||||
|
surname = State()
|
||||||
|
age = State()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -17,18 +42,18 @@ def start_ex(message):
|
|||||||
"""
|
"""
|
||||||
Start command. Here we are starting state
|
Start command. Here we are starting state
|
||||||
"""
|
"""
|
||||||
bot.set_state(message.from_user.id, MyStates.name)
|
bot.set_state(message.from_user.id, MyStates.name, message.chat.id)
|
||||||
bot.send_message(message.chat.id, 'Hi, write me a name')
|
bot.send_message(message.chat.id, 'Hi, write me a name')
|
||||||
|
|
||||||
|
|
||||||
|
# Any state
|
||||||
@bot.message_handler(state="*", commands='cancel')
|
@bot.message_handler(state="*", commands='cancel')
|
||||||
def any_state(message):
|
def any_state(message):
|
||||||
"""
|
"""
|
||||||
Cancel state
|
Cancel state
|
||||||
"""
|
"""
|
||||||
bot.send_message(message.chat.id, "Your state was cancelled.")
|
bot.send_message(message.chat.id, "Your state was cancelled.")
|
||||||
bot.delete_state(message.from_user.id)
|
bot.delete_state(message.from_user.id, message.chat.id)
|
||||||
|
|
||||||
@bot.message_handler(state=MyStates.name)
|
@bot.message_handler(state=MyStates.name)
|
||||||
def name_get(message):
|
def name_get(message):
|
||||||
@ -36,8 +61,8 @@ def name_get(message):
|
|||||||
State 1. Will process when user's state is 1.
|
State 1. Will process when user's state is 1.
|
||||||
"""
|
"""
|
||||||
bot.send_message(message.chat.id, f'Now write me a surname')
|
bot.send_message(message.chat.id, f'Now write me a surname')
|
||||||
bot.set_state(message.from_user.id, MyStates.surname)
|
bot.set_state(message.from_user.id, MyStates.surname, message.chat.id)
|
||||||
with bot.retrieve_data(message.from_user.id) as data:
|
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||||
data['name'] = message.text
|
data['name'] = message.text
|
||||||
|
|
||||||
|
|
||||||
@ -47,16 +72,16 @@ def ask_age(message):
|
|||||||
State 2. Will process when user's state is 2.
|
State 2. Will process when user's state is 2.
|
||||||
"""
|
"""
|
||||||
bot.send_message(message.chat.id, "What is your age?")
|
bot.send_message(message.chat.id, "What is your age?")
|
||||||
bot.set_state(message.from_user.id, MyStates.age)
|
bot.set_state(message.from_user.id, MyStates.age, message.chat.id)
|
||||||
with bot.retrieve_data(message.from_user.id) as data:
|
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||||
data['surname'] = message.text
|
data['surname'] = message.text
|
||||||
|
|
||||||
# result
|
# result
|
||||||
@bot.message_handler(state=MyStates.age, is_digit=True)
|
@bot.message_handler(state=MyStates.age, is_digit=True)
|
||||||
def ready_for_answer(message):
|
def ready_for_answer(message):
|
||||||
with bot.retrieve_data(message.from_user.id) as data:
|
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||||
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")
|
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")
|
||||||
bot.delete_state(message.from_user.id)
|
bot.delete_state(message.from_user.id, message.chat.id)
|
||||||
|
|
||||||
#incorrect number
|
#incorrect number
|
||||||
@bot.message_handler(state=MyStates.age, is_digit=False)
|
@bot.message_handler(state=MyStates.age, is_digit=False)
|
||||||
@ -68,7 +93,4 @@ def age_incorrect(message):
|
|||||||
bot.add_custom_filter(custom_filters.StateFilter(bot))
|
bot.add_custom_filter(custom_filters.StateFilter(bot))
|
||||||
bot.add_custom_filter(custom_filters.IsDigitFilter())
|
bot.add_custom_filter(custom_filters.IsDigitFilter())
|
||||||
|
|
||||||
# set saving states into file.
|
|
||||||
bot.enable_saving_states() # you can delete this if you do not need to save states
|
|
||||||
|
|
||||||
bot.infinity_polling(skip_pending=True)
|
bot.infinity_polling(skip_pending=True)
|
@ -364,6 +364,7 @@ class AsyncTeleBot:
|
|||||||
handler_error = None
|
handler_error = None
|
||||||
data = {}
|
data = {}
|
||||||
process_handler = True
|
process_handler = True
|
||||||
|
if middleware:
|
||||||
middleware_result = await middleware.pre_process(message, data)
|
middleware_result = await middleware.pre_process(message, data)
|
||||||
if isinstance(middleware_result, SkipHandler):
|
if isinstance(middleware_result, SkipHandler):
|
||||||
await middleware.post_process(message, data, handler_error)
|
await middleware.post_process(message, data, handler_error)
|
||||||
@ -2481,8 +2482,8 @@ class AsyncTeleBot:
|
|||||||
"""
|
"""
|
||||||
return await asyncio_helper.delete_chat_photo(self.token, chat_id)
|
return await asyncio_helper.delete_chat_photo(self.token, chat_id)
|
||||||
|
|
||||||
async def get_my_commands(self, scope: Optional[types.BotCommandScope]=None,
|
async def get_my_commands(self, scope: Optional[types.BotCommandScope],
|
||||||
language_code: Optional[str]=None) -> List[types.BotCommand]:
|
language_code: Optional[str]) -> List[types.BotCommand]:
|
||||||
"""
|
"""
|
||||||
Use this method to get the current list of the bot's commands.
|
Use this method to get the current list of the bot's commands.
|
||||||
Returns List of BotCommand on success.
|
Returns List of BotCommand on success.
|
||||||
|
@ -17,3 +17,19 @@ class BaseMiddleware:
|
|||||||
async def post_process(self, message, data, exception):
|
async def post_process(self, message, data, exception):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class State:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.name = None
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class StatesGroup:
|
||||||
|
def __init_subclass__(cls) -> None:
|
||||||
|
# print all variables of a subclass
|
||||||
|
for name, value in cls.__dict__.items():
|
||||||
|
if not name.startswith('__') and not callable(value) and isinstance(value, State):
|
||||||
|
# change value of that variable
|
||||||
|
value.name = ':'.join((cls.__name__, name))
|
||||||
|
|
||||||
|
@ -149,3 +149,19 @@ class RedisHandlerBackend(HandlerBackend):
|
|||||||
return handlers
|
return handlers
|
||||||
|
|
||||||
|
|
||||||
|
class State:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.name = None
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class StatesGroup:
|
||||||
|
def __init_subclass__(cls) -> None:
|
||||||
|
# print all variables of a subclass
|
||||||
|
for name, value in cls.__dict__.items():
|
||||||
|
if not name.startswith('__') and not callable(value) and isinstance(value, State):
|
||||||
|
# change value of that variable
|
||||||
|
value.name = ':'.join((cls.__name__, name))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user