mirror of
https://github.com/home-assistant/core.git
synced 2025-09-08 14:21:33 +02:00
Remove deprecated notify platform from Mastodon (#149735)
This commit is contained in:
@@ -8,12 +8,11 @@ from homeassistant.const import (
|
||||
CONF_ACCESS_TOKEN,
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
CONF_NAME,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import config_validation as cv, discovery
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.util import slugify
|
||||
|
||||
@@ -22,7 +21,7 @@ from .coordinator import MastodonConfigEntry, MastodonCoordinator, MastodonData
|
||||
from .services import setup_services
|
||||
from .utils import construct_mastodon_username, create_mastodon_client
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.NOTIFY, Platform.SENSOR]
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
|
||||
|
||||
@@ -53,26 +52,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: MastodonConfigEntry) ->
|
||||
|
||||
entry.runtime_data = MastodonData(client, instance, account, coordinator)
|
||||
|
||||
await discovery.async_load_platform(
|
||||
hass,
|
||||
Platform.NOTIFY,
|
||||
DOMAIN,
|
||||
{CONF_NAME: entry.title, "client": client},
|
||||
{},
|
||||
)
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(
|
||||
entry, [platform for platform in PLATFORMS if platform != Platform.NOTIFY]
|
||||
)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: MastodonConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(
|
||||
entry, [platform for platform in PLATFORMS if platform != Platform.NOTIFY]
|
||||
)
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
||||
|
||||
async def async_migrate_entry(hass: HomeAssistant, entry: MastodonConfigEntry) -> bool:
|
||||
|
@@ -1,152 +0,0 @@
|
||||
"""Mastodon platform for notify component."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, cast
|
||||
|
||||
from mastodon import Mastodon
|
||||
from mastodon.Mastodon import MastodonAPIError, MediaAttachment
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.notify import (
|
||||
ATTR_DATA,
|
||||
PLATFORM_SCHEMA as NOTIFY_PLATFORM_SCHEMA,
|
||||
BaseNotificationService,
|
||||
)
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv, issue_registry as ir
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import (
|
||||
ATTR_CONTENT_WARNING,
|
||||
ATTR_MEDIA_WARNING,
|
||||
CONF_BASE_URL,
|
||||
DEFAULT_URL,
|
||||
DOMAIN,
|
||||
)
|
||||
from .utils import get_media_type
|
||||
|
||||
ATTR_MEDIA = "media"
|
||||
ATTR_TARGET = "target"
|
||||
|
||||
PLATFORM_SCHEMA = NOTIFY_PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_ACCESS_TOKEN): cv.string,
|
||||
vol.Required(CONF_CLIENT_ID): cv.string,
|
||||
vol.Required(CONF_CLIENT_SECRET): cv.string,
|
||||
vol.Optional(CONF_BASE_URL, default=DEFAULT_URL): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
INTEGRATION_TITLE = "Mastodon"
|
||||
|
||||
|
||||
async def async_get_service(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> MastodonNotificationService | None:
|
||||
"""Get the Mastodon notification service."""
|
||||
if discovery_info is None:
|
||||
return None
|
||||
|
||||
client = cast(Mastodon, discovery_info.get("client"))
|
||||
|
||||
return MastodonNotificationService(hass, client)
|
||||
|
||||
|
||||
class MastodonNotificationService(BaseNotificationService):
|
||||
"""Implement the notification service for Mastodon."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
client: Mastodon,
|
||||
) -> None:
|
||||
"""Initialize the service."""
|
||||
|
||||
self.client = client
|
||||
|
||||
def send_message(self, message: str = "", **kwargs: Any) -> None:
|
||||
"""Toot a message, with media perhaps."""
|
||||
|
||||
ir.create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
"deprecated_notify_action_mastodon",
|
||||
breaks_in_ha_version="2025.9.0",
|
||||
is_fixable=False,
|
||||
issue_domain=DOMAIN,
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
translation_key="deprecated_notify_action",
|
||||
)
|
||||
|
||||
target = None
|
||||
if (target_list := kwargs.get(ATTR_TARGET)) is not None:
|
||||
target = cast(list[str], target_list)[0]
|
||||
|
||||
data = kwargs.get(ATTR_DATA)
|
||||
|
||||
media = None
|
||||
mediadata = None
|
||||
sensitive = False
|
||||
content_warning = None
|
||||
|
||||
if data:
|
||||
media = data.get(ATTR_MEDIA)
|
||||
if media:
|
||||
if not self.hass.config.is_allowed_path(media):
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="not_whitelisted_directory",
|
||||
translation_placeholders={"media": media},
|
||||
)
|
||||
mediadata = self._upload_media(media)
|
||||
|
||||
sensitive = data.get(ATTR_MEDIA_WARNING)
|
||||
content_warning = data.get(ATTR_CONTENT_WARNING)
|
||||
|
||||
if mediadata:
|
||||
try:
|
||||
self.client.status_post(
|
||||
message,
|
||||
visibility=target,
|
||||
spoiler_text=content_warning,
|
||||
media_ids=mediadata.id,
|
||||
sensitive=sensitive,
|
||||
)
|
||||
except MastodonAPIError as err:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="unable_to_send_message",
|
||||
) from err
|
||||
|
||||
else:
|
||||
try:
|
||||
self.client.status_post(
|
||||
message, visibility=target, spoiler_text=content_warning
|
||||
)
|
||||
except MastodonAPIError as err:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="unable_to_send_message",
|
||||
) from err
|
||||
|
||||
def _upload_media(self, media_path: Any = None) -> MediaAttachment:
|
||||
"""Upload media."""
|
||||
with open(media_path, "rb"):
|
||||
media_type = get_media_type(media_path)
|
||||
try:
|
||||
mediadata: MediaAttachment = self.client.media_post(
|
||||
media_path, mime_type=media_type
|
||||
)
|
||||
except MastodonAPIError as err:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="unable_to_upload_image",
|
||||
translation_placeholders={"media_path": media_path},
|
||||
) from err
|
||||
|
||||
return mediadata
|
@@ -26,10 +26,7 @@ rules:
|
||||
unique-config-entry: done
|
||||
|
||||
# Silver
|
||||
action-exceptions:
|
||||
status: todo
|
||||
comment: |
|
||||
Awaiting legacy Notify deprecation.
|
||||
action-exceptions: done
|
||||
config-entry-unloading: done
|
||||
docs-configuration-parameters:
|
||||
status: exempt
|
||||
@@ -39,19 +36,12 @@ rules:
|
||||
entity-unavailable: done
|
||||
integration-owner: done
|
||||
log-when-unavailable: done
|
||||
parallel-updates:
|
||||
status: todo
|
||||
comment: |
|
||||
Awaiting legacy Notify deprecation.
|
||||
parallel-updates: done
|
||||
reauthentication-flow:
|
||||
status: todo
|
||||
comment: |
|
||||
Waiting to move to oAuth.
|
||||
test-coverage:
|
||||
status: todo
|
||||
comment: |
|
||||
Awaiting legacy Notify deprecation.
|
||||
|
||||
test-coverage: done
|
||||
# Gold
|
||||
devices: done
|
||||
diagnostics: done
|
||||
|
@@ -42,12 +42,6 @@
|
||||
"message": "{media} is not a whitelisted directory."
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_notify_action": {
|
||||
"title": "Deprecated Notify action used for Mastodon",
|
||||
"description": "The Notify action for Mastodon is deprecated.\n\nUse the `mastodon.post` action instead."
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"followers": {
|
||||
|
@@ -1,65 +0,0 @@
|
||||
"""Tests for the Mastodon notify platform."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from mastodon.Mastodon import MastodonAPIError
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_notify(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_mastodon_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test sending a message."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert hass.services.has_service(NOTIFY_DOMAIN, "trwnh_mastodon_social")
|
||||
|
||||
await hass.services.async_call(
|
||||
NOTIFY_DOMAIN,
|
||||
"trwnh_mastodon_social",
|
||||
{
|
||||
"message": "test toot",
|
||||
},
|
||||
blocking=True,
|
||||
return_response=False,
|
||||
)
|
||||
|
||||
assert mock_mastodon_client.status_post.assert_called_once
|
||||
|
||||
|
||||
async def test_notify_failed(
|
||||
hass: HomeAssistant,
|
||||
mock_mastodon_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the notify raising an error."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_mastodon_client.status_post.side_effect = MastodonAPIError
|
||||
|
||||
with pytest.raises(HomeAssistantError, match="Unable to send message"):
|
||||
await hass.services.async_call(
|
||||
NOTIFY_DOMAIN,
|
||||
"trwnh_mastodon_social",
|
||||
{
|
||||
"message": "test toot",
|
||||
},
|
||||
blocking=True,
|
||||
return_response=False,
|
||||
)
|
Reference in New Issue
Block a user