From 85b87ffb8b322047639db4bb2c6abe356c0ad1a9 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 24 Feb 2022 10:31:00 +0100 Subject: [PATCH] Remove deprecated APNS integration (#67158) --- homeassistant/components/apns/__init__.py | 1 - homeassistant/components/apns/const.py | 2 - homeassistant/components/apns/manifest.json | 11 - homeassistant/components/apns/notify.py | 268 ------------------ homeassistant/components/apns/services.yaml | 0 homeassistant/components/notify/services.yaml | 22 -- 6 files changed, 304 deletions(-) delete mode 100644 homeassistant/components/apns/__init__.py delete mode 100644 homeassistant/components/apns/const.py delete mode 100644 homeassistant/components/apns/manifest.json delete mode 100644 homeassistant/components/apns/notify.py delete mode 100644 homeassistant/components/apns/services.yaml diff --git a/homeassistant/components/apns/__init__.py b/homeassistant/components/apns/__init__.py deleted file mode 100644 index 9332b0d1ede..00000000000 --- a/homeassistant/components/apns/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""The apns component.""" diff --git a/homeassistant/components/apns/const.py b/homeassistant/components/apns/const.py deleted file mode 100644 index a8dc1204aa1..00000000000 --- a/homeassistant/components/apns/const.py +++ /dev/null @@ -1,2 +0,0 @@ -"""Constants for the apns component.""" -DOMAIN = "apns" diff --git a/homeassistant/components/apns/manifest.json b/homeassistant/components/apns/manifest.json deleted file mode 100644 index bcefdcf0639..00000000000 --- a/homeassistant/components/apns/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "disabled": "Integration library not compatible with Python 3.10", - "domain": "apns", - "name": "Apple Push Notification Service (APNS)", - "documentation": "https://www.home-assistant.io/integrations/apns", - "requirements": ["apns2==0.3.0"], - "after_dependencies": ["device_tracker"], - "codeowners": [], - "iot_class": "cloud_push", - "loggers": ["apns2", "hyper"] -} diff --git a/homeassistant/components/apns/notify.py b/homeassistant/components/apns/notify.py deleted file mode 100644 index 8d0dcc334e9..00000000000 --- a/homeassistant/components/apns/notify.py +++ /dev/null @@ -1,268 +0,0 @@ -"""APNS Notification platform.""" -# pylint: disable=import-error -from contextlib import suppress -import logging - -from apns2.client import APNsClient -from apns2.errors import Unregistered -from apns2.payload import Payload -import voluptuous as vol - -from homeassistant.components.device_tracker import DOMAIN as DEVICE_TRACKER_DOMAIN -from homeassistant.components.notify import ( - ATTR_DATA, - ATTR_TARGET, - PLATFORM_SCHEMA, - BaseNotificationService, -) -from homeassistant.config import load_yaml_config_file -from homeassistant.const import ATTR_NAME, CONF_NAME, CONF_PLATFORM -from homeassistant.core import ServiceCall -from homeassistant.helpers import template as template_helper -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.event import track_state_change - -from .const import DOMAIN - -APNS_DEVICES = "apns.yaml" -CONF_CERTFILE = "cert_file" -CONF_TOPIC = "topic" -CONF_SANDBOX = "sandbox" - -ATTR_PUSH_ID = "push_id" - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Required(CONF_PLATFORM): "apns", - vol.Required(CONF_NAME): cv.string, - vol.Required(CONF_CERTFILE): cv.isfile, - vol.Required(CONF_TOPIC): cv.string, - vol.Optional(CONF_SANDBOX, default=False): cv.boolean, - } -) - -REGISTER_SERVICE_SCHEMA = vol.Schema( - {vol.Required(ATTR_PUSH_ID): cv.string, vol.Optional(ATTR_NAME): cv.string} -) - -_LOGGER = logging.getLogger(__name__) - - -def get_service(hass, config, discovery_info=None): - """Return push service.""" - _LOGGER.warning( - "The Apple Push Notification Service (APNS) integration is deprecated " - "and will be removed in Home Assistant Core 2022.4" - ) - - name = config[CONF_NAME] - cert_file = config[CONF_CERTFILE] - topic = config[CONF_TOPIC] - sandbox = config[CONF_SANDBOX] - - service = ApnsNotificationService(hass, name, topic, sandbox, cert_file) - hass.services.register( - DOMAIN, f"apns_{name}", service.register, schema=REGISTER_SERVICE_SCHEMA - ) - return service - - -class ApnsDevice: - """ - The APNS Device class. - - Stores information about a device that is registered for push - notifications. - """ - - def __init__(self, push_id, name, tracking_device_id=None, disabled=False): - """Initialize APNS Device.""" - self.device_push_id = push_id - self.device_name = name - self.tracking_id = tracking_device_id - self.device_disabled = disabled - - @property - def push_id(self): - """Return the APNS id for the device.""" - return self.device_push_id - - @property - def name(self): - """Return the friendly name for the device.""" - return self.device_name - - @property - def tracking_device_id(self): - """ - Return the device Id. - - The id of a device that is tracked by the device - tracking component. - """ - return self.tracking_id - - @property - def full_tracking_device_id(self): - """ - Return the fully qualified device id. - - The full id of a device that is tracked by the device - tracking component. - """ - return f"{DEVICE_TRACKER_DOMAIN}.{self.tracking_id}" - - @property - def disabled(self): - """Return the state of the service.""" - return self.device_disabled - - def disable(self): - """Disable the device from receiving notifications.""" - self.device_disabled = True - - def __eq__(self, other): - """Return the comparison.""" - if isinstance(other, self.__class__): - return self.push_id == other.push_id and self.name == other.name - return NotImplemented - - def __ne__(self, other): - """Return the comparison.""" - return not self.__eq__(other) - - -def _write_device(out, device): - """Write a single device to file.""" - attributes = [] - if device.name is not None: - attributes.append(f"name: {device.name}") - if device.tracking_device_id is not None: - attributes.append(f"tracking_device_id: {device.tracking_device_id}") - if device.disabled: - attributes.append("disabled: True") - - out.write(device.push_id) - out.write(": {") - if attributes: - separator = ", " - out.write(separator.join(attributes)) - - out.write("}\n") - - -class ApnsNotificationService(BaseNotificationService): - """Implement the notification service for the APNS service.""" - - def __init__(self, hass, app_name, topic, sandbox, cert_file): - """Initialize APNS application.""" - self.hass = hass - self.app_name = app_name - self.sandbox = sandbox - self.certificate = cert_file - self.yaml_path = hass.config.path(f"{app_name}_{APNS_DEVICES}") - self.devices = {} - self.device_states = {} - self.topic = topic - - with suppress(FileNotFoundError): - self.devices = { - str(key): ApnsDevice( - str(key), - value.get("name"), - value.get("tracking_device_id"), - value.get("disabled", False), - ) - for (key, value) in load_yaml_config_file(self.yaml_path).items() - } - - tracking_ids = [ - device.full_tracking_device_id - for (key, device) in self.devices.items() - if device.tracking_device_id is not None - ] - track_state_change(hass, tracking_ids, self.device_state_changed_listener) - - def device_state_changed_listener(self, entity_id, from_s, to_s): - """ - Listen for state change. - - Track device state change if a device has a tracking id specified. - """ - self.device_states[entity_id] = str(to_s.state) - - def write_devices(self): - """Write all known devices to file.""" - with open(self.yaml_path, "w+", encoding="utf8") as out: - for device in self.devices.values(): - _write_device(out, device) - - def register(self, call: ServiceCall) -> None: - """Register a device to receive push messages.""" - push_id = call.data.get(ATTR_PUSH_ID) - - device_name = call.data.get(ATTR_NAME) - current_device = self.devices.get(push_id) - current_tracking_id = ( - None if current_device is None else current_device.tracking_device_id - ) - - device = ApnsDevice(push_id, device_name, current_tracking_id) - - if current_device is None: - self.devices[push_id] = device - with open(self.yaml_path, "a", encoding="utf8") as out: - _write_device(out, device) - return - - if device != current_device: - self.devices[push_id] = device - self.write_devices() - - def send_message(self, message=None, **kwargs): - """Send push message to registered devices.""" - - apns = APNsClient( - self.certificate, use_sandbox=self.sandbox, use_alternative_port=False - ) - - device_state = kwargs.get(ATTR_TARGET) - if (message_data := kwargs.get(ATTR_DATA)) is None: - message_data = {} - - if isinstance(message, str): - rendered_message = message - elif isinstance(message, template_helper.Template): - rendered_message = message.render(parse_result=False) - else: - rendered_message = "" - - payload = Payload( - alert=rendered_message, - badge=message_data.get("badge"), - sound=message_data.get("sound"), - category=message_data.get("category"), - custom=message_data.get("custom", {}), - content_available=message_data.get("content_available", False), - ) - - device_update = False - - for push_id, device in self.devices.items(): - if not device.disabled: - state = None - if device.tracking_device_id is not None: - state = self.device_states.get(device.full_tracking_device_id) - - if device_state is None or state == str(device_state): - try: - apns.send_notification(push_id, payload, topic=self.topic) - except Unregistered: - logging.error("Device %s has unregistered", push_id) - device_update = True - device.disable() - - if device_update: - self.write_devices() - - return True diff --git a/homeassistant/components/apns/services.yaml b/homeassistant/components/apns/services.yaml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/homeassistant/components/notify/services.yaml b/homeassistant/components/notify/services.yaml index 7284cb68eb6..bc31aef1a6e 100644 --- a/homeassistant/components/notify/services.yaml +++ b/homeassistant/components/notify/services.yaml @@ -51,25 +51,3 @@ persistent_notification: example: "Your Garage Door Friend" selector: text: - -apns_register: - name: Register APNS device - description: - Registers a device to receive push notifications via APNS (Apple Push - Notification Service). - fields: - push_id: - name: Push ID - description: - The device token, a 64 character hex string (256 bits). The device token - is provided to you by your client app, which receives the token after - registering itself with the remote notification service. - example: "72f2a8633655c5ce574fdc9b2b34ff8abdfc3b739b6ceb7a9ff06c1cbbf99f62" - selector: - text: - name: - name: Name - description: A friendly name for the device. - example: "Sam's iPhone" - selector: - text: