diff --git a/aiogram/dispatcher/dispatcher.py b/aiogram/dispatcher/dispatcher.py index 4bcbbfa7..572205d6 100644 --- a/aiogram/dispatcher/dispatcher.py +++ b/aiogram/dispatcher/dispatcher.py @@ -1,5 +1,5 @@ import asyncio -from typing import AsyncGenerator, Optional +from typing import Any, AsyncGenerator, Dict, Optional from .. import loggers from ..api.client.bot import Bot @@ -18,7 +18,7 @@ class Dispatcher(Router): # Dispatcher is root Router then configuring parent router is not allowed raise RuntimeError("Dispatcher can not be attached to another Router.") - async def feed_update(self, bot: Bot, update: Update, **kwargs): + async def feed_update(self, bot: Bot, update: Update, **kwargs) -> AsyncGenerator[Any, None]: """ Main entry point for incoming updates @@ -38,12 +38,20 @@ class Dispatcher(Router): finish_time = loop.time() duration = (finish_time - start_time) * 1000 loggers.dispatcher.info( - "Update id=%s is %s. Duration %d ms.", + "Update id=%s is %s. Duration %d ms by bot id=%d", update.update_id, "handled" if handled else "not handled", duration, + bot.id, ) + async def feed_raw_update( + self, bot: Bot, update: Dict[str, Any], **kwargs + ) -> AsyncGenerator[Any, None]: + parsed_update = Update(**update) + async for result in self.feed_update(bot=bot, update=parsed_update, **kwargs): + yield result + @classmethod async def listen_updates(cls, bot: Bot) -> AsyncGenerator[Update, None]: update_id: Optional[int] = None diff --git a/tests/test_dispatcher/test_dispatcher.py b/tests/test_dispatcher/test_dispatcher.py index bc590b69..80f2be46 100644 --- a/tests/test_dispatcher/test_dispatcher.py +++ b/tests/test_dispatcher/test_dispatcher.py @@ -1,11 +1,12 @@ import datetime +import time import pytest - from aiogram import Bot from aiogram.api.types import Chat, Message, Update, User from aiogram.dispatcher.dispatcher import Dispatcher from aiogram.dispatcher.router import Router +from asynctest import MagicMock, patch class TestDispatcher: @@ -48,6 +49,30 @@ class TestDispatcher: assert results_count == 1 + @pytest.mark.asyncio + async def test_feed_raw_update(self): + dp = Dispatcher() + bot = Bot("42:TEST") + + with patch( + "aiogram.dispatcher.dispatcher.Dispatcher.feed_update", new_callable=MagicMock + ) as patched_feed_update: + patched_feed_update.__aiter__.return_value = ["test"] + async for result in dp.feed_raw_update( + bot=bot, + update={ + "update_id": 42, + "message": { + "message_id": 42, + "date": int(time.time()), + "text": "test", + "chat": {"id": 42, "type": "private"}, + "user": {"id": 42, "is_bot": False, "first_name": "Test"}, + }, + }, + ): + assert result == "test" + @pytest.mark.skip @pytest.mark.asyncio async def test_listen_updates(self):