Aiostep - Simple and Flexible State Management
Aiostep is a lightweight and flexible state management tool designed for Telegram bots and similar applications. It allows developers to track user states and manage transitions between them with ease. Whether you're building a multi-step form, handling complex user interactions, or simply need to store temporary user data, Aiostep makes it straightforward.
We have a vibrant community of developers helping each other in our Telegram group. Join us!
Stay tuned for library updates and new releases on our Telegram Channel.
Features
- Simple API: Intuitive methods for setting, getting, and deleting user states and associated data.
- Customizable Storage: Use in-memory storage or integrate with persistent options like Redis or file-based storage.
- Direct User Interaction: Easily ask questions and receive user responses directly within handlers, reducing boilerplate code.
- Extendable: Designed to integrate with existing frameworks such as aiogram.
How It Works
User Interaction Methods
Aiostep provides three primary methods for interacting with users and managing multi-step processes:
-
wait_for:- Use this method to wait for a specific user response within the current handler.
- Simplifies user interaction by reducing the need for separate handlers.
-
register_next_step:- Allows registering the next handler explicitly for a user.
- Useful for chaining steps in a process.
-
States:
- Define user states to manage stages in a multi-step workflow.
- States can include optional callbacks for seamless navigation between steps.
Installation
To start using Aiostep, simply install it via pip.
pip install --upgrade aiostep
If you want use RedisStateStorage, you should install aiostep with redis support:
pip install --upgrade aiostep[redis]
Usage
Using wait_for and register_next_step
Aiostep offers two primary methods for managing direct user interactions:
1. wait_for
- This method allows you to wait for a user response directly within the current handler.
- Requires the
Listenmiddleware to be set up for intercepting subsequent user messages.
Example:
from aiostep import aiogram_dialect, wait_for
from aiogram import Dispatcher, filters
from aiogram.types import Message
dp = Dispatcher()
dp.message.outer_middleware(aiogram_dialect.Listen())
@dp.message(filters.CommandStart())
async def ask_question(message: Message):
await message.reply("Please type something:")
try:
response = await wait_for(message.from_user.id, timeout=25) # timeout is optional
except TimeoutError:
await message.reply("You took too long to answer.")
else:
await message.reply(f"You typed: {response.text}")
2. register_next_step
- Use this method to explicitly register the next handler for the user's response.
- Also requires the
Listenmiddleware for processing follow-up messages.
Example:
import aiostep
from aiostep import aiogram_dialect
from aiogram import Dispatcher, filters
from aiogram.types import Message
dp = Dispatcher()
dp.message.outer_middleware(aiogram_dialect.Listen())
@dp.message(filters.CommandStart())
async def ask_question(message: Message):
await aiostep.register_next_step(message.chat.id, handle_answer)
await message.reply("What's your name?")
async def handle_answer(message: Message):
await message.reply(f"Hello, {message.text}!")
Using States
Aiostep supports managing user states to handle multi-step workflows. Unlike the previous methods, managing states does not require the Listen middleware.
1. Memory State Storage
- This is an in-memory implementation suitable for temporary state storage.
Example:
from aiostep import MemoryStateStorage
from aiostep.utils import IsState
from aiogram import Dispatcher, filters
from aiogram.types import Message
dp = Dispatcher()
state_manager = MemoryStateStorage()
@dp.message(filters.CommandStart())
async def start_process(message: Message):
state_manager.set_state(
user_id=message.from_user.id,
state="STEP_ONE"
)
await message.reply("State set to STEP_ONE!")
@dp.message(IsState("STEP_ONE", state_manager))
async def handle_step_one(message: Message):
await message.reply("You're in STEP_ONE.")
state_manager.delete_state(
user_id=message.from_user.id,
)
Returning to Previous State:
from aiogram import F
@dp.message(F.text == "Back")
async def go_back(message: Message):
step = state_manager.get_state(message.from_user.id)
if step and step.callback:
await step.callback(message)
else:
await message.reply("No previous state found.")
2. Other Storage Options
- File-based and Redis storage implementations are also available, providing similar functionality with persistent data storage.
- Simply replace MemoryStateStorage with FileStateStorage or RedisStateStorage when initializing the state manager.
3. Timeout States
To set a timeout (expiry) for the state storage, you can use the ex argument for both RedisStateStorage and FileStateStorage.
But for MemoryStateStorage you need to pass a TTLCache if you want set timeout.
Here's how you can set it up:
-
For
MemoryStateStorage(usingcachebox.TTLCache):from aiostep import MemoryStateStorage from cachebox import TTLCache # cachetools.TTLCache also works # Create a TTLCache with a timeout of 200 seconds storage = MemoryStateStorage(TTLCache(0, 200)) # Timeout is 200 seconds
-
For
RedisStateStorageandFileStateStorage(using theexargument for expiry time):from aiostep import RedisStateStorage from aiostep import FileStateStorage # Create RedisStateStorage with a timeout of 200 seconds storage = RedisStateStorage(db=0, ex=200) # Timeout (expiry) is 200 seconds storage = FileStateStorage("path.txt", ex=200) # Same as RedisStateStorage
In both cases, the state will automatically expire after the specified time, and the data will be removed from the storage.
Using Data
Setting Data
state_manager.set_data(
user_id=message.from_user.id,
data={"key": "value"},
other_key="other_value",
)
Getting Data
data = state_manager.get_data(user_id=user_id)
print(f"Data saved for {user_id} is: {data}")
Updating Data
state_manager.update_data(
user_id=user_id,
data={"key": "value"},
other_key="other_value",
)
Important Notes
-
Callbacks:
- Callbacks can be any callable object, such as functions.
- In
FileStateStorageandRedisStateStoragethey are stored as strings (e.g. function name).
-
Storage Flexibility:
- The memory-based implementation is ideal for development and testing.
- Persistent storage like Redis is recommended for production.
Future Plans
- Better Library Compatibility: Enhanced support for other Telegram bot libraries such as
python-telegram-bot, in addition toaiogram. - Improved Documentation: Detailed guides and best practices.
License
This project is licensed under the MIT License. See the LICENSE file for more details.
For more information or to contribute, visit our GitHub repository.
Metadata
Release files for aiostep 0.3.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| aiostep-0.3.7.tar.gz | 14.0 kB | Without provenance | Details for aiostep-0.3.7.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| aiostep-0.3.7-py3-none-any.whl | Python 3 | none | any | Details for aiostep-0.3.7-py3-none-any.whl |
Total release size: 38.1 kB
Release files / aiostep-0.3.7.tar.gz
| Download URL | aiostep-0.3.7.tar.gz |
|---|---|
| Size | 14.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecfbc5528fb1102e33b1a45e129bf9032d230e7de7c0a0cf9e7035fcf29b19dc
|
|
BLAKE2b-256 checksum How to use checksums |
0e0b12abb77bb1df7476d5599e79b9833a0987025edf967f1b09cbf9d506613f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.13.7 Windows/11
|
Release files / aiostep-0.3.7-py3-none-any.whl
| Download URL | aiostep-0.3.7-py3-none-any.whl |
|---|---|
| Size | 24.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
255cb8b529c99fd710e1f369bcc79bd62ef5121ac93698fc82a219611a6f75d0
|
|
BLAKE2b-256 checksum How to use checksums |
ccbbff72644cd668d918fe123a6f3710e16bbc3d3cfa77c5746d4a2ad60b8fa9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.13.7 Windows/11
|
Security for aiostep 0.3.7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.