aiogram_dialog

repository·develop·Indexed 21 days ago

https://github.com/tishka17/aiogram_dialog

A Telegram bot UI framework built on top of aiogram for developing interactive messages and menus. It uses a GUI-like approach to separate data retrieval (getters), UI rendering (widgets), and logic (handlers), allowing for reusable components and stateful user interfaces. Key features include Window and Dialog management, support for complex widgets like Multiselect and Calendar, and tools for generating state diagrams and HTML previews.

Tokens
30.3K
Snippets
105
Records
157
Agent score
74%

What's inside aiogram_dialog

  1. Choose a text widget for rendering content

    develop

    When you need to render text within a dialog, select the appropriate widget based on your requirements:

    • Const: Use for static text that requires no modifications.
    • Format: Use to format text dynamically using the format function.
    • Multi: Use to display multiple text segments joined by a specific separator.
    • Case: Use to display one of several text options based on a specific condition.
    • Progress: Use to render a visual progress bar.
    • List: Use to display a dynamic group of texts (behaves similarly to a Select keyboard widget).
    • Jinja: Use to render HTML content using the jinja2 templating engine.
  2. Understand the types of widgets in aiogram_dialog

    develop

    Aiogram Dialog uses widgets to represent different types of content and interactions within a dialog. There are five primary built-in widget types:

    • Texts: Used to render text anywhere in the dialog (e.g., message text, button titles).
    • Keyboards: Represent components of an InlineKeyboard.
    • Media: Represent media attachments (images, videos, etc.) attached to a message.
    • Input: Used to process incoming messages from the user. These widgets have no visual representation in the message.
    • Link Preview: Used to manage how link previews appear in messages.

    You can also create Custom Widgets to implement specialized behavior.

  3. Understand the dialog task stack

    develop

    The dialog stack manages multiple opened dialogs by 'stacking' them. Only the top-most dialog in the stack is visible and interactive.

    • Adding to stack: Every time you start a dialog, a new task is added to the top of the stack with a new dialog context.
    • Removing from stack: When a dialog is closed, its task and context are removed, revealing the dialog underneath.
    • Context Isolation: Each dialog in the stack is identified by an intent_id. You can start the same dialog multiple times, creating multiple independent contexts.
    • Limits: A single stack can hold a maximum of 100 dialogs simultaneously.
    • Memory Management: Be careful when restarting dialogs; ensure you clear the stack if necessary to avoid memory leaks.
  4. Update dialogs using ShowMode

    develop

    To control how a dialog is updated in aiogram_dialog, use the ShowMode enum. ShowMode determines the behavior of the message update (e.g., whether it edits the existing message or sends a new one).

    You can apply a ShowMode in two ways:

    1. Use the show_mode setter on the DialogManager instance.
    2. Pass the show_mode argument directly into DialogManager methods such as .start(), .update(), or .switch_to().

    Important: A specified ShowMode only applies to the next update. After that single update is performed, the manager automatically reverts to AUTO mode.

    # Example of passing show_mode to a DialogManager method
    await dialog_manager.start(show_mode=ShowMode.EDIT)
    
    # Example of using the show_mode setter
    dialog_manager.show_mode = ShowMode.NEW
    await dialog_manager.update()
  5. Handle forbidden interactions in groups

    develop
    When a user attempts to interact with a dialog they are not permitted to access, the event is not routed to the dialogs. You can detect and handle these forbidden interactions in your aiogram handlers by checking for the aiogd_stack_forbidden key within the middleware data.
  6. Use the Select widget to create dynamic button groups

    develop

    The Select widget acts as a group of buttons where the data is provided dynamically. It is primarily used for selecting an item from a list. Unlike static button groups, the text of the buttons in a Select widget is typically dynamic.

    When rendering the text for an item, the widget provides a dictionary containing:

    • item: The current item itself.
    • data: The original window data.
    • pos: The position of the item in the current list (starting from 1).
    • pos0: The position of the item in the current list (starting from 0).

    Note: Select places all items in a single row. If you need a different layout, wrap the widget in a group or column widget.

    # Example of how Select might be used (based on documentation description)
    from aiogram_dialog.widgets.kbd import Select
    from aiogram_dialog.filters import F
    
    # Example using a magic filter to get items from window data
    select_widget = Select(
        items=F["fruits"],
        id="fruit_select",
        format="{item}",  # Uses the 'item' key from the rendering dictionary
        on_click=OnItemClick()
    )
  7. Define a default option in the Case widget

    develop

    When using the Case widget, you can provide a fallback text that will be displayed if the selector result does not match any of the keys provided in the texts dictionary. To do this, use the ... (Ellipsis object) as a key in the texts dictionary.

    Case(
        texts={
            'active': 'The status is active',
            'inactive': 'The status is inactive',
            ...: 'Unknown status'
        },
        selector='status'
    )
  8. How widget visibility and actions work

    develop

    Widgets in aiogram_dialog are categorized into two functional types:

    1. Whenable: Widgets that can be conditionally shown or hidden based on data or specific conditions. Currently, all widgets support this capability.
    2. Actionable: Widgets that trigger an action. Currently, this applies to keyboard widgets.

    Key requirements for Actionable widgets:

    • They must have a unique id.
    • If you are using stateful widgets (like Checkboxes) or buttons with different behaviors, you must assign them unique IDs within the dialog so they can be identified and managed.
  9. Pass data between dialogs

    develop

    Data can be passed between dialogs using the following patterns:

    • Input (Passing data to a new dialog): Pass data via dialog_manager.start(..., data="your_data"). The receiving dialog can read this using dialog_manager.start_data.
    • Output (Passing data back to a parent): Pass data via dialog_manager.done(result="your_result"). The parent dialog can read this as a parameter in its on_process_result callback.
  10. Use the Column widget for vertical layouts

    develop

    The Column widget is used to arrange multiple widgets vertically in a column. Unlike standard dialog hierarchy, the Column widget ignores the parent-child hierarchy of the dialog and places all its children in a single vertical stack. It behaves similarly to a Row widget, but with a vertical orientation.

    from aiogram_dialog.widgets.kbd.group import Column
    # Usage involves adding widgets as children to a Column instance
  11. Declare a Window in aiogram-dialog

    develop

    A Window is the building block of a dialog. It defines what the user sees and how they interact with a specific state. A Window consists of:

    • Text widgets: For rendering message text (e.g., Format, Const).
    • Keyboard widgets: For rendering inline keyboards (e.g., Button).
    • Media widgets: For rendering photos or videos.
    • Message handlers: To process incoming messages while the window is active.
    • Data getters (getter=): Functions that load data used by text or keyboard widgets.
    • State: The specific State from a StatesGroup that this window represents.

    Note: Always define your State inside a StatesGroup class.

    from aiogram.fsm.state import StatesGroup, State
    from aiogram_dialog.widgets.text import Format, Const
    from aiogram_dialog.widgets.kbd import Button
    from aiogram_dialog import Window
    
    
    class MySG(StatesGroup):
        main = State()
    
    
    async def get_data(**kwargs):
        return {"name": "world"}
    
    
    window = Window(
        Format("Hello, {name}!"),
        Button(Const("Empty button"), id="nothing"),
        state=MySG.main,
        getter=get_data,
    )