Only add Overseerr event if we are push based (#136258)

This commit is contained in:
Joost Lekkerkerker 2025-01-22 19:58:48 +01:00 committed by GitHub
parent ad205aeea3
commit 9f2a6af1ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 120 additions and 9 deletions

View File

@ -116,15 +116,13 @@ class OverseerrWebhookManager:
allowed_methods=[METH_POST],
)
if not await self.check_need_change():
self.entry.runtime_data.push = True
return
for url in self.webhook_urls:
if await self.test_and_set_webhook(url):
return
LOGGER.info("Failed to register Overseerr webhook")
if (
cloud.async_active_subscription(self.hass)
and CONF_CLOUDHOOK_URL not in self.entry.data
):
if cloud.async_active_subscription(self.hass):
LOGGER.info("Trying to register a cloudhook URL")
url = await _async_cloudhook_generate_url(self.hass, self.entry)
if await self.test_and_set_webhook(url):
@ -151,6 +149,7 @@ class OverseerrWebhookManager:
webhook_url=url,
json_payload=JSON_PAYLOAD,
)
self.entry.runtime_data.push = True
return True
return False

View File

@ -47,6 +47,7 @@ class OverseerrCoordinator(DataUpdateCoordinator[RequestCount]):
session=async_get_clientsession(hass),
)
self.url = URL.build(host=host, port=port, scheme="https" if ssl else "http")
self.push = False
async def _async_update_data(self) -> RequestCount:
"""Fetch data from API endpoint."""

View File

@ -4,11 +4,13 @@ from dataclasses import dataclass
from typing import Any
from homeassistant.components.event import EventEntity, EventEntityDescription
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import EVENT_KEY
from . import DOMAIN, EVENT_KEY
from .coordinator import OverseerrConfigEntry, OverseerrCoordinator
from .entity import OverseerrEntity
@ -47,10 +49,17 @@ async def async_setup_entry(
"""Set up Overseerr sensor entities based on a config entry."""
coordinator = entry.runtime_data
async_add_entities(
OverseerrEvent(coordinator, description) for description in EVENTS
ent_reg = er.async_get(hass)
event_entities_setup_before = ent_reg.async_get_entity_id(
Platform.EVENT, DOMAIN, f"{entry.entry_id}-media"
)
if coordinator.push or event_entities_setup_before:
async_add_entities(
OverseerrEvent(coordinator, description) for description in EVENTS
)
class OverseerrEvent(OverseerrEntity, EventEntity):
"""Defines a Overseerr event entity."""
@ -94,7 +103,7 @@ class OverseerrEvent(OverseerrEntity, EventEntity):
@property
def available(self) -> bool:
"""Return True if entity is available."""
return self._attr_available
return self._attr_available and self.coordinator.push
def parse_event(event: dict[str, Any], nullable_fields: list[str]) -> dict[str, Any]:

View File

@ -107,3 +107,64 @@ async def test_event_goes_unavailable(
assert (
hass.states.get("event.overseerr_last_media_event").state == STATE_UNAVAILABLE
)
async def test_not_push_based(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_overseerr_client_needs_change: AsyncMock,
) -> None:
"""Test event entities aren't created if not push based."""
mock_overseerr_client_needs_change.test_webhook_notification_config.return_value = (
False
)
await setup_integration(hass, mock_config_entry)
assert hass.states.get("event.overseerr_last_media_event") is None
async def test_cant_fetch_webhook_config(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_overseerr_client: AsyncMock,
) -> None:
"""Test event entities aren't created if not push based."""
mock_overseerr_client.get_webhook_notification_config.side_effect = (
OverseerrConnectionError("Boom")
)
await setup_integration(hass, mock_config_entry)
assert hass.states.get("event.overseerr_last_media_event") is None
async def test_not_push_based_but_was_before(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_overseerr_client_needs_change: AsyncMock,
entity_registry: er.EntityRegistry,
) -> None:
"""Test event entities are created if push based in the past."""
entity_registry.async_get_or_create(
Platform.EVENT,
DOMAIN,
f"{mock_config_entry.entry_id}-media",
suggested_object_id="overseerr_last_media_event",
disabled_by=None,
)
mock_overseerr_client_needs_change.test_webhook_notification_config.return_value = (
False
)
await setup_integration(hass, mock_config_entry)
assert hass.states.get("event.overseerr_last_media_event") is not None
assert (
hass.states.get("event.overseerr_last_media_event").state == STATE_UNAVAILABLE
)

View File

@ -9,6 +9,7 @@ from python_overseerr.models import WebhookNotificationOptions
from syrupy import SnapshotAssertion
from homeassistant.components import cloud
from homeassistant.components.cloud import CloudNotAvailable
from homeassistant.components.overseerr import (
CONF_CLOUDHOOK_URL,
JSON_PAYLOAD,
@ -362,10 +363,50 @@ async def test_cloudhook_not_connecting(
len(
mock_overseerr_client_needs_change.test_webhook_notification_config.mock_calls
)
== 2
== 3
)
mock_overseerr_client_needs_change.set_webhook_notification_config.assert_not_called()
assert hass.config_entries.async_entries(DOMAIN)
fake_create_cloudhook.assert_not_called()
async def test_removing_entry_with_cloud_unavailable(
hass: HomeAssistant,
mock_cloudhook_config_entry: MockConfigEntry,
mock_overseerr_client: AsyncMock,
) -> None:
"""Test handling cloud unavailable when deleting entry."""
await mock_cloud(hass)
await hass.async_block_till_done()
with (
patch("homeassistant.components.cloud.async_is_logged_in", return_value=True),
patch("homeassistant.components.cloud.async_is_connected", return_value=True),
patch.object(cloud, "async_active_subscription", return_value=True),
patch(
"homeassistant.components.cloud.async_create_cloudhook",
return_value="https://hooks.nabu.casa/ABCD",
),
patch(
"homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation",
),
patch(
"homeassistant.components.cloud.async_delete_cloudhook",
side_effect=CloudNotAvailable(),
),
):
await setup_integration(hass, mock_cloudhook_config_entry)
assert cloud.async_active_subscription(hass) is True
await hass.async_block_till_done()
assert hass.config_entries.async_entries(DOMAIN)
for config_entry in hass.config_entries.async_entries(DOMAIN):
await hass.config_entries.async_remove(config_entry.entry_id)
await hass.async_block_till_done()
assert not hass.config_entries.async_entries(DOMAIN)