Fix scene handling for channel updates with missing FSM state (#1743)

This commit is contained in:
latand 2026-02-10 21:39:06 +02:00
parent 1708980ceb
commit 647e544fd5
5 changed files with 294 additions and 5 deletions

View file

@ -0,0 +1,118 @@
from datetime import datetime
import pytest
from aiogram import Dispatcher, F, Router
from aiogram.fsm.context import FSMContext
from aiogram.fsm.scene import Scene, SceneRegistry, on
from aiogram.fsm.strategy import FSMStrategy
from aiogram.types import Chat, Message, Update
from tests.mocked_bot import MockedBot
CHANNEL_ID = -1001234567890
class BrowseScene(Scene, state="browse"):
pass
class ChannelStateScene(Scene, state="channel_state"):
@on.channel_post()
async def save_message_id(
self,
message: Message,
state: FSMContext,
) -> int:
await state.update_data(last_message_id=message.message_id)
return message.message_id
@pytest.mark.parametrize("update_type", ["channel_post", "edited_channel_post"])
async def test_channel_events_with_scenes_do_not_require_fsm_state(
bot: MockedBot,
update_type: str,
):
dispatcher = Dispatcher()
channel_router = Router()
if update_type == "channel_post":
channel_router.channel_post.filter(F.chat.id == CHANNEL_ID)
@channel_router.channel_post()
async def on_channel_post(message: Message):
return message.message_id
else:
channel_router.edited_channel_post.filter(F.chat.id == CHANNEL_ID)
@channel_router.edited_channel_post()
async def on_edited_channel_post(message: Message):
return message.message_id
dispatcher.include_router(channel_router)
SceneRegistry(dispatcher).add(BrowseScene)
message = Message(
message_id=1,
date=datetime.now(),
chat=Chat(id=CHANNEL_ID, type="channel"),
text="test",
)
kwargs = {"update_id": 1, update_type: message}
update = Update(**kwargs)
result = await dispatcher.feed_update(bot, update)
assert result == 1
async def test_channel_scene_has_fsm_state_with_chat_strategy(bot: MockedBot):
dispatcher = Dispatcher(fsm_strategy=FSMStrategy.CHAT)
router = Router()
@router.channel_post((F.chat.id == CHANNEL_ID) & (F.text == "enter"))
async def enter_channel_state(message: Message, state: FSMContext):
await state.set_state(ChannelStateScene.__scene_config__.state)
return message.message_id
dispatcher.include_router(router)
SceneRegistry(dispatcher).add(ChannelStateScene)
initial_update = Update(
update_id=1,
channel_post=Message(
message_id=10,
date=datetime.now(),
chat=Chat(id=CHANNEL_ID, type="channel"),
text="enter",
),
)
await dispatcher.feed_update(bot, initial_update)
active_state = await dispatcher.fsm.storage.get_state(
key=dispatcher.fsm.get_context(
bot=bot,
chat_id=CHANNEL_ID,
user_id=CHANNEL_ID,
).key
)
assert active_state == ChannelStateScene.__scene_config__.state
scene_update = Update(
update_id=2,
channel_post=Message(
message_id=11,
date=datetime.now(),
chat=Chat(id=CHANNEL_ID, type="channel"),
text="scene",
),
)
result = await dispatcher.feed_update(bot, scene_update)
assert result == 11
state_data = await dispatcher.fsm.storage.get_data(
key=dispatcher.fsm.get_context(
bot=bot,
chat_id=CHANNEL_ID,
user_id=CHANNEL_ID,
).key
)
assert state_data["last_message_id"] == 11