Skip to content

Commit

Permalink
move message->callback convertion to middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
Tishka17 committed Nov 23, 2023
1 parent 6fbac22 commit 5c722b7
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 37 deletions.
17 changes: 12 additions & 5 deletions example/mega/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from aiogram.exceptions import TelegramBadRequest
from aiogram.filters import ExceptionTypeFilter
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message, ErrorEvent
from aiogram.types import Message, ErrorEvent, ReplyKeyboardRemove

from aiogram_dialog import DialogManager, setup_dialogs, StartMode, ShowMode
from aiogram_dialog.api.exceptions import UnknownIntent
Expand Down Expand Up @@ -35,10 +35,17 @@ async def on_unknown_intent(event: ErrorEvent, dialog_manager: DialogManager):
"Bot process was restarted due to maintenance.\n"
"Redirecting to main menu.",
)
try:
await event.update.callback_query.message.delete()
except TelegramBadRequest:
pass # whatever
if event.update.callback_query.message:
try:
await event.update.callback_query.message.delete()
except TelegramBadRequest:
pass # whatever
elif event.update.message:
await event.update.message.answer(
"Bot process was restarted due to maintenance.\n"
"Redirecting to main menu.",
reply_markup=ReplyKeyboardRemove(),
)
await dialog_manager.start(
states.Main.MAIN,
mode=StartMode.RESET_STACK,
Expand Down
5 changes: 3 additions & 2 deletions src/aiogram_dialog/api/internal/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
__all__ = [
"FakeChat", "FakeUser",
"DialogManagerFactory",
"CALLBACK_DATA_KEY", "CONTEXT_KEY", "STACK_KEY", "STORAGE_KEY",
"CALLBACK_DATA_KEY", "CONTEXT_KEY", "EVENT_SIMULATED",
"STACK_KEY", "STORAGE_KEY",
"ButtonVariant", "DataGetter", "InputWidget", "KeyboardWidget",
"MediaWidget", "RawKeyboard", "TextWidget", "Widget",
"WindowProtocol",
Expand All @@ -12,7 +13,7 @@
DialogManagerFactory,
)
from .middleware import (
CALLBACK_DATA_KEY, CONTEXT_KEY, STACK_KEY, STORAGE_KEY,
CALLBACK_DATA_KEY, CONTEXT_KEY, EVENT_SIMULATED, STACK_KEY, STORAGE_KEY,
)
from .widgets import (
ButtonVariant, DataGetter, InputWidget, KeyboardWidget,
Expand Down
1 change: 1 addition & 0 deletions src/aiogram_dialog/api/internal/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
STACK_KEY = "aiogd_stack"
CONTEXT_KEY = "aiogd_context"
CALLBACK_DATA_KEY = "aiogd_original_callback_data"
EVENT_SIMULATED = "aiogd_event_simulated"
24 changes: 22 additions & 2 deletions src/aiogram_dialog/context/intent_middleware.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from logging import getLogger
from typing import Any, Awaitable, Callable, Dict, Optional

from aiogram import Router
from aiogram.dispatcher.middlewares.base import BaseMiddleware
from aiogram.types import CallbackQuery, Chat, Message, User
from aiogram.types.error_event import ErrorEvent
Expand All @@ -12,10 +13,11 @@
InvalidStackIdError, OutdatedIntent, UnknownIntent, UnknownState,
)
from aiogram_dialog.api.internal import (
CALLBACK_DATA_KEY, CONTEXT_KEY, STACK_KEY, STORAGE_KEY,
CALLBACK_DATA_KEY, CONTEXT_KEY, EVENT_SIMULATED,
STACK_KEY, STORAGE_KEY,
)
from aiogram_dialog.api.protocols import DialogRegistryProtocol
from aiogram_dialog.utils import remove_indent_id
from aiogram_dialog.utils import remove_indent_id, split_reply_callback
from .storage import StorageProxy

logger = getLogger(__name__)
Expand Down Expand Up @@ -111,6 +113,24 @@ async def process_message(
event: Message,
data: dict,
):
text, callback_data = split_reply_callback(event.text)
if callback_data:
query = CallbackQuery(
id="",
message=None,
data=callback_data,
from_user=event.from_user,
# we cannot know real chat instance
chat_instance=str(event.chat.id),
)
router: Router = data["event_router"]
return await router.propagate_event(
"callback_query",
query,
**{EVENT_SIMULATED: True},
**data,
)

if intent_id := self._intent_id_from_reply(event, data):
await self._load_context(event, intent_id, DEFAULT_STACK_ID, data)
else:
Expand Down
16 changes: 2 additions & 14 deletions src/aiogram_dialog/dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
DialogManager, DialogProtocol,
)
from .context.intent_filter import IntentFilter
from .utils import remove_indent_id, split_reply_callback
from .utils import remove_indent_id
from .widgets.data import PreviewAwareGetter
from .widgets.utils import ensure_data_getter, GetterVariant

Expand Down Expand Up @@ -126,21 +126,9 @@ async def render(self, manager: DialogManager) -> NewMessage:
async def _message_handler(
self, message: Message, dialog_manager: DialogManager,
):
text, data = split_reply_callback(message.text)
old_context = dialog_manager.current_context()
window = await self._current_window(dialog_manager)
if data:
query = CallbackQuery(
id="0",
message=message,
data=data,
from_user=message.from_user,
# we cannot know real chat instance
chat_instance=str(message.chat.id),
)
return await self._callback_handler(query, dialog_manager)
else:
await window.process_message(message, self, dialog_manager)
await window.process_message(message, self, dialog_manager)
if dialog_manager.has_context():
if dialog_manager.current_context() == old_context: # same dialog
await dialog_manager.show()
Expand Down
51 changes: 37 additions & 14 deletions src/aiogram_dialog/manager/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from aiogram import Router
from aiogram.fsm.state import State
from aiogram.types import (
CallbackQuery, Chat, Message, ReplyKeyboardMarkup, User,
CallbackQuery, Chat, ErrorEvent, Message, ReplyKeyboardMarkup, User,
)

from aiogram_dialog.api.entities import (
Expand All @@ -16,10 +16,8 @@
IncorrectBackgroundError, InvalidKeyboardType, NoContextError,
)
from aiogram_dialog.api.internal import (
CONTEXT_KEY, STACK_KEY, STORAGE_KEY,
)
from aiogram_dialog.api.internal import (
FakeChat, FakeUser,
CONTEXT_KEY, EVENT_SIMULATED, FakeChat, FakeUser,
STACK_KEY, STORAGE_KEY,
)
from aiogram_dialog.api.protocols import (
BaseDialogManager, DialogManager, DialogProtocol, DialogRegistryProtocol,
Expand Down Expand Up @@ -174,6 +172,8 @@ async def done(
async def answer_callback(self) -> None:
if not isinstance(self.event, CallbackQuery):
return
if self.is_event_simulated():
return
return await self.message_manager.answer_callback(
bot=self._data["bot"],
callback_query=self.event,
Expand Down Expand Up @@ -342,24 +342,47 @@ async def _fix_cached_media_id(self, new_message: NewMessage):
type=new_message.media.type,
)

def _get_last_message(self) -> Optional[OldMessage]:
def is_event_simulated(self):
return bool(self.middleware_data.get(EVENT_SIMULATED))

def _get_message_from_callback(
self, event: CallbackQuery,
) -> Optional[OldMessage]:
current_message = event.message
stack = self.current_stack()
chat = self._data["event_chat"]
if (
isinstance(self.event, CallbackQuery) and
self.event.message and
stack.last_message_id == self.event.message.message_id
):
current_message = self.event.message
chat = self.middleware_data["event_chat"]
if current_message:
media_id = get_media_id(current_message)
return OldMessage(
media_id=(media_id.file_id if media_id else None),
media_uniq_id=(media_id.file_unique_id if media_id else None),
text=current_message.text,
has_reply_keyboard=False,
has_reply_keyboard=self.is_event_simulated(),
chat=chat,
message_id=current_message.message_id,
)
elif not stack or not stack.last_message_id:
return None
else:
return OldMessage(
media_id=None,
media_uniq_id=None,
text=UnknownText.UNKNOWN,
has_reply_keyboard=self.is_event_simulated(),
chat=chat,
message_id=stack.last_message_id,
)

def _get_last_message(self) -> Optional[OldMessage]:
if isinstance(self.event, ErrorEvent):
event = self.event.update.event
else:
event = self.event
if isinstance(event, CallbackQuery):
return self._get_message_from_callback(event)

stack = self.current_stack()
chat = self.middleware_data["event_chat"]
if not stack or not stack.last_message_id:
return None
return OldMessage(
Expand Down

0 comments on commit 5c722b7

Please sign in to comment.