mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-06 07:50:32 +00:00
Migration guide 2.x -> 3.0 (#1143)
* Initial commit for docs cleanup * Update migration guide * More docs * Added changes description * Small fixes
This commit is contained in:
parent
2ecf9cefd7
commit
56f0d9d220
24 changed files with 363 additions and 85 deletions
|
|
@ -1,3 +1,5 @@
|
|||
.. _enums:
|
||||
|
||||
#####
|
||||
Enums
|
||||
#####
|
||||
|
|
|
|||
1
CHANGES/1143.doc.rst
Normal file
1
CHANGES/1143.doc.rst
Normal file
|
|
@ -0,0 +1 @@
|
|||
Improved docs, added basic migration guide (will be expanded later)
|
||||
|
|
@ -53,6 +53,12 @@ DEFAULT_TIMEOUT: Final[float] = 60.0
|
|||
|
||||
|
||||
class BaseSession(abc.ABC):
|
||||
"""
|
||||
This is base class for all HTTP sessions in aiogram.
|
||||
|
||||
If you want to create your own session, you must inherit from this class.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: TelegramAPIServer = PRODUCTION,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class Router:
|
|||
self.chat_member = TelegramEventObserver(router=self, event_name="chat_member")
|
||||
self.chat_join_request = TelegramEventObserver(router=self, event_name="chat_join_request")
|
||||
|
||||
self.errors = TelegramEventObserver(router=self, event_name="error")
|
||||
self.errors = self.error = TelegramEventObserver(router=self, event_name="error")
|
||||
|
||||
self.startup = EventObserver()
|
||||
self.shutdown = EventObserver()
|
||||
|
|
@ -184,6 +184,12 @@ class Router:
|
|||
router.sub_routers.append(self)
|
||||
|
||||
def include_routers(self, *routers: Router) -> None:
|
||||
"""
|
||||
Attach multiple routers.
|
||||
|
||||
:param routers:
|
||||
:return:
|
||||
"""
|
||||
if not routers:
|
||||
raise ValueError("At least one router must be provided")
|
||||
for router in routers:
|
||||
|
|
|
|||
|
|
@ -6,10 +6,16 @@ from aiogram.utils.link import docs_url
|
|||
|
||||
|
||||
class AiogramError(Exception):
|
||||
pass
|
||||
"""
|
||||
Base exception for all aiogram errors.
|
||||
"""
|
||||
|
||||
|
||||
class DetailedAiogramError(AiogramError):
|
||||
"""
|
||||
Base exception for all aiogram errors with detailed message.
|
||||
"""
|
||||
|
||||
url: Optional[str] = None
|
||||
|
||||
def __init__(self, message: str) -> None:
|
||||
|
|
@ -26,14 +32,24 @@ class DetailedAiogramError(AiogramError):
|
|||
|
||||
|
||||
class CallbackAnswerException(AiogramError):
|
||||
pass
|
||||
"""
|
||||
Exception for callback answer.
|
||||
"""
|
||||
|
||||
|
||||
class UnsupportedKeywordArgument(DetailedAiogramError):
|
||||
"""
|
||||
Exception raised when a keyword argument is passed as filter.
|
||||
"""
|
||||
|
||||
url = docs_url("migration_2_to_3.html", fragment_="filtering-events")
|
||||
|
||||
|
||||
class TelegramAPIError(DetailedAiogramError):
|
||||
"""
|
||||
Base exception for all Telegram API errors.
|
||||
"""
|
||||
|
||||
label: str = "Telegram server says"
|
||||
|
||||
def __init__(
|
||||
|
|
@ -50,10 +66,18 @@ class TelegramAPIError(DetailedAiogramError):
|
|||
|
||||
|
||||
class TelegramNetworkError(TelegramAPIError):
|
||||
"""
|
||||
Base exception for all Telegram network errors.
|
||||
"""
|
||||
|
||||
label = "HTTP Client says"
|
||||
|
||||
|
||||
class TelegramRetryAfter(TelegramAPIError):
|
||||
"""
|
||||
Exception raised when flood control exceeds.
|
||||
"""
|
||||
|
||||
url = "https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this"
|
||||
|
||||
def __init__(
|
||||
|
|
@ -73,6 +97,10 @@ class TelegramRetryAfter(TelegramAPIError):
|
|||
|
||||
|
||||
class TelegramMigrateToChat(TelegramAPIError):
|
||||
"""
|
||||
Exception raised when chat has been migrated to a supergroup.
|
||||
"""
|
||||
|
||||
url = "https://core.telegram.org/bots/api#responseparameters"
|
||||
|
||||
def __init__(
|
||||
|
|
@ -90,38 +118,66 @@ class TelegramMigrateToChat(TelegramAPIError):
|
|||
|
||||
|
||||
class TelegramBadRequest(TelegramAPIError):
|
||||
pass
|
||||
"""
|
||||
Exception raised when request is malformed.
|
||||
"""
|
||||
|
||||
|
||||
class TelegramNotFound(TelegramAPIError):
|
||||
pass
|
||||
"""
|
||||
Exception raised when chat, message, user, etc. not found.
|
||||
"""
|
||||
|
||||
|
||||
class TelegramConflictError(TelegramAPIError):
|
||||
pass
|
||||
"""
|
||||
Exception raised when bot token is already used by another application in polling mode.
|
||||
"""
|
||||
|
||||
|
||||
class TelegramUnauthorizedError(TelegramAPIError):
|
||||
pass
|
||||
"""
|
||||
Exception raised when bot token is invalid.
|
||||
"""
|
||||
|
||||
|
||||
class TelegramForbiddenError(TelegramAPIError):
|
||||
pass
|
||||
"""
|
||||
Exception raised when bot is kicked from chat or etc.
|
||||
"""
|
||||
|
||||
|
||||
class TelegramServerError(TelegramAPIError):
|
||||
pass
|
||||
"""
|
||||
Exception raised when Telegram server returns 5xx error.
|
||||
"""
|
||||
|
||||
|
||||
class RestartingTelegram(TelegramServerError):
|
||||
pass
|
||||
"""
|
||||
Exception raised when Telegram server is restarting.
|
||||
|
||||
It seems like this error is not used by Telegram anymore,
|
||||
but it's still here for backward compatibility.
|
||||
|
||||
Currently, you should expect that Telegram can raise RetryAfter (with timeout 5 seconds)
|
||||
error instead of this one.
|
||||
"""
|
||||
|
||||
|
||||
class TelegramEntityTooLarge(TelegramNetworkError):
|
||||
"""
|
||||
Exception raised when you are trying to send a file that is too large.
|
||||
"""
|
||||
|
||||
url = "https://core.telegram.org/bots/api#sending-files"
|
||||
|
||||
|
||||
class ClientDecodeError(AiogramError):
|
||||
"""
|
||||
Exception raised when client can't decode response. (Malformed response, etc.)
|
||||
"""
|
||||
|
||||
def __init__(self, message: str, original: Exception, data: Any) -> None:
|
||||
self.message = message
|
||||
self.original = original
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ def as_marked_list(*items: NodeType, marker: str = "- ") -> Text:
|
|||
Wrap elements as marked list
|
||||
|
||||
:param items:
|
||||
:param marker: line marker, by default is :code:`- `
|
||||
:param marker: line marker, by default is '- '
|
||||
:return: Text
|
||||
"""
|
||||
return as_list(*(Text(marker, item) for item in items))
|
||||
|
|
@ -544,7 +544,7 @@ def as_numbered_list(*items: NodeType, start: int = 1, fmt: str = "{}. ") -> Tex
|
|||
|
||||
:param items:
|
||||
:param start: initial number, by default 1
|
||||
:param fmt: number format, by default :code:`{}. `
|
||||
:param fmt: number format, by default '{}. '
|
||||
:return: Text
|
||||
"""
|
||||
return as_list(*(Text(fmt.format(index), item) for index, item in enumerate(items, start)))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _enums:
|
||||
|
||||
#####
|
||||
Enums
|
||||
#####
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
Use Custom API server
|
||||
=====================
|
||||
|
||||
.. autoclass:: aiogram.client.telegram.TelegramAPIServer
|
||||
:members:
|
||||
|
||||
For example, if you want to use self-hosted API server:
|
||||
|
||||
.. code-block:: python3
|
||||
.. code-block:: python
|
||||
|
||||
session = AiohttpSession(
|
||||
api=TelegramAPIServer.from_base('http://localhost:8082')
|
||||
)
|
||||
bot = Bot(..., session=session)
|
||||
|
||||
.. autoclass:: aiogram.client.telegram.TelegramAPIServer
|
||||
:members:
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ Client sessions is used for interacting with API server.
|
|||
custom_server
|
||||
base
|
||||
aiohttp
|
||||
middleware
|
||||
|
|
|
|||
75
docs/api/session/middleware.rst
Normal file
75
docs/api/session/middleware.rst
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
##########################
|
||||
Client session middlewares
|
||||
##########################
|
||||
|
||||
In some cases you may want to add some middlewares to the client session to customize the behavior of the client.
|
||||
|
||||
Some useful cases that is:
|
||||
|
||||
- Log the outgoing requests
|
||||
- Customize the request parameters
|
||||
- Handle rate limiting errors and retry the request
|
||||
- others ...
|
||||
|
||||
So, you can do it using client session middlewares.
|
||||
A client session middleware is a function (or callable class) that receives the request and the next middleware to call.
|
||||
The middleware can modify the request and then call the next middleware to continue the request processing.
|
||||
|
||||
How to register client session middleware?
|
||||
==========================================
|
||||
|
||||
Register using register method
|
||||
------------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bot.session.middleware(RequestLogging(ignore_methods=[GetUpdates]))
|
||||
|
||||
Register using decorator
|
||||
------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@bot.session.middleware()
|
||||
async def my_middleware(
|
||||
make_request: NextRequestMiddlewareType[TelegramType],
|
||||
bot: "Bot",
|
||||
method: TelegramMethod[TelegramType],
|
||||
) -> Response[TelegramType]:
|
||||
# do something with request
|
||||
return await make_request(bot, method)
|
||||
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
Class based session middleware
|
||||
------------------------------
|
||||
|
||||
.. literalinclude:: ../../../aiogram/client/session/middlewares/request_logging.py
|
||||
:lines: 16-
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. note::
|
||||
|
||||
this middlewware is already implemented inside aiogram, so, if you want to use it you can
|
||||
just import it :code:`from aiogram.client.session.middlewares.request_logging import RequestLogging`
|
||||
|
||||
|
||||
Function based session middleware
|
||||
---------------------------------
|
||||
|
||||
.. code-block:: 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
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
##########
|
||||
ErrorEvent
|
||||
##########
|
||||
|
||||
|
||||
.. automodule:: aiogram.types.error_event
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: True
|
||||
:exclude-members: model_config,model_fields
|
||||
|
|
@ -28,7 +28,6 @@ extensions = [
|
|||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.ifconfig",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx-prompt",
|
||||
"sphinx_substitution_extensions",
|
||||
"sphinx_copybutton",
|
||||
"sphinxcontrib.towncrier.ext",
|
||||
|
|
@ -67,6 +66,6 @@ texinfo_documents = [
|
|||
|
||||
# add_module_names = False
|
||||
|
||||
towncrier_draft_autoversion_mode = 'draft'
|
||||
towncrier_draft_autoversion_mode = "draft"
|
||||
towncrier_draft_include_empty = False
|
||||
towncrier_draft_working_directory = Path(__file__).parent.parent
|
||||
|
|
|
|||
49
docs/dispatcher/errors.rst
Normal file
49
docs/dispatcher/errors.rst
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
######
|
||||
Errors
|
||||
######
|
||||
|
||||
|
||||
Handling errors
|
||||
===============
|
||||
|
||||
Is recommended way that you should use errors inside handlers using try-except block,
|
||||
but in common cases you can use global errors handler at router or dispatcher level.
|
||||
|
||||
If you specify errors handler for router - it will be used for all handlers inside this router.
|
||||
|
||||
If you specify errors handler for dispatcher - it will be used for all handlers inside all routers.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.error(ExceptionTypeFilter(MyCustomException), F.update.message.as_("message"))
|
||||
async def handle_my_custom_exception(event: ErrorEvent, message: Message):
|
||||
# do something with error
|
||||
await message.answer("Oops, something went wrong!")
|
||||
|
||||
|
||||
@router.error()
|
||||
async def error_handler(event: ErrorEvent):
|
||||
logger.critical("Critical error caused by %s", event.exception, exc_info=True)
|
||||
# do something with error
|
||||
...
|
||||
|
||||
|
||||
.. _error-event:
|
||||
|
||||
ErrorEvent
|
||||
==========
|
||||
|
||||
.. automodule:: aiogram.types.error_event
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:undoc-members: True
|
||||
:exclude-members: model_config,model_fields
|
||||
|
||||
.. _error-types:
|
||||
|
||||
Error types
|
||||
===========
|
||||
|
||||
.. automodule:: aiogram.exceptions
|
||||
:members:
|
||||
:member-order: bysource
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
.. _callback-data-factory
|
||||
|
||||
==============================
|
||||
Callback Data Factory & Filter
|
||||
==============================
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ Dispatcher is subclass of router and should be always is root router.
|
|||
|
||||
.. toctree::
|
||||
|
||||
observer
|
||||
router
|
||||
dispatcher
|
||||
class_based_handlers/index
|
||||
|
|
@ -25,3 +24,4 @@ Dispatcher is subclass of router and should be always is root router.
|
|||
middlewares
|
||||
finite_state_machine/index
|
||||
flags
|
||||
errors
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _middlewares:
|
||||
|
||||
===========
|
||||
Middlewares
|
||||
===========
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
########
|
||||
Observer
|
||||
########
|
||||
|
||||
Observer is used for filtering and handling different events. That is part of internal API with some public methods and is recommended to don't use methods is not listed here.
|
||||
|
||||
In `aiogram` framework is available two variants of observer:
|
||||
|
||||
- `EventObserver <#eventobserver>`__
|
||||
- `TelegramEventObserver <#telegrameventobserver>`__
|
||||
|
||||
|
||||
EventObserver
|
||||
=============
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.event.event.EventObserver
|
||||
:members: register, trigger, __call__
|
||||
:member-order: bysource
|
||||
|
||||
|
||||
TelegramEventObserver
|
||||
=====================
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.event.telegram.TelegramEventObserver
|
||||
:members: register, trigger, __call__, bind_filter, middleware, outer_middleware
|
||||
:member-order: bysource
|
||||
|
|
@ -3,10 +3,12 @@ Router
|
|||
######
|
||||
|
||||
.. autoclass:: aiogram.dispatcher.router.Router
|
||||
:members: __init__, include_router
|
||||
:members: __init__, include_router, include_routers, resolve_used_update_types
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
.. _Event observers:
|
||||
|
||||
Event observers
|
||||
===============
|
||||
|
||||
|
|
@ -19,19 +21,6 @@ Here is the list of available observers and examples of how to register handlers
|
|||
|
||||
In these examples only decorator-style registering handlers are used, but if you don't like @decorators just use :obj:`<event type>.register(...)` method instead.
|
||||
|
||||
Update
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@router.update()
|
||||
async def message_handler(update: types.Update) -> Any: pass
|
||||
|
||||
.. note::
|
||||
|
||||
By default Router already has an update handler which route all event types to another observers.
|
||||
|
||||
|
||||
Message
|
||||
-------
|
||||
|
||||
|
|
@ -143,9 +132,12 @@ Errors
|
|||
@router.errors()
|
||||
async def error_handler(exception: ErrorEvent) -> Any: pass
|
||||
|
||||
Is useful for handling errors from other handlers
|
||||
Is useful for handling errors from other handlers, error event described :ref:`here <error-event>`
|
||||
|
||||
|
||||
|
||||
.. _Nested routers:
|
||||
|
||||
Nested routers
|
||||
==============
|
||||
|
||||
|
|
@ -159,8 +151,8 @@ Nested routers
|
|||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
:caption: module_2.py
|
||||
:name: module_2
|
||||
:caption: module_1.py
|
||||
:name: module_1
|
||||
|
||||
router2 = Router()
|
||||
|
||||
|
|
@ -170,7 +162,7 @@ Example:
|
|||
|
||||
.. code-block:: python
|
||||
:caption: module_2.py
|
||||
:name: module_1
|
||||
:name: module_2
|
||||
|
||||
from module_2 import router2
|
||||
|
||||
|
|
@ -179,6 +171,22 @@ Example:
|
|||
router1.include_router(router2)
|
||||
|
||||
|
||||
Update
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@dispatcher.update()
|
||||
async def message_handler(update: types.Update) -> Any: pass
|
||||
|
||||
.. warning::
|
||||
|
||||
The only root Router (Dispatcher) can handle this type of event.
|
||||
|
||||
.. note::
|
||||
|
||||
Dispatcher already has default handler for this event type, so you can use it for handling all updates that are not handled by any other handlers.
|
||||
|
||||
How it works?
|
||||
-------------
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ Contents
|
|||
:maxdepth: 3
|
||||
|
||||
install
|
||||
migration_2_to_3
|
||||
api/index
|
||||
dispatcher/index
|
||||
utils/index
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@
|
|||
Installation
|
||||
############
|
||||
|
||||
Stable (2.x)
|
||||
============
|
||||
|
||||
From PyPI
|
||||
---------
|
||||
|
||||
|
|
@ -35,10 +32,3 @@ From GitHub
|
|||
.. code-block:: bash
|
||||
|
||||
pip install https://github.com/aiogram/aiogram/archive/refs/heads/dev-3.x.zip
|
||||
|
||||
From AUR
|
||||
--------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
yay -S python-aiogram3
|
||||
|
|
|
|||
114
docs/migration_2_to_3.rst
Normal file
114
docs/migration_2_to_3.rst
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
==========================
|
||||
Migration FAQ (2.x -> 3.0)
|
||||
==========================
|
||||
|
||||
.. danger::
|
||||
|
||||
This guide is still in progress.
|
||||
|
||||
This version introduces much many breaking changes and architectural improvements,
|
||||
helping to reduce global variables count in your code, provides useful mechanisms
|
||||
to separate your code to modules or just make sharable modules via packages on the PyPi,
|
||||
makes middlewares and filters more controllable and others.
|
||||
|
||||
On this page you can read about points that changed corresponding to last stable 2.x version.
|
||||
|
||||
.. note::
|
||||
|
||||
This page is most like a detailed changelog than a migration guide,
|
||||
but it will be updated in the future.
|
||||
|
||||
Feel free to contribute to this page, if you find something that is not mentioned here.
|
||||
|
||||
|
||||
Dispatcher
|
||||
==========
|
||||
|
||||
- :class:`Dispatcher` class no longer accepts the `Bot` instance into the initializer,
|
||||
it should be passed to dispatcher only for starting polling or handling event from webhook.
|
||||
Also this way adds possibility to use multiple bot instances at the same time ("multibot")
|
||||
- :class:`Dispatcher` now can be extended with another Dispatcher-like
|
||||
thing named :class:`Router` (:ref:`Read more » <Nested routers>`).
|
||||
With routes you can easily separate your code to multiple modules
|
||||
and may be share this modules between projects.
|
||||
- Removed the **_handler** suffix from all event handler decorators and registering methods.
|
||||
(:ref:`Read more » <Event observers>`)
|
||||
- Executor entirely removed, now you can use Dispatcher directly to start polling or webhook.
|
||||
|
||||
Filtering events
|
||||
================
|
||||
|
||||
- Keyword filters can no more be used, use filters explicitly. (`Read more » <https://github.com/aiogram/aiogram/issues/942>`_)
|
||||
- In due to keyword filters was removed all enabled by default filters (state and content_type now is not enabled),
|
||||
so you should specify them explicitly if you want to use.
|
||||
For example instead of using :code:`@dp.message_handler(content_types=ContentType.PHOTO)`
|
||||
you should use :code:`@router.message(F.photo)`
|
||||
- Most of common filters is replaced by "magic filter". (:ref:`Read more » <magic-filters>`)
|
||||
- Now by default message handler receives any content type,
|
||||
if you want specific one just add the filters (Magic or any other)
|
||||
- State filter now is not enabled by default, that's mean if you using :code:`state="*"` in v2
|
||||
then you should not pass any state filter in v3, and vice versa,
|
||||
if the state in v2 is not specified now you should specify the state.
|
||||
- Added possibility to register per-router global filters, that helps to reduces
|
||||
the number of repetitions in the code and makes easily way to control
|
||||
for what each router will be used.
|
||||
|
||||
Bot API
|
||||
=======
|
||||
|
||||
- Now all API methods is classes with validation (via `pydantic <https://docs.pydantic.dev/>`_)
|
||||
(all API calls is also available as methods in the Bot class).
|
||||
- Added more pre-defined Enums and moved into `aiogram.enums` sub-package. For example chat type enum now is
|
||||
:class:`aiogram.enums.ChatType` instead of :class:`aiogram.types.chat.ChatType`.
|
||||
(:ref:`Read more » <enums>`)
|
||||
- Separated HTTP client session into container that can be reused between different
|
||||
Bot instances in the application.
|
||||
- API Exceptions is no more classified by specific message in due to Telegram has no documented error codes.
|
||||
But all errors is classified by HTTP status code and for each method only one case can be caused with the same code,
|
||||
so in most cases you should check that only error type (by status-code) without checking error message.
|
||||
(:ref:`Read more » <error-types>`)
|
||||
|
||||
Middlewares
|
||||
===========
|
||||
|
||||
- Middlewares can now control a execution context, e.g. using context managers (:ref:`Read more » <middlewares>`)
|
||||
- All contextual data now is shared between middlewares, filters and handlers to end-to-end use.
|
||||
For example now you can easily pass some data into context inside middleware and
|
||||
get it in the filters layer as the same way as in the handlers via keyword arguments.
|
||||
- Added mechanism named **flags**, that helps to customize handler behavior
|
||||
in conjunction with middlewares. (:ref:`Read more » <flags>`)
|
||||
|
||||
Keyboard Markup
|
||||
===============
|
||||
|
||||
- Now :class:`aiogram.types.inline_keyboard_markup.InlineKeyboardMarkup`
|
||||
and :class:`aiogram.types.reply_keyboard_markup.ReplyKeyboardMarkup` has no methods to extend it,
|
||||
instead you have to use markup builders :class:`aiogram.utils.keyboard.ReplyKeyboardBuilder`
|
||||
and :class:`aiogram.utils.keyboard.KeyboardBuilder` respectively
|
||||
(:ref:`Read more » <keyboard-builder>`)
|
||||
|
||||
|
||||
Callbacks data
|
||||
==============
|
||||
|
||||
- Callback data factory now is strictly typed via `pydantic <https://docs.pydantic.dev/>`_ models
|
||||
(:ref:`Read more » <callback-data-factory>`)
|
||||
|
||||
Finite State machine
|
||||
====================
|
||||
|
||||
- State filter will no more added to all handlers, you will need to specify state if you want
|
||||
- Added possibility to change FSM strategy, for example if you want to control state
|
||||
for each user in chat topics instead of user in chat you can specify it in the Dispatcher.
|
||||
|
||||
Sending Files
|
||||
=============
|
||||
|
||||
- From now you should wrap sending files into InputFile object before send instead of passing
|
||||
IO object directly to the API method. (:ref:`Read more » <sending-files>`)
|
||||
|
||||
Webhook
|
||||
=======
|
||||
|
||||
- Simplified aiohttp web app configuration
|
||||
- By default added possibility to upload files when you use reply into webhook
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
.. _formatting-tool
|
||||
.. _formatting-tool:
|
||||
|
||||
==========
|
||||
Formatting
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
.. _keyboard-builder
|
||||
================
|
||||
Keyboard builder
|
||||
================
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ docs = [
|
|||
"sphinx-autobuild~=2021.3.14",
|
||||
"sphinx-copybutton~=0.5.2",
|
||||
"furo~=2023.7.26",
|
||||
"sphinx-prompt~=1.7.0",
|
||||
"Sphinx-Substitution-Extensions~=2022.2.16",
|
||||
"towncrier~=23.6.0",
|
||||
"pygments~=2.15.1",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue