Fix #1743: scene handling for channel updates (#1763)

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

* Add changelog entry for scene handling fix

* Refine scene context error handling
This commit is contained in:
Kostiantyn Kriuchkov 2026-02-10 23:08:44 +02:00 committed by GitHub
parent 1708980ceb
commit da7bfdca0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 298 additions and 4 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