diff --git a/homeassistant/components/signal_messenger/manifest.json b/homeassistant/components/signal_messenger/manifest.json index 058b01535ea16..217109bfa2ca4 100644 --- a/homeassistant/components/signal_messenger/manifest.json +++ b/homeassistant/components/signal_messenger/manifest.json @@ -5,5 +5,5 @@ "documentation": "https://www.home-assistant.io/integrations/signal_messenger", "iot_class": "cloud_push", "loggers": ["pysignalclirestapi"], - "requirements": ["pysignalclirestapi==0.3.23"] + "requirements": ["pysignalclirestapi==0.3.24"] } diff --git a/homeassistant/components/signal_messenger/notify.py b/homeassistant/components/signal_messenger/notify.py index 9c8846b27671a..b93e5bb43e24f 100644 --- a/homeassistant/components/signal_messenger/notify.py +++ b/homeassistant/components/signal_messenger/notify.py @@ -27,18 +27,32 @@ ATTR_FILENAMES = "attachments" ATTR_URLS = "urls" ATTR_VERIFY_SSL = "verify_ssl" +ATTR_TEXTMODE = "text_mode" -DATA_FILENAMES_SCHEMA = vol.Schema({vol.Required(ATTR_FILENAMES): [cv.string]}) +TEXTMODE_OPTIONS = ["normal", "styled"] + +DATA_FILENAMES_SCHEMA = vol.Schema( + { + vol.Required(ATTR_FILENAMES): [cv.string], + vol.Optional(ATTR_TEXTMODE, default="normal"): vol.In(TEXTMODE_OPTIONS), + } +) DATA_URLS_SCHEMA = vol.Schema( { vol.Required(ATTR_URLS): [cv.url], vol.Optional(ATTR_VERIFY_SSL, default=True): cv.boolean, + vol.Optional(ATTR_TEXTMODE, default="normal"): vol.In(TEXTMODE_OPTIONS), } ) DATA_SCHEMA = vol.Any( None, + vol.Schema( + { + vol.Optional(ATTR_TEXTMODE, default="normal"): vol.In(TEXTMODE_OPTIONS), + } + ), DATA_FILENAMES_SCHEMA, DATA_URLS_SCHEMA, ) @@ -100,10 +114,13 @@ def send_message(self, message: str = "", **kwargs: Any) -> None: attachments_as_bytes = self.get_attachments_as_bytes( data, CONF_MAX_ALLOWED_DOWNLOAD_SIZE_BYTES, self._hass ) - try: self._signal_cli_rest_api.send_message( - message, self._recp_nrs, filenames, attachments_as_bytes + message, + self._recp_nrs, + filenames, + attachments_as_bytes, + text_mode="normal" if data is None else data.get(ATTR_TEXTMODE), ) except SignalCliRestApiError as ex: _LOGGER.error("%s", ex) @@ -116,7 +133,6 @@ def get_filenames(data: Any) -> list[str] | None: data = DATA_FILENAMES_SCHEMA(data) except vol.Invalid: return None - return data[ATTR_FILENAMES] @staticmethod @@ -130,7 +146,6 @@ def get_attachments_as_bytes( data = DATA_URLS_SCHEMA(data) except vol.Invalid: return None - urls = data[ATTR_URLS] attachments_as_bytes: list[bytearray] = [] diff --git a/requirements_all.txt b/requirements_all.txt index 82c50ce7c7099..d24eee9397692 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2164,7 +2164,7 @@ pysesame2==1.0.1 pysiaalarm==3.1.1 # homeassistant.components.signal_messenger -pysignalclirestapi==0.3.23 +pysignalclirestapi==0.3.24 # homeassistant.components.sky_hub pyskyqhub==0.1.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 514b26ecbe90a..c6fab7775e2d5 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1700,7 +1700,7 @@ pyserial==3.5 pysiaalarm==3.1.1 # homeassistant.components.signal_messenger -pysignalclirestapi==0.3.23 +pysignalclirestapi==0.3.24 # homeassistant.components.sma pysma==0.7.3 diff --git a/tests/components/signal_messenger/test_notify.py b/tests/components/signal_messenger/test_notify.py index 012de07df0e05..d0085fd6e21c3 100644 --- a/tests/components/signal_messenger/test_notify.py +++ b/tests/components/signal_messenger/test_notify.py @@ -64,6 +64,26 @@ def test_send_message( assert_sending_requests(signal_requests_mock) +def test_send_message_styled( + signal_notification_service: SignalNotificationService, + signal_requests_mock_factory: Mocker, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test send styled message.""" + signal_requests_mock = signal_requests_mock_factory() + with caplog.at_level( + logging.DEBUG, logger="homeassistant.components.signal_messenger.notify" + ): + data = {"text_mode": "styled"} + signal_notification_service.send_message(MESSAGE, data=data) + post_data = json.loads(signal_requests_mock.request_history[-1].text) + assert "Sending signal message" in caplog.text + assert signal_requests_mock.called + assert signal_requests_mock.call_count == 2 + assert post_data["text_mode"] == "styled" + assert_sending_requests(signal_requests_mock) + + def test_send_message_to_api_with_bad_data_throws_error( signal_notification_service: SignalNotificationService, signal_requests_mock_factory: Mocker, @@ -103,6 +123,27 @@ def test_send_message_with_bad_data_throws_vol_error( assert "extra keys not allowed" in str(exc.value) +def test_send_message_styled_with_bad_data_throws_vol_error( + signal_notification_service: SignalNotificationService, + signal_requests_mock_factory: Mocker, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test sending a styled message with bad data throws an error.""" + with ( + caplog.at_level( + logging.DEBUG, logger="homeassistant.components.signal_messenger.notify" + ), + pytest.raises(vol.Invalid) as exc, + ): + signal_notification_service.send_message(MESSAGE, data={"text_mode": "test"}) + + assert "Sending signal message" in caplog.text + assert ( + "value must be one of ['normal', 'styled'] for dictionary value @ data['text_mode']" + in str(exc.value) + ) + + def test_send_message_with_attachment( signal_notification_service: SignalNotificationService, signal_requests_mock_factory: Mocker, @@ -128,6 +169,32 @@ def test_send_message_with_attachment( assert_sending_requests(signal_requests_mock, 1) +def test_send_message_styled_with_attachment( + signal_notification_service: SignalNotificationService, + signal_requests_mock_factory: Mocker, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test send message with attachment.""" + signal_requests_mock = signal_requests_mock_factory() + with ( + caplog.at_level( + logging.DEBUG, logger="homeassistant.components.signal_messenger.notify" + ), + tempfile.NamedTemporaryFile( + mode="w", suffix=".png", prefix=os.path.basename(__file__) + ) as temp_file, + ): + temp_file.write("attachment_data") + data = {"attachments": [temp_file.name], "text_mode": "styled"} + signal_notification_service.send_message(MESSAGE, data=data) + post_data = json.loads(signal_requests_mock.request_history[-1].text) + assert "Sending signal message" in caplog.text + assert signal_requests_mock.called + assert signal_requests_mock.call_count == 2 + assert_sending_requests(signal_requests_mock, 1) + assert post_data["text_mode"] == "styled" + + def test_send_message_with_attachment_as_url( signal_notification_service: SignalNotificationService, signal_requests_mock_factory: Mocker, @@ -147,6 +214,26 @@ def test_send_message_with_attachment_as_url( assert_sending_requests(signal_requests_mock, 1) +def test_send_message_styled_with_attachment_as_url( + signal_notification_service: SignalNotificationService, + signal_requests_mock_factory: Mocker, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test send message with attachment as URL.""" + signal_requests_mock = signal_requests_mock_factory(True, str(len(CONTENT))) + with caplog.at_level( + logging.DEBUG, logger="homeassistant.components.signal_messenger.notify" + ): + data = {"urls": [URL_ATTACHMENT], "text_mode": "styled"} + signal_notification_service.send_message(MESSAGE, data=data) + post_data = json.loads(signal_requests_mock.request_history[-1].text) + assert "Sending signal message" in caplog.text + assert signal_requests_mock.called + assert signal_requests_mock.call_count == 3 + assert_sending_requests(signal_requests_mock, 1) + assert post_data["text_mode"] == "styled" + + def test_get_attachments( signal_notification_service: SignalNotificationService, signal_requests_mock_factory: Mocker,