mirror of https://github.com/caronc/apprise
Add Power Automate (Workflows/MS Teams) alternative URL support (#1407)
parent
2d12b7e50d
commit
27091b5b34
|
@ -29,12 +29,19 @@
|
||||||
# https://support.microsoft.com/en-us/office/browse-and-add-workflows-\
|
# https://support.microsoft.com/en-us/office/browse-and-add-workflows-\
|
||||||
# in-microsoft-teams-4998095c-8b72-4b0e-984c-f2ad39e6ba9a
|
# in-microsoft-teams-4998095c-8b72-4b0e-984c-f2ad39e6ba9a
|
||||||
|
|
||||||
# Your webhook will look somthing like this:
|
# Your webhook will look somthing like this (legacy):
|
||||||
# https://prod-161.westeurope.logic.azure.com:443/\
|
# https://prod-161.westeurope.logic.azure.com:443/\
|
||||||
# workflows/643e69f83c8944438d68119179a10a64/triggers/manual/\
|
# workflows/643e69f83c8944438d68119179a10a64/triggers/manual/\
|
||||||
# paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&\
|
# paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&\
|
||||||
# sv=1.0&sig=KODuebWbDGYFr0z0eu-6Rj8aUKz7108W3wrNJZxFE5A
|
# sv=1.0&sig=KODuebWbDGYFr0z0eu-6Rj8aUKz7108W3wrNJZxFE5A
|
||||||
#
|
#
|
||||||
|
# Or it may now look something like this:
|
||||||
|
# https://prod-161.westeurope.logic.azure.com:443/\
|
||||||
|
# powerautomate/automations/direct/\
|
||||||
|
# workflows/643e69f83c8944438d68119179a10a64/triggers/manual/\
|
||||||
|
# paths/invoke?api-version=2022-03-01-preview&sp=%2Ftriggers%2Fmanual%2F\
|
||||||
|
# run&sv=1.0&sig=KODuebWbDGYFr0z0eu-6Rj8aUKz7108W3wrNJZxFE5A
|
||||||
|
#
|
||||||
# Yes... The URL is that big... But it looks like this (greatly simplified):
|
# Yes... The URL is that big... But it looks like this (greatly simplified):
|
||||||
# https://HOST:PORT/workflows/ABCD/triggers/manual/path/...sig=DEFG
|
# https://HOST:PORT/workflows/ABCD/triggers/manual/path/...sig=DEFG
|
||||||
# ^ ^ ^ ^
|
# ^ ^ ^ ^
|
||||||
|
@ -63,6 +70,14 @@ from ..utils.templates import TemplateType, apply_template
|
||||||
from .base import NotifyBase
|
from .base import NotifyBase
|
||||||
|
|
||||||
|
|
||||||
|
class APIVersion:
|
||||||
|
"""
|
||||||
|
Define API Versions
|
||||||
|
"""
|
||||||
|
WORKFLOW = "2016-06-01"
|
||||||
|
POWER_AUTOMATE = "2022-03-01-preview"
|
||||||
|
|
||||||
|
|
||||||
class NotifyWorkflows(NotifyBase):
|
class NotifyWorkflows(NotifyBase):
|
||||||
"""A wrapper for Microsoft Workflows (MS Teams) Notifications."""
|
"""A wrapper for Microsoft Workflows (MS Teams) Notifications."""
|
||||||
|
|
||||||
|
@ -149,11 +164,17 @@ class NotifyWorkflows(NotifyBase):
|
||||||
"default": True,
|
"default": True,
|
||||||
"map_to": "include_image",
|
"map_to": "include_image",
|
||||||
},
|
},
|
||||||
|
"pa": {
|
||||||
|
"name": _("Use Power Automate URL"),
|
||||||
|
"type": "bool",
|
||||||
|
"default": False,
|
||||||
|
"map_to": "power_automate",
|
||||||
|
},
|
||||||
|
"powerautomate": {"alias_of": "pa"},
|
||||||
"wrap": {
|
"wrap": {
|
||||||
"name": _("Wrap Text"),
|
"name": _("Wrap Text"),
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"default": True,
|
"default": True,
|
||||||
"map_to": "wrap",
|
|
||||||
},
|
},
|
||||||
"template": {
|
"template": {
|
||||||
"name": _("Template Path"),
|
"name": _("Template Path"),
|
||||||
|
@ -168,7 +189,6 @@ class NotifyWorkflows(NotifyBase):
|
||||||
"ver": {
|
"ver": {
|
||||||
"name": _("API Version"),
|
"name": _("API Version"),
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "2016-06-01",
|
|
||||||
"map_to": "version",
|
"map_to": "version",
|
||||||
},
|
},
|
||||||
"api-version": {"alias_of": "ver"},
|
"api-version": {"alias_of": "ver"},
|
||||||
|
@ -188,6 +208,7 @@ class NotifyWorkflows(NotifyBase):
|
||||||
workflow,
|
workflow,
|
||||||
signature,
|
signature,
|
||||||
include_image=None,
|
include_image=None,
|
||||||
|
power_automate=None,
|
||||||
version=None,
|
version=None,
|
||||||
template=None,
|
template=None,
|
||||||
tokens=None,
|
tokens=None,
|
||||||
|
@ -220,6 +241,13 @@ class NotifyWorkflows(NotifyBase):
|
||||||
else self.template_args["image"]["default"]
|
else self.template_args["image"]["default"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Power Automate status
|
||||||
|
self.power_automate = bool(
|
||||||
|
power_automate
|
||||||
|
if power_automate is not None
|
||||||
|
else self.template_args["pa"]["default"]
|
||||||
|
)
|
||||||
|
|
||||||
# Wrap Text
|
# Wrap Text
|
||||||
self.wrap = bool(
|
self.wrap = bool(
|
||||||
wrap if wrap is not None else self.template_args["wrap"]["default"]
|
wrap if wrap is not None else self.template_args["wrap"]["default"]
|
||||||
|
@ -234,10 +262,16 @@ class NotifyWorkflows(NotifyBase):
|
||||||
self.template[0].max_file_size = self.max_workflows_template_size
|
self.template[0].max_file_size = self.max_workflows_template_size
|
||||||
|
|
||||||
# Prepare Version
|
# Prepare Version
|
||||||
|
# The default is taken from the template_args
|
||||||
|
# - If using power_automate, the API version required is different.
|
||||||
|
default_api_version = (
|
||||||
|
APIVersion.POWER_AUTOMATE
|
||||||
|
if self.power_automate else APIVersion.WORKFLOW)
|
||||||
|
|
||||||
self.api_version = (
|
self.api_version = (
|
||||||
version
|
version
|
||||||
if version is not None
|
if version is not None
|
||||||
else self.template_args["ver"]["default"]
|
else default_api_version
|
||||||
)
|
)
|
||||||
|
|
||||||
# Template functionality
|
# Template functionality
|
||||||
|
@ -379,11 +413,20 @@ class NotifyWorkflows(NotifyBase):
|
||||||
"sig": self.signature,
|
"sig": self.signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The URL changes depending on whether we're using power automate or
|
||||||
|
# not
|
||||||
|
path = (
|
||||||
|
"/powerautomate/automations/direct"
|
||||||
|
if self.power_automate
|
||||||
|
else ""
|
||||||
|
)
|
||||||
|
|
||||||
notify_url = (
|
notify_url = (
|
||||||
"https://{host}{port}/workflows/{workflow}/"
|
"https://{host}{port}{path}/workflows/{workflow}/"
|
||||||
"triggers/manual/paths/invoke".format(
|
"triggers/manual/paths/invoke".format(
|
||||||
host=self.host,
|
host=self.host,
|
||||||
port="" if not self.port else f":{self.port}",
|
port="" if not self.port else f":{self.port}",
|
||||||
|
path=path,
|
||||||
workflow=self.workflow,
|
workflow=self.workflow,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -471,6 +514,7 @@ class NotifyWorkflows(NotifyBase):
|
||||||
params = {
|
params = {
|
||||||
"image": "yes" if self.include_image else "no",
|
"image": "yes" if self.include_image else "no",
|
||||||
"wrap": "yes" if self.wrap else "no",
|
"wrap": "yes" if self.wrap else "no",
|
||||||
|
"pa": "yes" if self.power_automate else "no",
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.template:
|
if self.template:
|
||||||
|
@ -479,7 +523,12 @@ class NotifyWorkflows(NotifyBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Store our version if it differs from default
|
# Store our version if it differs from default
|
||||||
if self.api_version != self.template_args["ver"]["default"]:
|
if (self.api_version != APIVersion.WORKFLOW
|
||||||
|
and not self.power_automate) or (
|
||||||
|
self.api_version != APIVersion.POWER_AUTOMATE
|
||||||
|
and self.power_automate):
|
||||||
|
# But only do so if we're not using power automate with the
|
||||||
|
# default version for that.
|
||||||
params["ver"] = self.api_version
|
params["ver"] = self.api_version
|
||||||
|
|
||||||
# Extend our parameters
|
# Extend our parameters
|
||||||
|
@ -518,6 +567,17 @@ class NotifyWorkflows(NotifyBase):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Support Power Automate URL
|
||||||
|
results["power_automate"] = parse_bool(
|
||||||
|
results["qsd"].get(
|
||||||
|
"powerautomate",
|
||||||
|
results["qsd"].get(
|
||||||
|
"pa",
|
||||||
|
NotifyWorkflows.template_args["pa"]["default"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Wrap Text?
|
# Wrap Text?
|
||||||
results["wrap"] = parse_bool(
|
results["wrap"] = parse_bool(
|
||||||
results["qsd"].get(
|
results["qsd"].get(
|
||||||
|
@ -584,12 +644,17 @@ class NotifyWorkflows(NotifyBase):
|
||||||
"""
|
"""
|
||||||
Support parsing the webhook straight out of workflows
|
Support parsing the webhook straight out of workflows
|
||||||
https://HOST:443/workflows/WORKFLOWID/triggers/manual/paths/invoke
|
https://HOST:443/workflows/WORKFLOWID/triggers/manual/paths/invoke
|
||||||
|
or
|
||||||
|
https://HOST:443/powerautomate/automations/direct/workflows
|
||||||
|
/WORKFLOWID/triggers/manual/paths/invoke
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Match our workflows webhook URL and re-assemble
|
# Match our workflows webhook URL and re-assemble
|
||||||
result = re.match(
|
result = re.match(
|
||||||
r"^https?://(?P<host>[A-Z0-9_.-]+)"
|
r"^https?://(?P<host>[A-Z0-9_.-]+)"
|
||||||
r"(?P<port>:[1-9][0-9]{0,5})?"
|
r"(?P<port>:[1-9][0-9]{0,5})?"
|
||||||
|
# The new URL structure includes /powerautomate/automations/direct
|
||||||
|
r"(?P<power_automate>/powerautomate/automations/direct)?"
|
||||||
r"/workflows/"
|
r"/workflows/"
|
||||||
r"(?P<workflow>[A-Z0-9_-]+)"
|
r"(?P<workflow>[A-Z0-9_-]+)"
|
||||||
r"/triggers/manual/paths/invoke/?"
|
r"/triggers/manual/paths/invoke/?"
|
||||||
|
@ -599,9 +664,17 @@ class NotifyWorkflows(NotifyBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
|
# Determine if we're using power automate or not
|
||||||
|
power_automate = (
|
||||||
|
"&pa=yes"
|
||||||
|
if result.group("power_automate")
|
||||||
|
else ""
|
||||||
|
)
|
||||||
|
|
||||||
# Construct our URL
|
# Construct our URL
|
||||||
return NotifyWorkflows.parse_url(
|
return NotifyWorkflows.parse_url(
|
||||||
"{schema}://{host}{port}/{workflow}/{params}".format(
|
"{schema}://{host}{port}/{workflow}/{params}{pa}"
|
||||||
|
.format(
|
||||||
schema=NotifyWorkflows.secure_protocol[0],
|
schema=NotifyWorkflows.secure_protocol[0],
|
||||||
host=result.group("host"),
|
host=result.group("host"),
|
||||||
port=(
|
port=(
|
||||||
|
@ -611,6 +684,7 @@ class NotifyWorkflows(NotifyBase):
|
||||||
),
|
),
|
||||||
workflow=result.group("workflow"),
|
workflow=result.group("workflow"),
|
||||||
params=result.group("params"),
|
params=result.group("params"),
|
||||||
|
pa=power_automate,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -135,6 +135,27 @@ apprise_url_tests = (
|
||||||
"privacy_url": "workflow://host:443/w...b/s...e/",
|
"privacy_url": "workflow://host:443/w...b/s...e/",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"workflows://host:443/workflow1e/signature/?powerautomate=yes",
|
||||||
|
{
|
||||||
|
# support power_automate flag
|
||||||
|
"instance": NotifyWorkflows,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"workflows://host:443/workflow1e/signature/?pa=yes&ver=1995-01-01",
|
||||||
|
{
|
||||||
|
# support power_automate flag with ver flag
|
||||||
|
"instance": NotifyWorkflows,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"workflows://host:443/workflow1e/signature/?pa=yes",
|
||||||
|
{
|
||||||
|
# support power_automate flag
|
||||||
|
"instance": NotifyWorkflows,
|
||||||
|
},
|
||||||
|
),
|
||||||
# Support native URLs
|
# Support native URLs
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
|
@ -150,6 +171,20 @@ apprise_url_tests = (
|
||||||
"privacy_url": "workflow://server.azure.com:443/6...4/K...u/",
|
"privacy_url": "workflow://server.azure.com:443/6...4/K...u/",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
(
|
||||||
|
"https://server.azure.com:443/"
|
||||||
|
"powerautomate/automations/direct/"
|
||||||
|
"workflows/643e69f83c8944/"
|
||||||
|
"triggers/manual/paths/invoke?"
|
||||||
|
"api-version=2022-03-01-preview&sp=%2Ftriggers%2Fmanual%2Frun&"
|
||||||
|
"sv=1.0&sig=KODuebWbDGYFr0z0eu"
|
||||||
|
),
|
||||||
|
{
|
||||||
|
# Power-Automate alternative URL - All tokens provided - we're good
|
||||||
|
"instance": NotifyWorkflows,
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"workflow://host:443/workflow2/signature/",
|
"workflow://host:443/workflow2/signature/",
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue