Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions custom_components/pyscript/stubs/pyscript_builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
and documentation live here.
"""

# pylint: disable=unnecessary-ellipsis, invalid-name, redefined-outer-name
# pylint: disable=unnecessary-ellipsis, invalid-name, redefined-outer-name, dangerous-default-value
from __future__ import annotations

from asyncio import Task
from collections.abc import Callable
from datetime import datetime
from typing import Any, Literal

from homeassistant.components.webhook import SUPPORTED_METHODS
from homeassistant.core import HomeAssistant

hass: HomeAssistant
Expand Down Expand Up @@ -121,6 +122,25 @@ def mqtt_trigger(
...


def webhook_trigger(
webhook_id: str,
str_expr: str | None = None,
local_only: bool = True,
methods: set[SUPPORTED_METHODS] | list[SUPPORTED_METHODS] = {"POST", "PUT"},
kwargs: dict | None = None,
) -> Callable[..., Any]:
"""Trigger when a request is made to a webhook endpoint.

Args:
webhook_id: Webhook id to listen to.
str_expr: Optional expression evaluated against ``trigger_type``, ``webhook_id``, and ``payload``.
local_only: If False, allow requests from anywhere on the internet.
methods: HTTP methods to allow.
kwargs: Extra keyword arguments merged into each invocation.
"""
...


def pyscript_compile() -> Callable[..., Any]:
"""Compile the wrapped function into native (synchronous) Python.

Expand Down Expand Up @@ -425,7 +445,7 @@ def wait_until(
mqtt_trigger_encoding: str | None = None,
webhook_trigger: str | list[str] | None = None,
webhook_local_only: bool = True,
webhook_methods: list[str] = ("POST", "PUT"),
webhook_methods: list[SUPPORTED_METHODS] = ("POST", "PUT"),
timeout: int | float | None = None,
state_check_now: bool = True,
state_hold: int | float | None = None,
Expand Down
80 changes: 40 additions & 40 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,13 @@ access the names of those built-in events by importing from ``homeassistant.cons
Function Trigger Decorators
---------------------------

There are four decorators for defining state, time, event and MQTT triggers, and two decorators for
defining whether any trigger actually causes the function to run (i.e., is active), based on
state-based expressions or one or more time-windows. The decorators should appear immediately before
the function they refer to. A single function can have any or all of the decorator types specified.
Multiple trigger decorators of the same type can be added to a single function, but only one
``@state_active``, ``@time_active`` or ``@task_unique`` can be used per function.
There are five decorators for defining state, time, event, MQTT and webhook triggers, and two
decorators for defining whether any trigger actually causes the function to run (i.e., is active),
based on state-based expressions or one or more time-windows. The decorators should appear
immediately before the function they refer to. A single function can have any or all of the
decorator types specified. Multiple trigger decorators of the same type can be added to a single
function, but only one ``@state_active``, ``@time_active`` or ``@task_unique`` can be used per
function.

A Python function with decorators is still a normal Python function that can be called by any other
Python function. The decorators have no effect in the case where you call it directly from another
Expand Down Expand Up @@ -863,6 +864,39 @@ must be set up to use ``@mqtt_trigger``.
task.sleep(300)
light.turn_off(entity_id="light.carport")

@webhook_trigger
^^^^^^^^^^^^^^^^

.. code:: python

@webhook_trigger(webhook_id, str_expr=None, local_only=True, methods={"POST", "PUT"}, kwargs=None)

``@webhook_trigger`` listens for calls to a `Home Assistant webhook <https://www.home-assistant.io/docs/automation/trigger/#webhook-trigger>`__ at ``your_hass_url/api/webhook/webhook_id`` and triggers whenever a request is made at that endpoint. Multiple ``@webhook_trigger`` decorators can be applied to a single function if you want to trigger off different webhook ids.

Setting ``local_only`` option to ``False`` will allow request made from anywhere on the internet (as opposed to just on local network).
The methods option needs to be an list or set with elements ``GET``, ``HEAD``, ``POST``, or ``PUT``.

An optional ``str_expr`` can be used to match against payload message data, and the trigger will only occur if that expression evaluates to ``True`` or non-zero. This expression has available these three
variables:

- ``trigger_type`` is set to "webhook"
- ``webhook_id`` is set to the webhook_id that was called.
- ``payload`` is the data/json that was sent in the request returned as a dictionary.

When the ``@webhook_trigger`` occurs, those same variables are passed as keyword arguments to the function in case it needs them. Additional keyword parameters can be specified by setting the optional ``kwargs`` argument to a ``dict`` with the keywords and values.

An simple example looks like

.. code:: python

@webhook_trigger("myid", kwargs={"extra": 10})
def webhook_test(payload, extra):
log.info(f"It ran! {payload}, {extra}")

which if called using the curl command ``curl -X POST -d 'key1=xyz&key2=abc' hass_url/api/webhook/myid`` outputs ``It ran! {'key1': 'xyz', 'key2': 'abc'}, 10``

NOTE: A webhook_id can only be used by either a built-in Home Assistant automation or pyscript, but not both. Trying to use the same webhook_id in both will result in an error.

@state_active
^^^^^^^^^^^^^

Expand Down Expand Up @@ -950,40 +984,6 @@ matches any of the positive arguments, and none of the negative arguments.
log.info(f"got motion. turning on the lights")
light.turn_on(entity_id="light.hallway")


@webhook_trigger
^^^^^^^^^^^^^^^^

.. code:: python

@webhook_trigger(webhook_id, str_expr=None, local_only=True, methods={"POST", "PUT"}, kwargs=None)

``@webhook_trigger`` listens for calls to a `Home Assistant webhook <https://www.home-assistant.io/docs/automation/trigger/#webhook-trigger>`__ at ``your_hass_url/api/webhook/webhook_id`` and triggers whenever a request is made at that endpoint. Multiple ``@webhook_trigger`` decorators can be applied to a single function if you want to trigger off different webhook ids.

Setting ``local_only`` option to ``False`` will allow request made from anywhere on the internet (as opposed to just on local network).
The methods option needs to be an list or set with elements ``GET``, ``HEAD``, ``POST``, or ``PUT``.

An optional ``str_expr`` can be used to match against payload message data, and the trigger will only occur if that expression evaluates to ``True`` or non-zero. This expression has available these three
variables:

- ``trigger_type`` is set to "webhook"
- ``webhook_id`` is set to the webhook_id that was called.
- ``payload`` is the data/json that was sent in the request returned as a dictionary.

When the ``@webhook_trigger`` occurs, those same variables are passed as keyword arguments to the function in case it needs them. Additional keyword parameters can be specified by setting the optional ``kwargs`` argument to a ``dict`` with the keywords and values.

An simple example looks like

.. code:: python

@webhook_trigger("myid", kwargs={"extra": 10})
def webhook_test(payload, extra):
log.info(f"It ran! {payload}, {extra}")

which if called using the curl command ``curl -X POST -d 'key1=xyz&key2=abc' hass_url/api/webhook/myid`` outputs ``It ran! {'key1': 'xyz', 'key2': 'abc'}, 10``

NOTE: A webhook_id can only be used by either a built-in Home Assistant automation or pyscript, but not both. Trying to use the same webhook_id in both will result in an error.

Other Function Decorators
-------------------------

Expand Down
Loading