### Setup Project with uv Source: https://docs.aiogram.dev/en/v3.27.0/contributing.html Clones the aiogram repository and installs all dependencies using uv, automatically creating a virtual environment and generating a lock file. ```bash git clone https://github.com/aiogram/aiogram.git cd aiogram uv sync --all-extras --group dev --group test uv run pre-commit install ``` -------------------------------- ### Start FSM and Transition to Initial State Source: https://docs.aiogram.dev/en/v3.27.0/dispatcher/finite_state_machine/index.html Handle a command (e.g., /start) to initiate the FSM and set the first state for the user. This example transitions to the 'Form.name' state. ```python @form_router.message(CommandStart()) async def command_start(message: Message, state: FSMContext) -> None: await state.set_state(Form.name) await message.answer( "Hi there! What's your name?", reply_markup=ReplyKeyboardRemove(), ) ``` -------------------------------- ### Complete FSM Example Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/index.rst.txt Full implementation of the finite state machine example. ```python import asyncio import logging from typing import Any, Dict from aiogram import Bot, Dispatcher, F, Router from aiogram.filters import Command from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from aiogram.types import ( Message, ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove, ) # All handlers should be attached to the Router (or Dispatcher) router = Router() # States class Form(StatesGroup): name = State() like_bots = State() language = State() @router.message(Command("start")) async def command_start(message: Message, state: FSMContext) -> None: await state.set_state(Form.name) await message.answer( "Hi! What is your name?", reply_markup=ReplyKeyboardRemove(), ) @router.message(Command("cancel")) @router.message(F.text.casefold() == "cancel") async def cancel_handler(message: Message, state: FSMContext) -> None: current_state = await state.get_state() if current_state is None: return logging.info("Cancelling state %r", current_state) await state.clear() await message.answer( "Cancelled.", reply_markup=ReplyKeyboardRemove(), ) @router.message(Form.name) async def process_name(message: Message, state: FSMContext) -> None: await state.update_data(name=message.text) await state.set_state(Form.like_bots) await message.answer( f"Nice to meet you, {message.text}!\nDid you like to write bots?", reply_markup=ReplyKeyboardMarkup( keyboard=[ [ KeyboardButton(text="Yes"), KeyboardButton(text="No"), ] ], resize_keyboard=True, ), ) @router.message(Form.like_bots, F.text.casefold() == "yes") async def process_like_write_bots(message: Message, state: FSMContext) -> None: await state.set_state(Form.language) await message.answer( "Cool! What is your favorite programming language?", reply_markup=ReplyKeyboardRemove(), ) @router.message(Form.like_bots, F.text.casefold() == "no") async def process_dont_like_write_bots(message: Message, state: FSMContext) -> None: await state.set_state(Form.language) await message.answer( "You should try! What is your favorite programming language?", reply_markup=ReplyKeyboardRemove(), ) @router.message(Form.like_bots) async def process_unknown_write_bots(message: Message) -> None: await message.answer("I don't understand you :(") @router.message(Form.language) async def process_language(message: Message, state: FSMContext) -> None: await state.update_data(language=message.text) await show_summary(message=message, state=state) async def show_summary(message: Message, state: FSMContext, positive: bool = True) -> None: data = await state.get_data() text = f"Nice to meet you, {data.get('name')}!\nYour favorite language is {data.get('language')}" await message.answer(text=text, reply_markup=ReplyKeyboardRemove()) await state.clear() async def main() -> None: bot = Bot(token="BOT_TOKEN") dp = Dispatcher() dp.include_router(router) await dp.start_polling(bot) if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.run(main()) ``` -------------------------------- ### Start Documentation Server (uv) Source: https://docs.aiogram.dev/en/v3.27.0/contributing.html Starts the documentation server using sphinx-autobuild within a uv-managed environment. Prefix commands with 'uv run'. ```bash uv run sphinx-autobuild --watch aiogram/ docs/ docs/_build/ ``` -------------------------------- ### Install uv using pip Source: https://docs.aiogram.dev/en/v3.27.0/contributing.html Installs the uv package manager using pip. ```bash pip install uv ``` -------------------------------- ### Basic Bot Initialization and Message Handling Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/client/bot.html Demonstrates how to initialize an aiogram bot and set up a handler for incoming messages. This is a fundamental example for starting any aiogram bot. ```python from aiogram import Bot, Dispatcher # Replace 'YOUR_BOT_TOKEN' with your actual bot token bot = Bot(token='YOUR_BOT_TOKEN') dp = Dispatcher(bot) @dp.message_handler() async def echo(message): await message.answer(f'You sent: {message.text}') # To run the bot, you would typically use: # import asyncio # async def main(): # await dp.start_polling() # if __name__ == '__main__': # asyncio.run(main()) ``` -------------------------------- ### Install aiogram Development Build Source: https://docs.aiogram.dev/en/v3.27.0/_sources/install.rst.txt Install the latest development version directly from the GitHub repository. ```bash pip install https://github.com/aiogram/aiogram/archive/refs/heads/dev-3.x.zip ``` -------------------------------- ### Install uv package manager Source: https://docs.aiogram.dev/en/v3.27.0/_sources/contributing.rst.txt Methods to install the uv tool for managing environments and dependencies. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` ```powershell powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" ``` ```bash pip install uv ``` -------------------------------- ### Install uv (Windows PowerShell) Source: https://docs.aiogram.dev/en/v3.27.0/contributing.html Installs the uv package manager using a PowerShell command. ```powershell powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" ``` -------------------------------- ### Complete FSM Form Example Source: https://docs.aiogram.dev/en/v3.27.0/dispatcher/finite_state_machine/index.html This is a full implementation of a conversational form using aiogram's FSM. It guides the user through a series of questions to collect their name, preference for writing bots, and preferred programming language. Includes handlers for starting the form, canceling the process, and processing input for each state. ```Python import asyncio import logging import sys from os import getenv from typing import Any from aiogram import Bot, Dispatcher, F, Router, html from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode from aiogram.filters import Command, CommandStart from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from aiogram.types import ( KeyboardButton, Message, ReplyKeyboardMarkup, ReplyKeyboardRemove, ) TOKEN = getenv("BOT_TOKEN") form_router = Router() class Form(StatesGroup): name = State() like_bots = State() language = State() @form_router.message(CommandStart()) async def command_start(message: Message, state: FSMContext) -> None: await state.set_state(Form.name) await message.answer( "Hi there! What's your name?", reply_markup=ReplyKeyboardRemove(), ) @form_router.message(Command("cancel")) @form_router.message(F.text.casefold() == "cancel") async def cancel_handler(message: Message, state: FSMContext) -> None: """ Allow user to cancel any action """ current_state = await state.get_state() if current_state is None: return logging.info("Cancelling state %r", current_state) await state.clear() await message.answer( "Cancelled.", reply_markup=ReplyKeyboardRemove(), ) @form_router.message(Form.name) async def process_name(message: Message, state: FSMContext) -> None: await state.update_data(name=message.text) await state.set_state(Form.like_bots) await message.answer( f"Nice to meet you, {html.quote(message.text)}!\nDid you like to write bots?", reply_markup=ReplyKeyboardMarkup( keyboard=[ [ KeyboardButton(text="Yes"), KeyboardButton(text="No"), ], ], resize_keyboard=True, ), ) @form_router.message(Form.like_bots, F.text.casefold() == "no") async def process_dont_like_write_bots(message: Message, state: FSMContext) -> None: data = await state.get_data() await state.clear() await message.answer( "Not bad not terrible.\nSee you soon.", reply_markup=ReplyKeyboardRemove(), ) await show_summary(message=message, data=data, positive=False) @form_router.message(Form.like_bots, F.text.casefold() == "yes") async def process_like_write_bots(message: Message, state: FSMContext) -> None: await state.set_state(Form.language) await message.reply( "Cool! I'm too!\nWhat programming language did you use for it?", reply_markup=ReplyKeyboardRemove(), ) @form_router.message(Form.like_bots) async def process_unknown_write_bots(message: Message) -> None: await message.reply("I don't understand you :(") @form_router.message(Form.language) async def process_language(message: Message, state: FSMContext) -> None: data = await state.update_data(language=message.text) await state.clear() if message.text.casefold() == "python": await message.reply( "Python, you say? That's the language that makes my circuits light up! 😉", ) await show_summary(message=message, data=data) async def show_summary(message: Message, data: dict[str, Any], positive: bool = True) -> None: name = data["name"] language = data.get("language", "") text = f"I'll keep in mind that, {html.quote(name)}, " text += ( f"you like to write bots with {html.quote(language)}." if positive else "you don't like to write bots, so sad..." ) await message.answer(text=text, reply_markup=ReplyKeyboardRemove()) async def main() -> None: # Initialize Bot instance with default bot properties which will be passed to all API calls bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) dp = Dispatcher() dp.include_router(form_router) # Start event dispatching await dp.start_polling(bot) if __name__ == "__main__": logging.basicConfig(level=logging.INFO, stream=sys.stdout) asyncio.run(main()) ``` -------------------------------- ### Serve documentation Source: https://docs.aiogram.dev/en/v3.27.0/_sources/contributing.rst.txt Commands to start a live-preview server for documentation. ```bash sphinx-autobuild --watch aiogram/ docs/ docs/_build/ ``` ```bash uv run --extra docs sphinx-autobuild --watch aiogram/ docs/ docs/_build/ ``` ```bash make docs-serve ``` -------------------------------- ### Serve Documentation Source: https://docs.aiogram.dev/en/v3.27.0/contributing.html Build and serve the project documentation locally for live preview. Options include direct execution, uv, or Makefile. ```bash sphinx-autobuild --watch aiogram/ docs/ docs/_build/ ``` ```bash uv run --extra docs sphinx-autobuild --watch aiogram/ docs/ docs/_build/ ``` ```bash make docs-serve ``` -------------------------------- ### Example of a simple text filter Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/filters/index.rst.txt This example demonstrates how to create a custom filter for simple text matching. The filter checks if the event text starts with 'hello' and ends with '!'. ```python from aiogram import F @dp.message(F.text.startswith("hello") & F.text.endswith("!")) async def hello_handler(message: Message): await message.answer("Hello!") ``` -------------------------------- ### Setup project with uv Source: https://docs.aiogram.dev/en/v3.27.0/_sources/contributing.rst.txt Clone the repository and synchronize dependencies using uv. ```bash # Clone the repository git clone https://github.com/aiogram/aiogram.git cd aiogram # Install all dependencies (creates .venv automatically) uv sync --all-extras --group dev --group test # Install pre-commit hooks uv run pre-commit install ``` -------------------------------- ### Webhook Setup with Self-Signed SSL Certificate Source: https://docs.aiogram.dev/en/v3.27.0/dispatcher/webhook.html This example demonstrates how to configure aiogram to use webhooks with a self-signed SSL certificate. It includes bot token, webhook settings, SSL certificate paths, and aiohttp server setup. Ensure you have a valid SSL certificate and private key. ```python """ This example shows how to use webhook with SSL certificate. """ import logging import ssl import sys from os import getenv from aiohttp import web from aiogram import Bot, Dispatcher, Router from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode from aiogram.filters import CommandStart from aiogram.types import FSInputFile, Message from aiogram.utils.markdown import hbold from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application # Bot token can be obtained via https://t.me/BotFather TOKEN = getenv("BOT_TOKEN") # Webserver settings # bind localhost only to prevent any external access WEB_SERVER_HOST = "127.0.0.1" # Port for incoming request from reverse proxy. Should be any available port WEB_SERVER_PORT = 8080 # Path to webhook route, on which Telegram will send requests WEBHOOK_PATH = "/webhook" # Secret key to validate requests from Telegram (optional) WEBHOOK_SECRET = "my-secret" # Base URL for webhook will be used to generate webhook URL for Telegram, # in this example it is used public address with TLS support BASE_WEBHOOK_URL = "https://aiogram.dev" # Path to SSL certificate and private key for self-signed certificate. WEBHOOK_SSL_CERT = "/path/to/cert.pem" WEBHOOK_SSL_PRIV = "/path/to/private.key" # All handlers should be attached to the Router (or Dispatcher) router = Router() @router.message(CommandStart()) async def command_start_handler(message: Message) -> None: """ This handler receives messages with `/start` command """ # Most event objects have aliases for API methods that can be called in events' context # For example if you want to answer to incoming message you can use `message.answer(...)` alias # and the target chat will be passed to :ref:`aiogram.methods.send_message.SendMessage` # method automatically or call API method directly via # Bot instance: `bot.send_message(chat_id=message.chat.id, ...)` await message.answer(f"Hello, {hbold(message.from_user.full_name)}!") @router.message() async def echo_handler(message: Message) -> None: """ Handler will forward receive a message back to the sender By default, message handler will handle all message types (like text, photo, sticker etc.) """ try: # Send a copy of the received message await message.send_copy(chat_id=message.chat.id) except TypeError: # But not all the types is supported to be copied so need to handle it await message.answer("Nice try!") async def on_startup(bot: Bot) -> None: # In case when you have a self-signed SSL certificate, you need to send the certificate # itself to Telegram servers for validation purposes # (see https://core.telegram.org/bots/self-signed) # But if you have a valid SSL certificate, you SHOULD NOT send it to Telegram servers. await bot.set_webhook( f"{BASE_WEBHOOK_URL}{WEBHOOK_PATH}", certificate=FSInputFile(WEBHOOK_SSL_CERT), secret_token=WEBHOOK_SECRET, ) def main() -> None: # Dispatcher is a root router dp = Dispatcher() # ... and all other routers should be attached to Dispatcher dp.include_router(router) # Register startup hook to initialize webhook dp.startup.register(on_startup) # Initialize Bot instance with default bot properties which will be passed to all API calls bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) # Create aiohttp.web.Application instance app = web.Application() # Create an instance of request handler, # aiogram has few implementations for different cases of usage # In this example we use SimpleRequestHandler which is designed to handle simple cases webhook_requests_handler = SimpleRequestHandler( dispatcher=dp, bot=bot, secret_token=WEBHOOK_SECRET, ) # Register webhook handler on application webhook_requests_handler.register(app, path=WEBHOOK_PATH) # Mount dispatcher startup and shutdown hooks to aiohttp application setup_application(app, dp, bot=bot) # Generate SSL context context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain(WEBHOOK_SSL_CERT, WEBHOOK_SSL_PRIV) # And finally start webserver web.run_app(app, host=WEB_SERVER_HOST, port=WEB_SERVER_PORT, ssl_context=context) if __name__ == "__main__": logging.basicConfig(level=logging.INFO, stream=sys.stdout) main() ``` -------------------------------- ### Get Business Account Gifts as Bot Method Source: https://docs.aiogram.dev/en/v3.27.0/api/methods/get_business_account_gifts.html Example of calling the get_business_account_gifts method directly on the bot object. Ensure you have the necessary business bot rights. ```python result: OwnedGifts = await bot.get_business_account_gifts(...) ``` -------------------------------- ### Handle Start Command Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/index.rst.txt Initialize the dialogue and transition the user to the first state. ```python @router.message(Command("start")) async def command_start(message: Message, state: FSMContext) -> None: await state.set_state(Form.name) await message.answer("Hi! What is your name?") ``` -------------------------------- ### Get Business Account Gifts as Method Object Source: https://docs.aiogram.dev/en/v3.27.0/api/methods/get_business_account_gifts.html Example of using GetBusinessAccountGifts as a method object, which can be useful when working with specific bots or in more complex scenarios. Imports are required. ```python from aiogram.methods.get_business_account_gifts import GetBusinessAccountGifts result: OwnedGifts = await bot(GetBusinessAccountGifts(...)) ``` -------------------------------- ### Simple InlineQueryHandler Usage Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/class_based_handlers/inline_query.rst.txt Demonstrates the basic setup for an InlineQueryHandler. Ensure the router is correctly initialized before use. ```python from aiogram.handlers import InlineQueryHandler ... @router.inline_query() class MyHandler(InlineQueryHandler): async def handle(self) -> Any: ... ``` -------------------------------- ### Exporting ReplyKeyboardMarkup from ReplyKeyboardBuilder Source: https://docs.aiogram.dev/en/v3.27.0/utils/keyboard.html This example demonstrates how to export a configured markup from a ReplyKeyboardBuilder instance. It's useful when you need to get the underlying list of lists of buttons to construct a ReplyKeyboardMarkup. ```python >>> builder = KeyboardBuilder(button_type=KeyboardButton) >>> # Add buttons to builder >>> markup = ReplyKeyboardMarkup(reply_keyboard=builder.export()) ``` -------------------------------- ### Dispatcher Initialization and Middleware Setup Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/dispatcher/dispatcher.html Illustrates the initialization of the Dispatcher class, including the setup of event observers, error handling, user context management, and FSM integration. This snippet shows how to configure storage, FSM strategy, and event isolation. ```python from __future__ import annotations import asyncio import contextvars import signal import sys import warnings from asyncio import CancelledError, Event, Future, Lock from collections.abc import AsyncGenerator, Awaitable from contextlib import suppress from typing import TYPE_CHECKING, Any from aiogram import loggers from aiogram.exceptions import TelegramAPIError from aiogram.fsm.middleware import FSMContextMiddleware from aiogram.fsm.storage.base import BaseEventIsolation, BaseStorage from aiogram.fsm.storage.memory import DisabledEventIsolation, MemoryStorage from aiogram.fsm.strategy import FSMStrategy from aiogram.methods import GetUpdates, TelegramMethod from aiogram.types import Update, User from aiogram.types.base import UNSET, UNSET_TYPE from aiogram.types.update import UpdateTypeLookupError from aiogram.utils.backoff import Backoff, BackoffConfig from .event.bases import UNHANDLED, SkipHandler from .event.telegram import TelegramEventObserver from .middlewares.error import ErrorsMiddleware from .middlewares.user_context import UserContextMiddleware from .router import Router if TYPE_CHECKING: from aiogram.client.bot import Bot from aiogram.methods.base import TelegramType DEFAULT_BACKOFF_CONFIG = BackoffConfig(min_delay=1.0, max_delay=5.0, factor=1.3, jitter=0.1) class Dispatcher(Router): """ Root router """ def __init__( self, *, storage: BaseStorage | None = None, fsm_strategy: FSMStrategy = FSMStrategy.USER_IN_CHAT, events_isolation: BaseEventIsolation | None = None, disable_fsm: bool = False, name: str | None = None, **kwargs: Any, ) -> None: """ Root router :param storage: Storage for FSM :param fsm_strategy: FSM strategy :param events_isolation: Events isolation :param disable_fsm: Disable FSM, note that if you disable FSM then you should not use storage and events isolation :param kwargs: Other arguments, will be passed as keyword arguments to handlers """ super().__init__(name=name) if storage and not isinstance(storage, BaseStorage): msg = f"FSM storage should be instance of 'BaseStorage' not {type(storage).__name__}" raise TypeError(msg) # Telegram API provides originally only one event type - Update # For making easily interactions with events here is registered handler which helps # to separate Update to different event types like Message, CallbackQuery etc. self.update = self.observers["update"] = TelegramEventObserver( router=self, event_name="update", ) self.update.register(self._listen_update) # Error handlers should work is out of all other functions # and should be registered before all others middlewares self.update.outer_middleware(ErrorsMiddleware(self)) # User context middleware makes small optimization for all other builtin # middlewares via caching the user and chat instances in the event context self.update.outer_middleware(UserContextMiddleware()) # FSM middleware should always be registered after User context middleware # because here is used context from previous step self.fsm = FSMContextMiddleware( storage=storage or MemoryStorage(), strategy=fsm_strategy, events_isolation=events_isolation or DisabledEventIsolation(), ) if not disable_fsm: # Note that when FSM middleware is disabled, the event isolation is also disabled # Because the isolation mechanism is a part of the FSM self.update.outer_middleware(self.fsm) self.shutdown.register(self.fsm.close) self.workflow_data: dict[str, Any] = kwargs self._running_lock = Lock() self._stop_signal: Event | None = None self._stopped_signal: Event | None = None self._handle_update_tasks: set[asyncio.Task[Any]] = set() ``` -------------------------------- ### Initializing MediaGroupBuilder Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/utils/media_group.html Demonstrates how to initialize the MediaGroupBuilder with an optional list of media and a caption. ```python builder = MediaGroupBuilder( media=[ InputMediaPhoto(media="attach://photo1.jpg", caption="Photo 1"), InputMediaPhoto(media="attach://photo2.jpg", caption="Photo 2"), ], caption="My awesome media group", ) ``` -------------------------------- ### Install Babel for Translation Source: https://docs.aiogram.dev/en/v3.27.0/_sources/utils/i18n.rst.txt Install the Babel library, which is required for extracting translation strings from your code. It can be installed directly via pip or as an extra dependency of aiogram. ```bash pip install Babel ``` ```bash pip install aiogram[i18n] ``` -------------------------------- ### emit_startup Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/dispatcher/router.html Recursively call startup callbacks for the current router and all its sub-routers. ```APIDOC ## emit_startup ### Description Recursively call startup callbacks for the current router and all its sub-routers. ### Method `emit_startup` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **args** (*Any) - Optional - Positional arguments to pass to startup callbacks. * **kwargs** (*Any) - Optional - Keyword arguments to pass to startup callbacks. ``` -------------------------------- ### Install aiogram dependencies Source: https://docs.aiogram.dev/en/v3.27.0/_sources/contributing.rst.txt Install the project in editable mode with all necessary extras. ```bash pip install -e ."[dev,test,docs,fast,redis,mongo,proxy,i18n]" ``` ```bash pip install -e .[dev,test,docs,fast,redis,mongo,proxy,i18n] ``` -------------------------------- ### Registering a scene as a handler Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/scene.rst.txt Demonstrates how to convert a scene's entry point into a handler and register it with the router, allowing users to initiate the scene via a command. ```python router.message.register(SettingsScene.as_handler(), Command("settings")) ``` -------------------------------- ### Initialize and use a Dispatcher Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/dispatcher.rst.txt Basic setup for a Dispatcher instance with a message handler. ```python dp = Dispatcher() @dp.message() async def message_handler(message: types.Message) -> None: await SendMessage(chat_id=message.from_user.id, text=message.text) ``` -------------------------------- ### Router Initialization and Usage Source: https://docs.aiogram.dev/en/v3.27.0/dispatcher/router.html Demonstrates how to initialize a Router and register a message handler using the decorator syntax. ```APIDOC ## Router Initialization and Usage ### Description This example shows how to create a new Router instance and define a message handler that will process incoming messages. ### Usage ```python from aiogram import Router from aiogram.types import Message my_router = Router(name=__name__) @my_router.message() async def message_handler(message: Message) -> Any: await message.answer('Hello from my router!') ``` ### Class `aiogram.dispatcher.router.Router` ### Methods - `__init__(name: str | None = None)`: Initializes the Router. An optional router name can be provided for debugging purposes. ``` -------------------------------- ### Start Command Handler Source: https://docs.aiogram.dev/en/v3.27.0/dispatcher/finite_state_machine/scene.html Handles the '/start' command to close any active scenes and provide introductory information about the quiz bot. ```python @quiz_router.message(Command("start")) async def command_start(message: Message, scenes: ScenesManager) -> None: await scenes.close() await message.answer( "Hi! This is a quiz bot. To start the quiz, use the /quiz command.", reply_markup=ReplyKeyboardRemove(), ) ``` -------------------------------- ### Install uv (Linux/macOS) Source: https://docs.aiogram.dev/en/v3.27.0/contributing.html Installs the uv package manager using a curl script on Linux or macOS. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` -------------------------------- ### CommandStart Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/filters/command.html A specific filter for handling the /start command. It supports deep linking and options to ignore case and mentions. ```APIDOC ## CommandStart ### Description A specific filter for handling the /start command. It supports deep linking and options to ignore case and mentions. ### Initialization ```python CommandStart( deep_link: bool | None = None, deep_link_encoded: bool = False, ignore_case: bool = False, ignore_mention: bool = False, magic: MagicFilter | None = None, ) ``` ### Parameters - **deep_link** (bool | None) - Enable deep linking - **deep_link_encoded** (bool) - Whether the deep link is encoded - **ignore_case** (bool) - Ignore case for command matching - **ignore_mention** (bool) - Ignore mention for command matching - **magic** (MagicFilter | None) - A magic filter to apply ### Method ```python async parse_command(text: str, bot: Bot) -> CommandObject ``` ### Description Extract command from the text and validate ``` -------------------------------- ### Bot Initialization and Usage Source: https://docs.aiogram.dev/en/v3.27.0/_sources/api/bot.rst.txt Demonstrates how to initialize the Bot class and highlights that methods are available via a bot instance configured with a token. It also mentions that methods are aliased in lower camel case. ```APIDOC ## Bot Class ### Description The `aiogram.Bot` class is used to create a bot instance. A configured token is required to use any of its methods. Methods are aliased in `lower_camel_case` for convenience. ### Initialization ```python from aiogram import Bot bot = Bot(token="YOUR_BOT_TOKEN") ``` ### Method Aliases All methods available in the Bot class are aliased in `lower_camel_case`. For example, `sendMessage` is available as `send_message`. ### Available Members - `token`: The bot token. - `id`: The bot's unique identifier. - `context`: Bot context information. - `me`: Information about the bot user. - `download_file`: Method to download files. - `download`: Alias for `download_file`. ### Warning A full list of methods can be found in the appropriate section of the documentation. ``` -------------------------------- ### Install aiogram with i18n dependency Source: https://docs.aiogram.dev/en/v3.27.0/migration_2_to_3.html If your application uses translation functionality, install aiogram with the optional i18n dependency. ```bash pip install aiogram[i18n] ``` -------------------------------- ### Function-based Session Middleware Example Source: https://docs.aiogram.dev/en/v3.27.0/api/session/middleware.html Example of a function-based session middleware demonstrating request processing and post-request actions. ```python async def __call__( self, make_request: NextRequestMiddlewareType[TelegramType], bot: "Bot", method: TelegramMethod[TelegramType], ) -> Response[TelegramType]: try: # do something with request return await make_request(bot, method) finally: # do something after request ``` -------------------------------- ### Explicit scene transition with wizard.goto Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/scene.rst.txt Demonstrates using wizard.goto within a scene handler for more control over transitions. Dependencies are injected and extended with specified arguments. ```python # Dependencies will be injected into the handler normally and then extended with # the arguments specified in the goto method. ``` -------------------------------- ### Get Chat Member Count Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/types/chat.html Use this method to get the number of members in a chat. Returns an Integer on success. ```python from aiogram.methods import GetChatMemberCount return GetChatMemberCount( chat_id=self.id, **kwargs, ).as_(self._bot) ``` -------------------------------- ### Transitioning to another scene using After.goto Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/scene.rst.txt Illustrates how to transition to another scene after a handler is executed using the After.goto marker, useful for sequential workflows. Dependencies are persisted. ```python class MyScene(Scene, state="my_scene"): ... @on.message(F.text.startswith("🚀"), after=After.goto(AnotherScene)) async def on_message(self, message: Message, some_repo: SomeRepository, db: AsyncSession): # Persist some data before going to another scene await some_repo.save(user_id=message.from_user.id, value=message.text) await db.commit() ... ``` -------------------------------- ### SendVideo Method Initialization Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/types/message.html Shows the initialization of the SendVideo method, including the necessary import and an assertion to ensure the chat is present. ```python # DO NOT EDIT MANUALLY!!! # This method was auto-generated via `butcher` from aiogram.methods import SendVideo assert self.chat is not None, ( "This method can be used only if chat is present in the message." ) ``` -------------------------------- ### Install aiogram via PyPI Source: https://docs.aiogram.dev/en/v3.27.0/_sources/install.rst.txt Use this command to install the latest stable version of aiogram from the Python Package Index. ```bash pip install -U aiogram ``` -------------------------------- ### Create a Router and Register a Message Handler Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/router.rst.txt Demonstrates how to initialize a Router and define a message handler using a decorator. Ensure the handler is asynchronous. ```python from aiogram import Router from aiogram.types import Message my_router = Router(name=__name__) @my_router.message() async def message_handler(message: Message) -> Any: await message.answer('Hello from my router!') ``` -------------------------------- ### SendLocation Method Example Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/types/chat_join_request.html Example of how to use the SendLocation method within the ChatJoinRequest context. This method is auto-generated and should not be edited manually. ```python # DO NOT EDIT MANUALLY!!! # This method was auto-generated via `butcher` from aiogram.methods import SendLocation return SendLocation( chat_id=self.chat.id, latitude=latitude, longitude=longitude, business_connection_id=business_connection_id, message_thread_id=message_thread_id, direct_messages_topic_id=direct_messages_topic_id, horizontal_accuracy=horizontal_accuracy, live_period=live_period, heading=heading, proximity_alert_radius=proximity_alert_radius, disable_notification=disable_notification, protect_content=protect_content, allow_paid_broadcast=allow_paid_broadcast, message_effect_id=message_effect_id, suggested_post_parameters=suggested_post_parameters, reply_parameters=reply_parameters, reply_markup=reply_markup, allow_sending_without_reply=allow_sending_without_reply, reply_to_message_id=reply_to_message_id, **kwargs, ).as_(self._bot) ``` -------------------------------- ### Scene Entry Points and Handlers Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/scene.rst.txt Demonstrates how to define entry points for scenes using markers and how to register them as handlers. ```APIDOC ## Scene Entry Points and Handlers ### Description Scenes can be entered via specific entry points marked with decorators. These entry points can be converted into handlers and registered with a router. ### Method N/A (Decorator-based registration) ### Endpoint N/A ### Parameters N/A ### Request Example ```python from aiogram.fsm.scene import Scene, on from aiogram import types, router from aiogram.filters.command import Command class SettingsScene(Scene, name="settings_scene"): @on.message.enter() async def on_enter(self, message: types.Message): await message.answer("Welcome to settings!") # Registering the scene as a handler router.message.register(SettingsScene.as_handler(), Command("settings")) ``` ### Response N/A ``` -------------------------------- ### Upgrade pip Source: https://docs.aiogram.dev/en/v3.27.0/contributing.html Ensures the latest version of pip is installed within the virtual environment to prevent potential errors during package installation. ```bash python -m pip install --upgrade pip ``` -------------------------------- ### Explicit Scene Transition with wizard.goto Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/scene.rst.txt Explains how to use `wizard.goto` within a scene handler for explicit control over scene transitions, including dependency injection. ```APIDOC ## Explicit Scene Transition with wizard.goto ### Description The `wizard.goto` method provides explicit control over scene transitions from within a scene handler. It allows for passing additional arguments that will be injected into the target scene's entry point. ### Method N/A (Method call within a handler) ### Endpoint N/A ### Parameters N/A ### Request Example ```python from aiogram.fsm.scene import Scene, SceneWizard from aiogram.types import Message class TargetScene(Scene, name="target_scene"): async def on_enter(self, message: Message, custom_data: str): await message.answer(f"Entered TargetScene with: {custom_data}") class SourceScene(Scene, name="source_scene"): async def on_message(self, message: Message, wizard: SceneWizard): await message.answer("Transitioning to TargetScene...") # Explicitly go to TargetScene, passing custom_data await wizard.goto(TargetScene, custom_data="some_value") ``` ### Response N/A ``` -------------------------------- ### Install optional i18n dependencies Source: https://docs.aiogram.dev/en/v3.27.0/_sources/migration_2_to_3.rst.txt Use this command to install the necessary dependencies for internationalization support, as they are no longer included in the default package. ```bash pip install aiogram[i18n] ``` -------------------------------- ### Complete Quiz Example Source: https://docs.aiogram.dev/en/v3.27.0/_sources/dispatcher/finite_state_machine/scene.rst.txt This is a complete example of a quiz scene implementation in aiogram, demonstrating various handlers and scene management features. ```python import asyncio import logging from aiogram import Bot, Dispatcher, types from aiogram.filters.command import Command from aiogram.fsm.scene import Scene, SceneRegistry, ScenesManager, on, After from aiogram.fsm.state import State, StatesGroup class QuizScene(Scene): name = "quiz" def __init__(self, **kwargs): super().__init__(**kwargs) self.score = 0 self.total_questions = 0 self.current_question_index = 0 self.questions = [ {"question": "What is the capital of France?", "options": ["Berlin", "Madrid", "Paris", "Rome"], "answer": "Paris"}, {"question": "What is 2 + 2?", "options": ["3", "4", "5", "6"], "answer": "4"}, {"question": "What is the largest planet in our solar system?", "options": ["Earth", "Jupiter", "Mars", "Saturn"], "answer": "Jupiter"}, ] self.total_questions = len(self.questions) @on.message.enter() async def on_enter(self, message: types.Message): await message.answer("Welcome to the Quiz Game!") await self.ask_question() async def ask_question(self): if self.current_question_index < len(self.questions): question_data = self.questions[self.current_question_index] keyboard = types.InlineKeyboardMarkup( inline_keyboard=[ [types.InlineKeyboardButton(text=option, callback_data=option)] for option in question_data["options"] ] ) await self.update.message.answer(question_data["question"], reply_markup=keyboard) else: await self.on_exit(self.update.message) @on.callback_query.enter() async def on_callback_query(self, callback_query: types.CallbackQuery): await callback_query.answer() question_data = self.questions[self.current_question_index] if callback_query.data == question_data["answer"]: self.score += 1 await callback_query.message.answer("Correct!") else: await callback_query.message.answer(f"Wrong! The answer was {question_data['answer']}.") self.current_question_index += 1 await self.ask_question() async def on_exit(self, message: types.Message): await message.answer( f"You have completed the quiz! Your score is {self.score}/{self.total_questions}" ) async def exit(self, message: types.Message): await message.answer("You have exited the quiz.") async def back(self, message: types.Message): await message.answer("Going back to the previous question.") await self.previous_question() async def previous_question(self): if self.current_question_index > 0: self.current_question_index -= 1 await self.ask_question() else: await self.update.message.answer("This is the first question.") async def main(): bot = Bot(token="YOUR_BOT_TOKEN") dp = Dispatcher() scene_registry = SceneRegistry() await scene_registry.register(QuizScene) dp.include_router(scene_registry.router) @dp.message(Command("start")) async def start_handler(message: types.Message, scenes: ScenesManager): await message.answer("Hello! Type /quiz to start the quiz game.") @dp.message(Command("quiz")) async def quiz_handler(message: types.Message, scenes: ScenesManager): await scenes.enter(QuizScene) await dp.start_polling(bot) if __name__ == "__main__": logging.basicConfig(level=logging.INFO) asyncio.run(main()) ``` -------------------------------- ### Initialize Language Catalog with Pybabel Source: https://docs.aiogram.dev/en/v3.27.0/_sources/utils/i18n.rst.txt Initialize a new language catalog using `pybabel init`. This command takes the POT template, the destination directory for translations, the domain, and the target language code as arguments. ```bash pybabel init -i locales/messages.pot -d locales -D messages -l en ``` -------------------------------- ### Get Bot Name Source: https://docs.aiogram.dev/en/v3.27.0/_modules/aiogram/client/bot.html Use this method to get the current bot name for the given user language. Returns BotName on success. ```python async def get_my_name( self, language_code: str | None = None, request_timeout: int | None = None, ) -> BotName: """ Use this method to get the current bot name for the given user language. Returns :class:`aiogram.types.bot_name.BotName` on success. Source: https://core.telegram.org/bots/api#getmyname :param language_code: A two-letter ISO 639-1 language code or an empty string :param request_timeout: Request timeout :return: Returns :class:`aiogram.types.bot_name.BotName` on success. """ call = GetMyName( language_code=language_code, ) return await self(call, request_timeout=request_timeout) ```