From dc371cf46d080fa5c9c1fe3d2823a0d5e8b5a2ed Mon Sep 17 00:00:00 2001 From: Manu <4445816+tr4nt0r@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:53:13 +0200 Subject: [PATCH] Ignore errors when PlayStation Network group fetch is blocked by parental controls (#150364) --- .../playstation_network/coordinator.py | 38 +++++++++++++++---- .../playstation_network/strings.json | 6 +++ .../playstation_network/test_notify.py | 29 +++++++++++++- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/playstation_network/coordinator.py b/homeassistant/components/playstation_network/coordinator.py index c1872a31613..2dced4b64ad 100644 --- a/homeassistant/components/playstation_network/coordinator.py +++ b/homeassistant/components/playstation_network/coordinator.py @@ -5,6 +5,7 @@ from __future__ import annotations from abc import abstractmethod from dataclasses import dataclass from datetime import timedelta +import json import logging from typing import TYPE_CHECKING, Any @@ -21,12 +22,14 @@ from psnawp_api.models.group.group_datatypes import GroupDetails from psnawp_api.models.trophies import TrophyTitle from homeassistant.config_entries import ConfigEntry, ConfigSubentry +from homeassistant.const import CONF_NAME from homeassistant.core import HomeAssistant from homeassistant.exceptions import ( ConfigEntryAuthFailed, ConfigEntryError, ConfigEntryNotReady, ) +from homeassistant.helpers import issue_registry as ir from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN @@ -163,13 +166,34 @@ class PlaystationNetworkGroupsUpdateCoordinator( async def update_data(self) -> dict[str, GroupDetails]: """Update groups data.""" - return await self.hass.async_add_executor_job( - lambda: { - group_info.group_id: group_info.get_group_information() - for group_info in self.psn.client.get_groups() - if not group_info.group_id.startswith("~") - } - ) + try: + return await self.hass.async_add_executor_job( + lambda: { + group_info.group_id: group_info.get_group_information() + for group_info in self.psn.client.get_groups() + if not group_info.group_id.startswith("~") + } + ) + except PSNAWPForbiddenError as e: + try: + error = json.loads(e.args[0]) + except json.JSONDecodeError as err: + raise PSNAWPServerError from err + ir.async_create_issue( + self.hass, + DOMAIN, + f"group_chat_forbidden_{self.config_entry.entry_id}", + is_fixable=False, + issue_domain=DOMAIN, + severity=ir.IssueSeverity.ERROR, + translation_key="group_chat_forbidden", + translation_placeholders={ + CONF_NAME: self.config_entry.title, + "error_message": error["error"]["message"], + }, + ) + await self.async_shutdown() + return {} class PlaystationNetworkFriendDataCoordinator( diff --git a/homeassistant/components/playstation_network/strings.json b/homeassistant/components/playstation_network/strings.json index 100e749f436..72648be2cc2 100644 --- a/homeassistant/components/playstation_network/strings.json +++ b/homeassistant/components/playstation_network/strings.json @@ -164,5 +164,11 @@ "name": "Direct message: {name}" } } + }, + "issues": { + "group_chat_forbidden": { + "title": "Failed to retrieve group chats for {name}", + "description": "The PlayStation Network integration was unable to retrieve group chats for **{name}**.\n\nThis is likely due to insufficient permissions (Error: `{error_message}`).\n\nTo resolve this issue, please ensure the account's chat and messaging feature is not restricted by parental controls or other privacy settings.\n\nIf the restriction is intentional, you can safely ignore this message." + } } } diff --git a/tests/components/playstation_network/test_notify.py b/tests/components/playstation_network/test_notify.py index e99609980ae..a4ef6584a6e 100644 --- a/tests/components/playstation_network/test_notify.py +++ b/tests/components/playstation_network/test_notify.py @@ -18,11 +18,12 @@ from homeassistant.components.notify import ( DOMAIN as NOTIFY_DOMAIN, SERVICE_SEND_MESSAGE, ) +from homeassistant.components.playstation_network.const import DOMAIN from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import entity_registry as er +from homeassistant.helpers import entity_registry as er, issue_registry as ir from tests.common import MockConfigEntry, snapshot_platform @@ -134,3 +135,29 @@ async def test_send_message_exceptions( ) mock_psnawpapi.group.return_value.send_message.assert_called_once_with("henlo fren") + + +async def test_notify_skip_forbidden( + hass: HomeAssistant, + config_entry: MockConfigEntry, + mock_psnawpapi: MagicMock, + issue_registry: ir.IssueRegistry, +) -> None: + """Test we skip creation of notifiers if forbidden by parental controls.""" + + mock_psnawpapi.me.return_value.get_groups.side_effect = PSNAWPForbiddenError( + """{"error": {"message": "Not permitted by parental control"}}""" + ) + + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.LOADED + + state = hass.states.get("notify.testuser_group_publicuniversalfriend") + assert state is None + + assert issue_registry.async_get_issue( + domain=DOMAIN, issue_id=f"group_chat_forbidden_{config_entry.entry_id}" + )