From 1197d2bc966727194b52fb227c805793e7327a15 Mon Sep 17 00:00:00 2001 From: Lohinth Date: Tue, 26 May 2026 00:31:43 +0530 Subject: [PATCH] fix(mattermost): accept leading-space slash commands --- plugins/platforms/mattermost/adapter.py | 2 + tests/gateway/test_mattermost.py | 50 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/plugins/platforms/mattermost/adapter.py b/plugins/platforms/mattermost/adapter.py index fc2b6fd8645..c5427af46f9 100644 --- a/plugins/platforms/mattermost/adapter.py +++ b/plugins/platforms/mattermost/adapter.py @@ -878,6 +878,8 @@ class MattermostAdapter(BasePlatformAdapter): # Determine message type. file_ids = post.get("file_ids") or [] msg_type = MessageType.TEXT + if message_text[:1].isspace() and message_text.lstrip().startswith("/"): + message_text = message_text.lstrip() if message_text.startswith("/"): msg_type = MessageType.COMMAND diff --git a/tests/gateway/test_mattermost.py b/tests/gateway/test_mattermost.py index 1fedb30a019..808180ba144 100644 --- a/tests/gateway/test_mattermost.py +++ b/tests/gateway/test_mattermost.py @@ -6,6 +6,7 @@ import pytest from unittest.mock import MagicMock, patch, AsyncMock from gateway.config import Platform, PlatformConfig +from gateway.platforms.base import MessageType from gateway.run import ( _resolve_gateway_display_bool, _resolve_progress_thread_id, @@ -588,6 +589,55 @@ class TestMattermostWebSocketParsing: msg_event = self.adapter.handle_message.call_args[0][0] assert msg_event.source.chat_type == "dm" + @pytest.mark.asyncio + async def test_leading_space_slash_command_is_command(self): + """Mattermost mobile suggests leading-space slash commands.""" + post_data = { + "id": "post_cmd", + "user_id": "user_123", + "channel_id": "chan_dm", + "message": " /new", + } + event = { + "event": "posted", + "data": { + "post": json.dumps(post_data), + "channel_type": "D", + "sender_name": "@bob", + }, + } + + await self.adapter._handle_ws_event(event) + assert self.adapter.handle_message.called + msg_event = self.adapter.handle_message.call_args[0][0] + assert msg_event.text == "/new" + assert msg_event.message_type is MessageType.COMMAND + assert msg_event.get_command() == "new" + + @pytest.mark.asyncio + async def test_leading_space_normal_text_is_preserved(self): + """Only command-shaped mobile messages should be normalized.""" + post_data = { + "id": "post_text", + "user_id": "user_123", + "channel_id": "chan_dm", + "message": " hello", + } + event = { + "event": "posted", + "data": { + "post": json.dumps(post_data), + "channel_type": "D", + "sender_name": "@bob", + }, + } + + await self.adapter._handle_ws_event(event) + assert self.adapter.handle_message.called + msg_event = self.adapter.handle_message.call_args[0][0] + assert msg_event.text == " hello" + assert msg_event.message_type is MessageType.TEXT + @pytest.mark.asyncio async def test_thread_id_from_root_id(self): """Post with root_id should have thread_id set."""