Import webhook (#64102)

* Import webhook

* Adjust webhook trigger

* Fix pylint

* Add type hints to async_handle_webhook

* Revert changes to netatmo

Co-authored-by: epenet <epenet@users.noreply.github.com>
pull/64113/head
epenet 2022-01-14 12:31:02 +01:00 committed by GitHub
parent 0eff3e4b26
commit 44a686931e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 78 additions and 60 deletions

View File

@ -10,7 +10,7 @@ from typing import Any
import aiohttp
from hass_nabucasa.client import CloudClient as Interface
from homeassistant.components import persistent_notification
from homeassistant.components import persistent_notification, webhook
from homeassistant.components.alexa import (
errors as alexa_errors,
smart_home as alexa_sh,
@ -220,8 +220,8 @@ class CloudClient(Interface):
mock_source=DOMAIN,
)
response = await self._hass.components.webhook.async_handle_webhook(
found["webhook_id"], request
response = await webhook.async_handle_webhook(
self._hass, found["webhook_id"], request
)
response_dict = serialize_response(response)

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.auth.models import User
from homeassistant.components import webhook
from homeassistant.core import callback
from homeassistant.helpers.typing import UNDEFINED
from homeassistant.util.logging import async_create_catching_coro
@ -59,7 +60,7 @@ class CloudPreferences:
await self._save_prefs(
{
**self._prefs,
PREF_GOOGLE_LOCAL_WEBHOOK_ID: self._hass.components.webhook.async_generate_id(),
PREF_GOOGLE_LOCAL_WEBHOOK_ID: webhook.async_generate_id(),
}
)
@ -305,7 +306,8 @@ class CloudPreferences:
self._hass.async_create_task(async_create_catching_coro(listener(self)))
@callback
def _empty_config(self, username):
@staticmethod
def _empty_config(username):
"""Return an empty config."""
return {
PREF_ALEXA_DEFAULT_EXPOSE: DEFAULT_EXPOSED_DOMAINS,
@ -317,7 +319,7 @@ class CloudPreferences:
PREF_ENABLE_REMOTE: False,
PREF_GOOGLE_DEFAULT_EXPOSE: DEFAULT_EXPOSED_DOMAINS,
PREF_GOOGLE_ENTITY_CONFIGS: {},
PREF_GOOGLE_LOCAL_WEBHOOK_ID: self._hass.components.webhook.async_generate_id(),
PREF_GOOGLE_LOCAL_WEBHOOK_ID: webhook.async_generate_id(),
PREF_GOOGLE_SECURE_DEVICES_PIN: None,
PREF_USERNAME: username,
}

View File

@ -4,6 +4,7 @@ import logging
from aiohttp import web
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant
@ -65,15 +66,15 @@ async def handle_webhook(hass, webhook_id, request):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "DialogFlow", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "DialogFlow", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
return True

View File

@ -4,6 +4,7 @@ from http import HTTPStatus
from aiohttp import web
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_LATITUDE,
@ -139,8 +140,8 @@ def _set_location(hass, data, location_name):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "Geofency", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "Geofency", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
@ -149,7 +150,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
hass.data[DOMAIN]["unsub_device_tracker"].pop(entry.entry_id)()
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@ -4,6 +4,7 @@ from http import HTTPStatus
from aiohttp import web
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.components.device_tracker import ATTR_BATTERY
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE, CONF_WEBHOOK_ID, Platform
@ -94,8 +95,8 @@ async def handle_webhook(hass, webhook_id, request):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "GPSLogger", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "GPSLogger", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
@ -105,7 +106,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
hass.data[DOMAIN]["unsub_device_tracker"].pop(entry.entry_id)()
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@ -7,6 +7,7 @@ import pyfttt
import requests
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant, ServiceCall
@ -115,15 +116,15 @@ async def handle_webhook(hass, webhook_id, request):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "IFTTT", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "IFTTT", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
return True

View File

@ -7,6 +7,7 @@ import logging
from aiohttp import web
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_ID,
@ -116,8 +117,8 @@ async def handle_webhook(hass, webhook_id, request):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "Locative", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "Locative", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
@ -126,7 +127,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
hass.data[DOMAIN]["unsub_device_tracker"].pop(entry.entry_id)()
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@ -6,6 +6,7 @@ import logging
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_DOMAIN, CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant
@ -89,15 +90,15 @@ async def verify_webhook(hass, token=None, timestamp=None, signature=None):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "Mailgun", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "Mailgun", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
return True

View File

@ -8,7 +8,7 @@ from aiohttp.web import json_response
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import mqtt
from homeassistant.components import mqtt, webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_GPS_ACCURACY,
@ -101,9 +101,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async_when_setup(hass, "mqtt", async_connect_mqtt)
hass.components.webhook.async_register(
DOMAIN, "OwnTracks", webhook_id, handle_webhook
)
webhook.async_register(hass, DOMAIN, "OwnTracks", webhook_id, handle_webhook)
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
@ -116,7 +114,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload an OwnTracks config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
hass.data[DOMAIN]["unsub"]()

View File

@ -2,6 +2,7 @@
import secrets
from homeassistant import config_entries
from homeassistant.components import webhook
from homeassistant.const import CONF_WEBHOOK_ID
from .const import DOMAIN
@ -66,14 +67,14 @@ class OwnTracksFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def _get_webhook_id(self):
"""Generate webhook ID."""
webhook_id = self.hass.components.webhook.async_generate_id()
webhook_id = webhook.async_generate_id()
if self.hass.components.cloud.async_active_subscription():
webhook_url = await self.hass.components.cloud.async_create_cloudhook(
webhook_id
)
cloudhook = True
else:
webhook_url = self.hass.components.webhook.async_generate_url(webhook_id)
webhook_url = webhook.async_generate_url(self.hass, webhook_id)
cloudhook = False
return webhook_id, webhook_url, cloudhook

View File

@ -1,5 +1,4 @@
"""Support for Plaato devices."""
from datetime import timedelta
import logging
@ -23,6 +22,7 @@ from pyplaato.plaato import (
)
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.components.sensor import DOMAIN as SENSOR
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
@ -106,8 +106,8 @@ def async_setup_webhook(hass: HomeAssistant, entry: ConfigEntry):
_set_entry_data(entry, hass)
hass.components.webhook.async_register(
DOMAIN, f"{DOMAIN}.{device_name}", webhook_id, handle_webhook
webhook.async_register(
hass, DOMAIN, f"{DOMAIN}.{device_name}", webhook_id, handle_webhook
)
@ -160,7 +160,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_webhook(hass: HomeAssistant, entry: ConfigEntry):
"""Unload webhook based entry."""
if entry.data[CONF_WEBHOOK_ID] is not None:
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
return await async_unload_platforms(hass, entry, PLATFORMS)

View File

@ -3,6 +3,7 @@ from pyplaato.plaato import PlaatoDeviceType
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_SCAN_INTERVAL, CONF_TOKEN, CONF_WEBHOOK_ID
from homeassistant.core import callback
@ -139,14 +140,14 @@ class PlaatoConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def _get_webhook_id(self):
"""Generate webhook ID."""
webhook_id = self.hass.components.webhook.async_generate_id()
webhook_id = webhook.async_generate_id()
if self.hass.components.cloud.async_active_subscription():
webhook_url = await self.hass.components.cloud.async_create_cloudhook(
webhook_id
)
cloudhook = True
else:
webhook_url = self.hass.components.webhook.async_generate_url(webhook_id)
webhook_url = webhook.async_generate_url(self.hass, webhook_id)
cloudhook = False
return webhook_id, webhook_url, cloudhook
@ -209,7 +210,7 @@ class PlaatoOptionsFlowHandler(config_entries.OptionsFlow):
webhook_url = (
""
if webhook_id is None
else self.hass.components.webhook.async_generate_url(webhook_id)
else webhook.async_generate_url(self.hass, webhook_id)
)
return self.async_show_form(

View File

@ -7,6 +7,7 @@ from pypoint import PointSession
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_CLIENT_ID,
@ -118,8 +119,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_webhook(hass: HomeAssistant, entry: ConfigEntry, session):
"""Set up a webhook to handle binary sensor events."""
if CONF_WEBHOOK_ID not in entry.data:
webhook_id = hass.components.webhook.async_generate_id()
webhook_url = hass.components.webhook.async_generate_url(webhook_id)
webhook_id = webhook.async_generate_id()
webhook_url = webhook.async_generate_url(hass, webhook_id)
_LOGGER.info("Registering new webhook at: %s", webhook_url)
hass.config_entries.async_update_entry(
@ -136,14 +137,14 @@ async def async_setup_webhook(hass: HomeAssistant, entry: ConfigEntry, session):
["*"],
)
hass.components.webhook.async_register(
DOMAIN, "Point", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "Point", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
session = hass.data[DOMAIN].pop(entry.entry_id)
await session.remove_webhook()

View File

@ -10,6 +10,7 @@ import aiohttp
import async_timeout
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.components.camera import PLATFORM_SCHEMA, STATE_IDLE, Camera
from homeassistant.components.camera.const import DOMAIN
from homeassistant.const import CONF_NAME, CONF_TIMEOUT, CONF_WEBHOOK_ID
@ -106,15 +107,15 @@ class PushCamera(Camera):
self._current_image = None
self._image_field = image_field
self.webhook_id = webhook_id
self.webhook_url = hass.components.webhook.async_generate_url(webhook_id)
self.webhook_url = webhook.async_generate_url(hass, webhook_id)
async def async_added_to_hass(self):
"""Call when entity is added to hass."""
self.hass.data[PUSH_CAMERA_DATA][self.webhook_id] = self
try:
self.hass.components.webhook.async_register(
DOMAIN, self.name, self.webhook_id, handle_webhook
webhook.async_register(
self.hass, DOMAIN, self.name, self.webhook_id, handle_webhook
)
except ValueError:
_LOGGER.error(

View File

@ -1,6 +1,7 @@
"""Webhooks used by rachio."""
from aiohttp import web
from homeassistant.components import webhook
from homeassistant.const import URL_API
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_send
@ -97,8 +98,8 @@ def async_register_webhook(hass, webhook_id, entry_id):
return web.Response(status=web.HTTPNoContent.status_code)
hass.components.webhook.async_register(
DOMAIN, "Rachio", webhook_id, _async_handle_rachio_webhook
webhook.async_register(
hass, DOMAIN, "Rachio", webhook_id, _async_handle_rachio_webhook
)
@ -110,7 +111,7 @@ async def async_get_or_create_registered_webhook_id_and_url(hass, entry):
webhook_url = None
if not (webhook_id := config.get(CONF_WEBHOOK_ID)):
webhook_id = hass.components.webhook.async_generate_id()
webhook_id = webhook.async_generate_id()
config[CONF_WEBHOOK_ID] = webhook_id
updated_config = True
@ -124,7 +125,7 @@ async def async_get_or_create_registered_webhook_id_and_url(hass, entry):
webhook_url = cloudhook_url
if not webhook_url:
webhook_url = hass.components.webhook.async_generate_url(webhook_id)
webhook_url = webhook.async_generate_url(hass, webhook_id)
if updated_config:
hass.config_entries.async_update_entry(entry, data=config)

View File

@ -4,6 +4,7 @@ from http import HTTPStatus
from aiohttp import web
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ID, CONF_WEBHOOK_ID, Platform
from homeassistant.core import HomeAssistant
@ -93,8 +94,8 @@ async def handle_webhook(hass, webhook_id, request):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "Traccar", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "Traccar", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
@ -103,7 +104,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
hass.data[DOMAIN]["unsub_device_tracker"].pop(entry.entry_id)()
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@ -3,6 +3,7 @@ from twilio.rest import Client
from twilio.twiml import TwiML
import voluptuous as vol
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.core import HomeAssistant
@ -55,15 +56,15 @@ async def handle_webhook(hass, webhook_id, request):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure based on config entry."""
hass.components.webhook.async_register(
DOMAIN, "Twilio", entry.data[CONF_WEBHOOK_ID], handle_webhook
webhook.async_register(
hass, DOMAIN, "Twilio", entry.data[CONF_WEBHOOK_ID], handle_webhook
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID])
webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
return True

View File

@ -82,7 +82,9 @@ def async_generate_path(webhook_id: str) -> str:
@bind_hass
async def async_handle_webhook(hass, webhook_id, request):
async def async_handle_webhook(
hass: HomeAssistant, webhook_id: str, request: Request
) -> Response:
"""Handle a webhook."""
handlers = hass.data.setdefault(DOMAIN, {})
@ -141,7 +143,7 @@ class WebhookView(HomeAssistantView):
requires_auth = False
cors_allowed = True
async def _handle(self, request: Request, webhook_id):
async def _handle(self, request: Request, webhook_id: str) -> Response:
"""Handle webhook call."""
# pylint: disable=no-self-use
_LOGGER.debug("Handling webhook %s payload for %s", request.method, webhook_id)

View File

@ -8,6 +8,8 @@ from homeassistant.const import CONF_PLATFORM, CONF_WEBHOOK_ID
from homeassistant.core import HassJob, callback
import homeassistant.helpers.config_validation as cv
from . import async_register, async_unregister
# mypy: allow-untyped-defs
DEPENDENCIES = ("webhook",)
@ -40,7 +42,8 @@ async def async_attach_trigger(hass, config, action, automation_info):
trigger_data = automation_info["trigger_data"]
webhook_id = config.get(CONF_WEBHOOK_ID)
job = HassJob(action)
hass.components.webhook.async_register(
async_register(
hass,
automation_info["domain"],
automation_info["name"],
webhook_id,
@ -50,6 +53,6 @@ async def async_attach_trigger(hass, config, action, automation_info):
@callback
def unregister():
"""Unregister webhook."""
hass.components.webhook.async_unregister(webhook_id)
async_unregister(hass, webhook_id)
return unregister