### Complete Minimal Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/11-quick-reference.md This example demonstrates a basic aiogram bot with a two-window dialog. It covers bot initialization, state management, dialog setup, and handling the start command. ```python import asyncio from aiogram import Bot, Dispatcher from aiogram.fsm.storage.memory import MemoryStorage from aiogram.fsm.state import StatesGroup, State from aiogram.filters import CommandStart from aiogram.types import Message from aiogram_dialog import Dialog, Window, DialogManager, setup_dialogs, StartMode from aiogram_dialog.widgets.text import Const from aiogram_dialog.widgets.kbd import Button, Next, Back TOKEN = "YOUR_TOKEN" class MainDialog(StatesGroup): main = State() next_step = State() dialog = Dialog( Window( Const("Welcome!"), Next(Const("Next")), state=MainDialog.main, ), Window( Const("Second step"), Back(Const("Back")), state=MainDialog.next_step, ), ) async def main(): bot = Bot(token=TOKEN) storage = MemoryStorage() dp = Dispatcher(storage=storage) dp.include_router(dialog) bg_factory = setup_dialogs(dp) @dp.message(CommandStart()) async def on_start(message: Message, manager: DialogManager): await manager.start(MainDialog.main, mode=StartMode.RESET_STACK) await dp.start_polling(bot) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Complete aiogram-dialog Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md A full example demonstrating the setup of a bot with aiogram-dialog, including defining states, creating a dialog with a window and button, initializing the bot and dispatcher with memory storage, and starting polling. ```python import asyncio from aiogram import Bot, Dispatcher, Router from aiogram.fsm.storage.memory import MemoryStorage from aiogram.fsm.state import StatesGroup, State from aiogram_dialog import Dialog, Window, setup_dialogs from aiogram_dialog.widgets.text import Const from aiogram_dialog.widgets.kbd import Button TOKEN = "YOUR_TOKEN" # Define states class Main(StatesGroup): menu = State() # Create dialog dialog = Dialog( Window( Const("Welcome!"), Button(Const("Click me"), id="btn"), state=Main.menu, ), ) async def main(): # Initialize bot and dispatcher bot = Bot(token=TOKEN) storage = MemoryStorage() dp = Dispatcher(storage=storage) # Register dialog dp.include_router(dialog) # Setup dialogs bg_manager_factory = setup_dialogs(dp) # Start polling try: await dp.start_polling(bot) finally: await bot.session.close() if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Basic Button with Start Action Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/keyboard/start/index.md Demonstrates how to create a generic Button widget and define an `on_click` handler to manually start a dialog state. Use this when you need custom logic before starting the dialog. ```python from aiogram_dialog.widgets.kbd import Button async def on_click( cq: CallbackQuery, button: Button, dialog_manager: DialogManager ): ... # your actions await dialog_manager.start(SOME_STATE, SOME_DATA) button = Button(..., on_click=on_click) ``` -------------------------------- ### Basic Dialog Setup Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md Demonstrates the basic setup of dialogs with aiogram and aiogram-dialog. Ensure setup_dialogs is called after registering all dialogs. ```python from aiogram import Bot, Dispatcher from aiogram_dialog import Dialog, Window, setup_dialogs # Create dispatcher dp = Dispatcher() # Create and register dialogs my_dialog = Dialog( Window(...), ) dp.include_router(my_dialog) # Setup dialogs - must be called after registering all dialogs bg_manager_factory = setup_dialogs(dp) ``` -------------------------------- ### Starting and Nesting Dialogs Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/transitions/index.md Demonstrates how to start a new dialog from within another, using the `Start` widget and a custom button click handler. Shows the structure of main and sub-dialog definitions. ```python from aiogram.filters.state import StatesGroup, State from aiogram.types import CallbackQuery from aiogram_dialog import Dialog, DialogManager, Window from aiogram_dialog.widgets.kbd import Button, Start from aiogram_dialog.widgets.text import Const class DialogSG(StatesGroup): first = State() class SubDialogSG(StatesGroup): first = State() second = State() async def start_subdialog(callback: CallbackQuery, button: Button, manager: DialogManager): await manager.start(SubDialogSG.second, data={"key": "value"}) dialog = Dialog( Window( Const("Main dialog"), Start(Const("Start 1"), id="start", state=SubDialogSG.first), Button(Const("Start 2"), id="sec", on_click=start_subdialog), state=DialogSG.first, ), ) subdialog = Dialog( Window( Const("Subdialog: first"), state=SubDialogSG.first, ), Window( Const("Subdialog: second"), state=SubDialogSG.second, ), ) ``` -------------------------------- ### Select Widget Usage Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/05-keyboard-widgets-api.md Example demonstrating how to use the Select widget to allow users to choose a product. It includes a getter for products and an on_click handler. ```python async def get_products(**kwargs): return { "products": [ {"id": 1, "name": "Apple"}, {"id": 2, "name": "Banana"}, ] } async def on_product_select(event: CallbackQuery, widget, manager: DialogManager, item_id: int): await manager.update(data={"selected_product": item_id}) Window( Const("Select product:"), Select( Format("{item[name]}"), id="products", item_id_getter=lambda item: item["id"], items=lambda data: data["products"], on_click=on_product_select, ), state=MyState.shop, getter=get_products, ) ``` -------------------------------- ### Install aiogram-dialog Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/quickstart/index.md Install the library using pip. Ensure you have Python and pip installed. ```default pip install aiogram_dialog ``` -------------------------------- ### Dialog Setup with Bot Polling Integration Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md Illustrates integrating dialog setup with bot polling, including setting up storage and the dispatcher. ```python from aiogram import Bot, Dispatcher from aiogram.fsm.storage.memory import MemoryStorage from aiogram_dialog import setup_dialogs TOKEN = "123:ABC" async def main(): bot = Bot(token=TOKEN) storage = MemoryStorage() dp = Dispatcher(storage=storage) # Include dialogs dp.include_router(my_dialog) # Setup dialogs bg_manager_factory = setup_dialogs(dp) # Start polling await dp.start_polling(bot) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Start Dialog Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Initiates a dialog, optionally resetting the stack and passing initial data. This is typically used in response to a message command. ```python @router.message() async def start_dialog(message: Message, dialog_manager: DialogManager): await dialog_manager.start( MyDialog.first_state, data={"triggered_by": "command"}, mode=StartMode.RESET_STACK, ) ``` -------------------------------- ### Dispatcher and Router Setup Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md Demonstrates setting up aiogram-dialog with both a Dispatcher and a Router. The setup process is similar for both, involving including the dialog's router and calling setup_dialogs. ```python # With Dispatcher dp = Dispatcher() dp.include_router(dialog) setup_dialogs(dp) # With Router router = Router() router.include_router(dialog) setup_dialogs(router) ``` -------------------------------- ### Install aiogram_dialog with tools extras Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/helper_tools/index.md Install the library with the necessary extras for using the helper tools. ```bash pip install aiogram_dialog[tools] ``` -------------------------------- ### Start Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/05-keyboard-widgets-api.md Initiates a new dialog. It requires a text, ID, and the initial state of the dialog to start, along with optional data and startup mode. ```APIDOC ## Start ### Description Starts a new dialog. ### Parameters - **text** (TextWidget) - Required - Button label. - **id** (str) - Required - Button ID. - **state** (State) - Required - Initial state of dialog to start. - **data** (Data) - Optional - Data to pass to started dialog. - **on_click** (OnClick | None) - Optional - Optional callback before start. - **show_mode** (ShowMode | None) - Optional - How to show dialog. - **mode** (StartMode) - Optional - How to handle stack (NORMAL, RESET_STACK, NEW_STACK). Default is NORMAL. - **when** (WhenCondition) - Optional - Show/hide condition. - **style** (StyleWidget) - Optional - Button style. ``` -------------------------------- ### Integration Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Example demonstrating how to integrate DialogManager into an aiogram application. ```APIDOC ### Integration Example ```python from aiogram import Router, F from aiogram.types import Message from aiogram_dialog import DialogManager, StartMode router = Router() @router.message() async def start_dialog(message: Message, dialog_manager: DialogManager): await dialog_manager.start( MyDialog.first_state, data={"triggered_by": "command"}, mode=StartMode.RESET_STACK, ) @router.callback_query() async def handle_button(query: CallbackQuery, dialog_manager: DialogManager): if dialog_manager.has_context(): ctx = dialog_manager.current_context() await dialog_manager.switch_to(MyDialog.next_state) ``` ``` -------------------------------- ### ManagedWidget Interface Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/12-style-and-common-widgets.md Demonstrates how to find a managed widget using its ID and interact with its state, such as getting or setting a checked status. ```python # Find widget and get managed wrapper managed = dialog_manager.find("checkbox_id") # Get current state is_checked = await managed.get_checked() # Set state await managed.set_checked(manager.dialog_data, True) ``` -------------------------------- ### Dialog Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/01-dialog-api.md Demonstrates the creation of a dialog with multiple windows, custom callbacks, and data getters. ```python from aiogram.fsm.state import StatesGroup, State from aiogram_dialog import Dialog, Window from aiogram_dialog.widgets.text import Const, Format from aiogram_dialog.widgets.kbd import Button, Next class UserFlow(StatesGroup): greeting = State() confirmation = State() async def on_dialog_start(data, manager): print("User started flow") async def get_user_name(**kwargs): return {"name": "John"} dialog = Dialog( Window( Format("Hello, {name}!"), Button(Const("Continue"), id="btn_next"), state=UserFlow.greeting, getter=get_user_name, ), Window( Const("Are you sure?"), Next(Const("Yes")), state=UserFlow.confirmation, ), on_start=on_dialog_start, launch_mode=LaunchMode.SINGLE_TOP, ) ``` -------------------------------- ### ListGroup with URL Buttons Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/keyboard/list_group/index.md This example demonstrates how to use ListGroup to display a list of products, where each product is represented by a URL button. It shows how to define the items, get item IDs, and format the button text and URL using item data. The `getter` function provides the `products` data to the window. ```Python from aiogram import F from aiogram.filters.state import State, StatesGroup from aiogram_dialog import ( Window, Dialog, ) from aiogram_dialog.widgets.kbd import ( Url, ListGroup, SwitchTo, Back, ) from aiogram_dialog.widgets.text import Const, Format class SG(StatesGroup): main = State() result = State() success = F["products"] fail = ~success async def actions(**kwargs): products = [ {"id": 1, "name": "Ferrari", "category": "car", "url": "https://www.ferrari.com/"}, {"id": 2, "name": "Detroit", "category": "game", "url": "https://wikipedia.org/wiki/Detroit:_Become_Human"}, ] return { "products": products, } dialog = Dialog( Window( Const("Click find products to show a list of available products:"), SwitchTo(Const("Find products"), id="search", state=SG.result), state=SG.main, ), Window( Const("Searching results:", when=success), Const("Search did not return any results", when=fail), ListGroup( Url( Format("{item[name]} ({item[category]})"), Format("{item[url]}"), id="url", ), id="select_search", item_id_getter=lambda item: item["id"], items="products", ), Back(Const("Back")), state=SG.result, getter=actions, ) ) ``` -------------------------------- ### Configuring Dialog Start Mode Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/transitions/index.md Demonstrates setting the `mode` for starting a dialog using `dialog_manager.start`, with `StartMode.RESET_STACK` to clear the existing stack before launching. ```python async def start(message: Message, dialog_manager: DialogManager): await dialog_manager.start(..., mode=StartMode.RESET_STACK) ``` -------------------------------- ### Get Start Data Property Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Retrieve the data that was passed when the dialog was initially started. ```python @property def start_data(self) -> Data ``` -------------------------------- ### Custom DialogManagerFactory Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md An example of creating a custom DialogManagerFactory by inheriting from the protocol and implementing the create method. ```python from aiogram_dialog.api.internal import DialogManagerFactory class CustomManagerFactory(DialogManagerFactory): async def create( self, router: Router, middleware_data: dict, registry: DialogRegistryProtocol, ) -> DialogManager: # Create custom DialogManager ... setup_dialogs( dp, dialog_manager_factory=CustomManagerFactory(), ) ``` -------------------------------- ### Start Button Widget Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/keyboard/start/index.md Shows the usage of the specialized Start widget, which directly configures the dialog state and data to be started upon click. This is a more concise way to initiate dialogs compared to a generic Button. ```python from aiogram_dialog.widgets.kbd import Button, Start async def on_click( cq: CallbackQuery, button: Button, dialog_manager: DialogManager ): ... # your actions button = Start(..., state=SOME_STATE, data=SOME_DATA, on_click=on_click) ``` -------------------------------- ### Complete aiogram-dialog Bot Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/quickstart/index.md A comprehensive example combining all the previous steps to create a functional Telegram bot with a simple dialog. This includes imports, state definition, window creation, dialog setup, command handling, and bot execution. ```python from aiogram import Bot, Dispatcher from aiogram.filters import Command from aiogram.filters.state import State, StatesGroup from aiogram.fsm.storage.memory import MemoryStorage from aiogram.types import Message from aiogram_dialog import ( Dialog, DialogManager, setup_dialogs, StartMode, Window, ) from aiogram_dialog.widgets.kbd import Button from aiogram_dialog.widgets.text import Const class MySG(StatesGroup): main = State() main_window = Window( Const("Hello, unknown person"), Button(Const("Useless button"), id="nothing"), state=MySG.main, ) dialog = Dialog(main_window) storage = MemoryStorage() bot = Bot(token='BOT TOKEN HERE') dp = Dispatcher(storage=storage) dp.include_router(dialog) setup_dialogs(dp) @dp.message(Command("start")) async def start(message: Message, dialog_manager: DialogManager): await dialog_manager.start(MySG.main, mode=StartMode.RESET_STACK) if __name__ == '__main__': dp.run_polling(bot, skip_updates=True) ``` -------------------------------- ### BgManagerFactory Usage Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md Demonstrates how to use the BgManagerFactory, returned by setup_dialogs, to create background managers for operations outside the event loop. ```python # In background task or webhook handler async def notify_user(user_id: int, bg_manager_factory: BgManagerFactory, bot: Bot): manager = bg_manager_factory.bg( bot=bot, user_id=user_id, chat_id=user_id, # Same as user_id for private chats ) await manager.update(data={"notification": "You have new message"}) ``` -------------------------------- ### Example Usage of Progress Widget Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/04-text-widgets-api.md Demonstrates how to use the Progress widget within a Window, providing a getter function to supply progress data. ```python async def get_progress(**kwargs): return { "current": 5, "total": 10, } Window( Progress( text_getter=lambda data, _: f"Progress: {data['current']}/{data['total']}", value_getter=lambda data: data["current"], max_value_getter=lambda data: data["total"], ), state=MyState.progress, getter=get_progress, ) ``` -------------------------------- ### Custom Dialog Setup Configuration Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md Shows how to set up dialogs with custom components like event isolation and a global getter. ```python from aiogram.fsm.storage.memory import MemoryStorage, SimpleEventIsolation from aiogram_dialog import setup_dialogs # Register dialogs... # Setup with custom components bg_manager_factory = setup_dialogs( dp, events_isolation=SimpleEventIsolation(), getter=async def global_getter(**kwargs): return {"app_version": "1.0.0"} ) ``` -------------------------------- ### Start New Dialog Button Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/05-keyboard-widgets-api.md Use the Start widget to initiate a new dialog. It requires text, ID, and the initial state of the dialog to start. You can also pass data and specify the start mode. ```python class Start(EventProcessorButton): def __init__( self, text: TextWidget, id: str, state: State, data: Data = None, on_click: OnClick | None = None, show_mode: ShowMode | None = None, mode: StartMode = StartMode.NORMAL, when: WhenCondition = None, style: StyleWidget = EMPTY_STYLE, ) ``` ```python Window( Const("Open submenu"), Start( Const("Settings"), id="settings", state=SettingsDialog.main, mode=StartMode.NORMAL, ), state=MainDialog.menu, ) ``` -------------------------------- ### Start Dialog with Command Handler Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/quickstart/index.md Create a command handler to initiate the dialog. Use DialogManager to start the dialog and ensure `mode=StartMode.RESET_STACK` is set to prevent dialog stacking. ```python from aiogram.filters import Command from aiogram.types import Message from aiogram_dialog import DialogManager, StartMode @dp.message(Command("start")) async def start(message: Message, dialog_manager: DialogManager): # Important: always set `mode=StartMode.RESET_STACK` you don't want to stack dialogs await dialog_manager.start(MySG.main, mode=StartMode.RESET_STACK) ``` -------------------------------- ### Counter Widget Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/keyboard/counter/index.md Demonstrates the creation and basic configuration of a Counter widget, including setting a default value, maximum value, and a click handler for the text display. ```python from aiogram_dialog.widgets.kbd import ManagedCounter, Counter async def on_text_click( event: CallbackQuery, widget: ManagedCounter, dialog_manager: DialogManager, ) -> None: await event.answer(f"Value: {widget.get_value()}") counter = Counter( id="someid", default=0, max_value=1000, on_text_click=on_text_click, ) ``` -------------------------------- ### Keyboard Widgets Examples Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/11-quick-reference.md Examples of common keyboard widgets for user interaction in aiogram-dialog. ```python Button(Const("Click"), id="btn") ``` ```python SwitchTo(Const("Next"), id="next", state=...) ``` ```python Next(Const("Next")) ``` ```python Back(Const("Back")) ``` ```python Start(Const("Menu"), id="menu", state=...) ``` ```python Cancel(Const("Cancel")) ``` ```python Select(..., items=...) ``` ```python Multiselect(..., items=...) ``` ```python Group(btn1, btn2, btn3) ``` ```python Column(btn1, btn2) ``` ```python Calendar(id="cal") ``` ```python Counter(id="count") ``` ```python Checkbox(checked_text, unchecked_text, id="check") ``` -------------------------------- ### Custom Media Storage Setup Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/08-media-and-input-widgets.md Configure custom media storage for aiogram dialogs. Pass an instance of your custom storage class to setup_dialogs. ```python setup_dialogs( dp, media_id_storage=CustomMediaStorage(), ) ``` -------------------------------- ### StyleWidget Usage Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/08-media-and-input-widgets.md Shows a basic example of applying a style to a Button widget. The style can be a predefined string, such as 'destructive', to control button appearance. ```python from aiogram_dialog.widgets.style import StyleWidget # Style can be a fixed string button = Button(..., style="destructive") ``` -------------------------------- ### Multiselect Widget Usage Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/05-keyboard-widgets-api.md Example demonstrating the Multiselect widget for choosing multiple items. It includes a handler to toggle the checked state of items. ```python async def on_selection_changed(event, widget, manager: DialogManager, item_id: str): widget.set_checked(manager.dialog_data, item_id, not widget.is_checked(manager.dialog_data, item_id)) Window( Const("Select items:"), Multiselect( Format("☑ {item}" if checked else "☐ {item}"), id="items", item_id_getter=lambda x: x, items=lambda data: data["available_items"], on_state_changed=on_selection_changed, ), state=MyState.select, ) ``` -------------------------------- ### When Condition Usage Examples Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/12-style-and-common-widgets.md Provides examples of different ways to define 'when' conditions: lambda functions, static booleans, and separate functions. ```python # Lambda condition when=lambda data, widget, manager: data["count"] > 0 # Static boolean when=True # Condition function def should_show(data: dict, widget, manager: DialogManager) -> bool: return data.get("show_details", False) when=should_show # No condition (always shown) when=None ``` -------------------------------- ### Example of Conditional Rendering in a Window Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/04-text-widgets-api.md Demonstrates conditional rendering of a 'Balance' field based on its presence in the provided data. ```python Window( Const("Welcome!"), Format( "Balance: ${balance}", when=lambda data, *_: data.get("balance") is not None, ), state=MyState.main, getter=get_data, ) ``` -------------------------------- ### Setup Dialogs Middleware Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/quickstart/index.md Call `setup_dialogs` to register necessary middlewares and core handlers for aiogram-dialog with your Dispatcher. ```python from aiogram_dialog import setup_dialogs setup_dialogs(dp) ``` -------------------------------- ### Group Widget Usage Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/05-keyboard-widgets-api.md Example showing how to use the Group widget to display buttons 'Option A', 'Option B', and 'Option C' in a single row. ```python Window( Const("Choose:"), Group( Button(Const("Option A"), id="a"), Button(Const("Option B"), id="b"), Button(Const("Option C"), id="c"), ), state=MyState.choose, ) ``` -------------------------------- ### Starting Background Task with Progress Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/text/progress/index.md This snippet illustrates how to initiate a background task for progress updates using `manager.bg()`. It specifies user and chat IDs, a stack ID, and loads existing data, then starts a specific background state. ```python async def start_bg(callback: CallbackQuery, button: Button, manager: DialogManager): bg = manager.bg( user_id=callback.from_user.id, chat_id=callback.message.chat.id, stack_id="progress_stack", load=True, ) await bg.start(Bg.progress) asyncio.create_task(background(callback, bg)) ``` -------------------------------- ### Calendar Widget Usage Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/05-keyboard-widgets-api.md Example demonstrating the Calendar widget for picking a date. The `on_date_selected` handler updates dialog data with the ISO format of the selected date. ```python async def on_date_selected(event, widget, manager, date): await manager.update(data={"selected_date": date.isoformat()}) Window( Const("Pick a date:"), Calendar(id="calendar", on_click=on_date_selected), state=MyState.pick_date, ) ``` -------------------------------- ### Start a New Dialog Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Initiates a new dialog and displays its first window. Use RESET_STACK mode to clear the existing dialog stack before starting. ```python async def handle_start(message: Message, dialog_manager: DialogManager): await dialog_manager.start( MainMenu.greeting, data={"user_id": message.from_user.id}, mode=StartMode.RESET_STACK, ) ``` -------------------------------- ### TextInput Widget Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/input/text_input/index.md Demonstrates the usage of the TextInput widget for capturing country and age, including type validation for age. The example sets up multiple windows for different input stages and a final window to display the collected information. ```python from typing import Any from aiogram.fsm.state import State, StatesGroup from aiogram.types import Message from aiogram_dialog import ( Dialog, DialogManager, Window, ) from aiogram_dialog.widgets.input import TextInput from aiogram_dialog.widgets.kbd import Next from aiogram_dialog.widgets.text import Const, Jinja class SG(StatesGroup): age = State() country = State() result = State() async def error( message: Message, dialog_: Any, manager: DialogManager, error_: ValueError ): await message.answer("Age must be a number!") async def getter(dialog_manager: DialogManager, **kwargs): return { "age": dialog_manager.find("age").get_value(), "country": dialog_manager.find("country").get_value(), } dialog = Dialog( Window( Const("Enter your country:"), TextInput(id="country", on_success=Next()), state=SG.country, ), Window( Const("Enter your age:"), TextInput( id="age", on_error=error, on_success=Next(), type_factory=int, ), state=SG.age, ), Window( Jinja( "You entered:\n\n" "age: {{age}}\n" "country: {{country}}\n" ), state=SG.result, getter=getter, parse_mode="html", ), ) ``` -------------------------------- ### Dialog Lifecycle Registration and Setup Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/11-quick-reference.md Register the dialog router with dp.include_router and set up dialogs using setup_dialogs(dp). These are the initial steps for integrating aiogram-dialog into your application. ```python # 1. Register: dp.include_router(dialog) # 2. Setup: setup_dialogs(dp) ``` -------------------------------- ### DialogManager.start Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Starts a new dialog and displays its initial window. It can optionally accept data, specify how to handle an existing dialog stack, and define how the dialog should be shown. ```APIDOC ## DialogManager.start ### Description Start a new dialog and show its first window. ### Method `start` ### Parameters - **state** (State) - Required - Initial FSM state (usually first window state) - **data** (dict or None) - Optional - Optional data passed to dialog's on_start callback - **mode** (StartMode) - Optional - How to handle existing stack - NORMAL, RESET_STACK, or NEW_STACK - **show_mode** (ShowMode or None) - Optional - How to show the dialog - AUTO, EDIT, SEND, DELETE_AND_SEND, or NO_UPDATE - **access_settings** (AccessSettings or None) - Optional - Access control settings for stack ### Raises Exception if state is not registered or dialog not found ### Example ```python async def handle_start(message: Message, dialog_manager: DialogManager): await dialog_manager.start( MainMenu.greeting, data={"user_id": message.from_user.id}, mode=StartMode.RESET_STACK, ) ``` ``` -------------------------------- ### StartMode Values Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Defines the different modes for starting a dialog. ```APIDOC ### StartMode Values - **NORMAL**: Continue from current state without resetting stack - **RESET_STACK**: Clear existing stack and start fresh - **NEW_STACK**: Create new stack while retaining old one ``` -------------------------------- ### Register Dialog with Dispatcher Source: https://github.com/tishka17/aiogram_dialog/blob/develop/README.md Include the created dialog router into the Dispatcher and call setup_dialogs to enable dialog functionality. This setup is crucial for the dialogs to operate correctly. ```python from aiogram import Dispatcher from aiogram_dialog import setup_dialogs dp = Dispatcher(storage=storage) # create as usual dp.include_router(dialog) setup_dialogs(dp) ``` -------------------------------- ### Dialog Lifecycle Start and Handling Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/11-quick-reference.md Initiate a dialog with manager.start(state) and handle events through callbacks like on_start, on_close, and event handlers for user interactions. ```python # 3. Start: await manager.start(state) # 4. On Start: on_start callback (if defined) # 5. Render: Window renders text, keyboard, media # 6. Show: Message sent or edited # 7. Handle Event: User clicks button or sends message # 8. Process: Window processes event # 9. Close: await manager.done() or Cancel() # 10. On Close: on_close callback (if defined) ``` -------------------------------- ### Setup Dialogs Function Signature Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md The main function to initialize the dialog system with a dispatcher. It accepts various optional parameters for customization. ```python def setup_dialogs( router: Router, *, dialog_manager_factory: DialogManagerFactory | None = None, message_manager: MessageManagerProtocol | None = None, media_id_storage: MediaIdStorageProtocol | None = None, stack_access_validator: StackAccessValidator | None = None, events_isolation: BaseEventIsolation | None = None, getter: DataGetter | None = None, ) -> BgManagerFactory ``` -------------------------------- ### JSON-Serializable Dialog Data Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/13-data-flows-and-context.md Demonstrates how to structure dialog data to be JSON-serializable by using primitive types. ```python dialog_data = { "name": "John", "age": 25, "tags": ["admin", "verified"], "score": 95.5, } ``` -------------------------------- ### Setup Jinja2 Environment Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/04-text-widgets-api.md Globally configures the Jinja2 environment for use with the Jinja text widget. Allows specifying a custom environment or loader. ```python def setup_jinja( env: Environment | None = None, loader: BaseLoader | None = None, ) -> None ``` ```python from jinja2 import Environment, FileSystemLoader from aiogram_dialog.widgets.text import setup_jinja setup_jinja( loader=FileSystemLoader("templates/"), ) ``` -------------------------------- ### Setup aiogram Dispatcher and Dialogs Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/00-core-concepts.md This snippet shows how to create an asynchronous dispatcher and include dialogs in your aiogram bot. Ensure you import the necessary components. ```python from aiogram import Dispatcher from aiogram_dialog import setup_dialogs, Dialog, Window dp = Dispatcher() dialog = Dialog(...) dp.include_router(dialog) setup_dialogs(dp) ``` -------------------------------- ### Show Link Preview Above Text Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/08-media-and-input-widgets.md Illustrates configuring the LinkPreview widget to display the URL preview above the message text by setting `show_above_text` to True. ```python Window( Format("Featured: {url}"), LinkPreview(show_above_text=True), state=MyState.featured, ) ``` -------------------------------- ### Select Widget Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/keyboard/select/index.md Demonstrates how to create and configure a Select widget. It uses a Format for button text, specifies an ID, an item ID getter, defines the source of items from window data, and sets an on-click handler. ```python import operator from typing import Any from aiogram.types import CallbackQuery from aiogram_dialog import DialogManager from aiogram_dialog.widgets.kbd import Select from aiogram_dialog.widgets.text import Format # let's assume this is our window data getter async def get_data(**kwargs): fruits = [ ("Apple", '1'), ("Pear", '2'), ("Orange", '3'), ("Banana", '4'), ] return { "fruits": fruits, "count": len(fruits), } async def on_fruit_selected(callback: CallbackQuery, widget: Any, manager: DialogManager, item_id: str): print("Fruit selected: ", item_id) fruits_kbd = Select( Format("{item[0]} ({pos}/{data[count]})"), # E.g `✓ Apple (1/4)` id="s_fruits", item_id_getter=operator.itemgetter(1), # each item is a tuple with id on a first position items="fruits", # we will use items from window data at a key `fruits` on_click=on_fruit_selected, ) ``` -------------------------------- ### Get Current Dialog Context Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Retrieves the current dialog's context, including its state and start data. Raises `NoContextError` if no dialog is active. ```python ctx = dialog_manager.current_context() print(ctx.state) # Current FSM state print(ctx.start_data) # Data passed to start() ``` -------------------------------- ### Handle Button Callback Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/03-dialog-manager-api.md Handles callback queries from buttons within a dialog, allowing for state transitions. It checks for an existing dialog context before switching states. ```python @router.callback_query() async def handle_button(query: CallbackQuery, dialog_manager: DialogManager): if dialog_manager.has_context(): ctx = dialog_manager.current_context() await dialog_manager.switch_to(MyDialog.next_state) ``` -------------------------------- ### Prevent Unregistered Dialog Error Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/09-errors-and-exceptions.md Ensure dialogs are correctly registered with the Dispatcher and `setup_dialogs` is called to prevent `UnregisteredDialogError`. This example shows the necessary setup steps. ```python from aiogram import Dispatcher from aiogram_dialog import setup_dialogs dp = Dispatcher() dp.include_router(my_dialog) # Must register setup_dialogs(dp) # Must call setup try: await dialog_manager.start(MyDialog.state) except UnregisteredDialogError as e: print(f"Dialog not found: {e}") ``` -------------------------------- ### Serve Dialog Previews via Web Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/helper_tools/index.md Serve dialog previews directly using the command line interface. Run `aiogram-dialog-preview` with the path to your Dispatcher, Router, or Dialog object. ```bash aiogram-dialog-preview example/subdialog:dialog_router ``` -------------------------------- ### Define Product List and Detail Windows Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/02-window-api.md Example of defining two windows for a product dialog: one for listing products and another for displaying product details. It includes state definitions, data getters, and widget configurations. ```python from aiogram.fsm.state import StatesGroup, State from aiogram_dialog import Window from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.kbd import Button, Select from aiogram_dialog.widgets.media import StaticMedia class ProductView(StatesGroup): list = State() detail = State() async def get_products(**kwargs): return {"products": ["Product A", "Product B"]} async def get_product_detail(item_id: str, **kwargs): products = {"1": "Product A", "2": "Product B"} return {"product_name": products.get(item_id, "Unknown")} dialog_windows = [ Window( Const("Available products:"), Select( Format("{item}"), id="products", item_id_getter=lambda x: str(x), items=lambda data: enumerate(data["products"]), ), state=ProductView.list, getter=get_products, ), Window( Format("Product: {product_name}"), Button(Const("Back"), id="back"), state=ProductView.detail, getter=get_product_detail, parse_mode="HTML", ), ] ``` -------------------------------- ### setup_dialogs Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/07-setup-and-configuration.md Main function to initialize the dialog system with your dispatcher. It registers dialogs and sets up the middleware pipeline. ```APIDOC ## setup_dialogs ### Description Main setup function to initialize dialog system with dispatcher. Registers dialogs with Dispatcher and sets up middleware pipeline. ### Parameters - **router** (Router) - Required - Aiogram router or dispatcher to register dialogs with - **dialog_manager_factory** (DialogManagerFactory | None) - Optional - Custom factory for creating DialogManager instances - **message_manager** (MessageManagerProtocol | None) - Optional - Custom message manager for sending/editing messages - **media_id_storage** (MediaIdStorageProtocol | None) - Optional - Custom storage for media IDs to avoid reuploads - **stack_access_validator** (StackAccessValidator | None) - Optional - Custom validator for access control - **events_isolation** (BaseEventIsolation | None) - Optional - FSM isolation strategy - **getter** (DataGetter | None) - Optional - Global getter applied to all dialogs ### Returns Returns `BgManagerFactory` for creating background managers outside of event handling. ### Basic Setup ```python from aiogram import Bot, Dispatcher from aiogram_dialog import Dialog, Window, setup_dialogs # Create dispatcher dp = Dispatcher() # Create and register dialogs my_dialog = Dialog( Window(...), ) dp.include_router(my_dialog) # Setup dialogs - must be called after registering all dialogs bg_manager_factory = setup_dialogs(dp) ``` ### Custom Configuration ```python from aiogram.fsm.storage.memory import MemoryStorage, SimpleEventIsolation from aiogram_dialog import setup_dialogs # Register dialogs... # Setup with custom components bg_manager_factory = setup_dialogs( dp, events_isolation=SimpleEventIsolation(), getter=async def global_getter(**kwargs): return {"app_version": "1.0.0"} ) ``` ### Integration with Bot Polling ```python from aiogram import Bot, Dispatcher from aiogram.fsm.storage.memory import MemoryStorage from aiogram_dialog import setup_dialogs TOKEN = "123:ABC" async def main(): bot = Bot(token=TOKEN) storage = MemoryStorage() dp = Dispatcher(storage=storage) # Include dialogs dp.include_router(my_dialog) # Setup dialogs bg_manager_factory = setup_dialogs(dp) # Start polling await dp.start_polling(bot) if __name__ == "__main__": asyncio.run(main()) ``` ``` -------------------------------- ### Text Widgets Examples Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/11-quick-reference.md Examples of common text widgets used in aiogram-dialog for displaying static or dynamic text. ```python Const("Hello") ``` ```python Format("Name: {name}") ``` ```python Jinja("{% for x in items %}...") ``` ```python Case("status", {"active": ..., "done": ...}) ``` ```python List(items=..., item_formatter=...) ``` ```python Multi(Const("A"), Format("{b}"), sep="\n") ``` -------------------------------- ### Check Stack Depth Before Starting Submenu Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/09-errors-and-exceptions.md Prevent exceeding maximum stack depth by checking before starting a new submenu. ```python MAX_STACK_DEPTH = 5 async def start_submenu(dialog_manager: DialogManager): stack = dialog_manager.current_stack() if len(stack.contexts) >= MAX_STACK_DEPTH: await dialog_manager.show(show_mode=ShowMode.NO_UPDATE) return await dialog_manager.start(Submenu.main) ``` -------------------------------- ### Basic StaticMedia Widget Usage Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/widgets/media/static_media/index.md Demonstrates how to use the StaticMedia widget to display a photo from a local file path. Ensure the path is correct and accessible. ```python from aiogram.types import ContentType from aiogram_dialog import Window from aiogram_dialog.widgets.media import StaticMedia windows = Window( StaticMedia( path="/home/tishka17/python_logo.png", type=ContentType.PHOTO, ), ) ``` -------------------------------- ### Window Constructor Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/02-window-api.md Initializes a new Window instance. It takes various widgets, an FSM state, and optional parameters for data fetching, result processing, markup generation, and message formatting. ```APIDOC ## Window Constructor ### Description Initializes a new Window instance. It takes various widgets, an FSM state, and optional parameters for data fetching, result processing, markup generation, and message formatting. ### Parameters - **widgets** (*WidgetSrc): Variable-length argument of UI widgets. Widgets are parsed to identify text, keyboard, message handler, media, and link preview. - **state** (State): FSM state for this window. Must belong to StatesGroup used by parent dialog. - **getter** (Awaitable or None): Async function returning dict of data for rendering text and keyboards. Called before each render. - **on_process_result** (Callable[[Data, Any, DialogManager], Awaitable] or None): Callback when nested dialog returns result. - **markup_factory** (MarkupFactory): Factory for rendering keyboard markup. Default uses Telegram inline keyboards. - **parse_mode** (str or None): Text parse mode for message. Values: "HTML", "Markdown", "MarkdownV2", or None. - **protect_content** (bool or None): Whether to protect message from forwarding/copying. - **disable_web_page_preview** (bool or None): Deprecated. Use LinkPreview widget instead. Disables preview for URLs in text. - **preview_add_transitions** (list[Keyboard] or None): Additional keyboard transitions to show in offline preview. - **preview_data** (Awaitable or None): Getter used only for preview generation, separate from runtime getter. ``` -------------------------------- ### StaticMedia Widget - From File Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/08-media-and-input-widgets.md Use StaticMedia to display a document from a local file path. Specify the correct file path and content type. ```python Window( Const("Catalog:"), StaticMedia( path="./catalog.pdf", type=ContentType.DOCUMENT, ), state=MyState.catalog, ) ``` -------------------------------- ### Handle Dialog Start Errors Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/09-errors-and-exceptions.md Safely start a dialog and handle potential errors like unregistered dialogs or general dialogs errors. ```python async def start_dialog(message: Message, dialog_manager: DialogManager): try: await dialog_manager.start( MyDialog.greeting, mode=StartMode.RESET_STACK, ) except UnregisteredDialogError: await message.reply("Dialog not configured") except DialogsError as e: await message.reply(f"Error: {e}") ``` -------------------------------- ### setup_jinja Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/04-text-widgets-api.md Configures the Jinja2 environment globally for use with Jinja text widgets. Allows specifying a custom environment or loader. ```APIDOC ## Function: setup_jinja ### Description Configures the global Jinja2 environment. This function allows you to set up a custom Jinja2 Environment or specify a template loader for all Jinja widgets. ### Parameters - **env** (Environment | None) - Optional - A custom Jinja2 Environment instance. - **loader** (BaseLoader | None) - Optional - A custom Jinja2 template loader. ``` -------------------------------- ### Window Methods Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/02-window-api.md Includes methods for retrieving the window's state, finding widgets, and rendering text, keyboard, and media. ```APIDOC ## Window Methods ### get_state ```python def get_state(self) -> State ``` Returns the FSM state for this window. ### find ```python def find(self, widget_id: str) -> Widget | None ``` Find a widget by ID within this window's widget tree. **Parameters**: - `widget_id` (str): The widget ID to search for **Returns**: Widget instance or None ### render_text ```python async def render_text(self, data: dict, manager: DialogManager) -> str ``` Render the text for this window. **Parameters**: - `data` (dict): Data dict from getter - `manager` (DialogManager): Dialog manager **Returns**: Rendered text string ### render_kbd ```python async def render_kbd(self, data: dict, manager: DialogManager) -> MarkupVariant ``` Render the keyboard for this window. **Parameters**: - `data` (dict): Data dict from getter - `manager` (DialogManager): Dialog manager **Returns**: InlineKeyboard or other markup ### render_media ```python async def render_media(self, data: dict, manager: DialogManager) -> MediaAttachment | None ``` Render media attachment if present. **Parameters**: - `data` (dict): Data dict from getter - `manager` (DialogManager): Dialog manager **Returns**: MediaAttachment or None ``` -------------------------------- ### Print Current Dialog and Start Data Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/13-data-flows-and-context.md A handler function to print the current dialog data and start data managed by the DialogManager for debugging purposes. ```python async def debug_handler(event, button, manager: DialogManager): print(f"Dialog data: {manager.dialog_data}") print(f"Start data: {manager.start_data}") ctx = manager.current_context() print(f"Context: state={ctx.state}, id={ctx.id}") ``` -------------------------------- ### Initialize Bot and Dispatcher Source: https://github.com/tishka17/aiogram_dialog/blob/develop/docs/quickstart/index.md Set up your aiogram Bot and Dispatcher instances. Proper storage is crucial as aiogram-dialog uses FSMContext internally. ```python from aiogram import Bot, Dispatcher from aiogram.fsm.storage.memory import MemoryStorage storage = MemoryStorage() bot = Bot(token='BOT TOKEN HERE') dp = Dispatcher(storage=storage) ``` -------------------------------- ### Simple String TextInput Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/08-media-and-input-widgets.md Demonstrates a basic TextInput widget configured to capture a user's name as a string. The on_success callback updates dialog data with the provided name. ```python async def on_name_input(message: Message, widget, manager: DialogManager, data: str): await manager.update(data={"user_name": data}) Window( Const("Enter your name:"), TextInput( id="name_input", on_success=on_name_input, ), state=MyState.name, ) ``` -------------------------------- ### Window Constructor Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/02-window-api.md Initializes a new Window instance with various configuration options for widgets, state, rendering, and event handling. ```python def __init__( self, *widgets: WidgetSrc, state: State, getter: GetterVariant = None, on_process_result: OnResultEvent | None = None, markup_factory: MarkupFactory = _DEFAULT_MARKUP_FACTORY, parse_mode: str | None = UNSET_PARSE_MODE, disable_web_page_preview: bool | None = None, protect_content: bool | None = None, preview_add_transitions: list[Keyboard] | None = None, preview_data: GetterVariant = None, ) ``` -------------------------------- ### Photo Upload MessageInput Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/08-media-and-input-widgets.md Example of using MessageInput to capture a photo upload. The on_success callback extracts the file ID of the last photo in the message. ```python async def on_photo(message: Message, widget, manager: DialogManager): if message.photo: photo_id = message.photo[-1].file_id await manager.update(data={"photo_id": photo_id}) Window( Const("Send your photo:"), MessageInput( id="photo_input", on_success=on_photo, ), state=MyState.photo, ) ``` -------------------------------- ### TextInput with Filter Example Source: https://github.com/tishka17/aiogram_dialog/blob/develop/_autodocs/08-media-and-input-widgets.md Illustrates using a filter with TextInput to validate input before processing. This example ensures the input contains an '@' symbol, suitable for email validation. ```python async def validate_email(message: Message, **kwargs) -> bool: return "@" in message.text async def on_email_input(message: Message, widget, manager: DialogManager, data: str): await manager.update(data={"email": data}) Window( Const("Enter email:"), TextInput( id="email_input", filter=validate_email, on_success=on_email_input, ), state=MyState.email, ) ```