diff --git a/CHANGES/889.feature.rst b/CHANGES/889.feature.rst new file mode 100644 index 00000000..8e58304c --- /dev/null +++ b/CHANGES/889.feature.rst @@ -0,0 +1 @@ +Added possibility to get command magic result as handler argument diff --git a/Makefile b/Makefile index 545af8e7..8d9abab8 100644 --- a/Makefile +++ b/Makefile @@ -94,9 +94,6 @@ test: test-run-services test-coverage: test-run-services mkdir -p $(reports_dir)/tests/ $(py) pytest --cov=aiogram --cov-config .coveragerc --html=$(reports_dir)/tests/index.html tests/ --redis $(redis_connection) - -.PHONY: test-coverage-report -test-coverage-report: $(py) coverage html -d $(reports_dir)/coverage .PHONY: test-coverage-view diff --git a/aiogram/dispatcher/filters/command.py b/aiogram/dispatcher/filters/command.py index 03cb41c7..3690f884 100644 --- a/aiogram/dispatcher/filters/command.py +++ b/aiogram/dispatcher/filters/command.py @@ -59,7 +59,10 @@ class Command(BaseFilter): command = await self.parse_command(text=text, bot=bot) except CommandException: return False - return {"command": command} + result = {"command": command} + if command.magic_result and isinstance(command.magic_result, dict): + result.update(command.magic_result) + return result def extract_command(self, text: str) -> CommandObject: # First step: separate command with arguments @@ -110,20 +113,22 @@ class Command(BaseFilter): self.validate_prefix(command=command) await self.validate_mention(bot=bot, command=command) command = self.validate_command(command) - self.do_magic(command=command) + command = self.do_magic(command=command) return command - def do_magic(self, command: CommandObject) -> None: + def do_magic(self, command: CommandObject) -> Any: if not self.command_magic: - return - if not self.command_magic.resolve(command): + return command + result = self.command_magic.resolve(command) + if not result: raise CommandException("Rejected via magic filter") + return replace(command, magic_result=result) class Config: arbitrary_types_allowed = True -@dataclass +@dataclass(frozen=True) class CommandObject: """ Instance of this object is always has command and it prefix. @@ -140,6 +145,7 @@ class CommandObject: """Command argument""" regexp_match: Optional[Match[str]] = field(repr=False, default=None) """Will be presented match result if the command is presented as regexp in filter""" + magic_result: Optional[Any] = field(repr=False, default=None) @property def mentioned(self) -> bool: diff --git a/tests/test_dispatcher/test_filters/test_command.py b/tests/test_dispatcher/test_filters/test_command.py index d7a0ef55..38faaa7d 100644 --- a/tests/test_dispatcher/test_filters/test_command.py +++ b/tests/test_dispatcher/test_filters/test_command.py @@ -92,6 +92,18 @@ class TestCommandFilter: command = Command(commands=["test"]) assert bool(await command(message=message, bot=bot)) is result + async def test_command_magic_result(self, bot: MockedBot): + message = Message( + message_id=0, + text="/test 42", + chat=Chat(id=42, type="private"), + date=datetime.datetime.now(), + ) + command = Command(commands=["test"], command_magic=(F.args.as_("args"))) + result = await command(message=message, bot=bot) + assert "args" in result + assert result["args"] == "42" + class TestCommandObject: @pytest.mark.parametrize(