src/dfcx_scrapi/core/webhooks.py (141 lines of code) (raw):
"""Webhook Resource functions."""
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import Dict
from google.cloud.dialogflowcx_v3beta1 import services, types
from google.protobuf import field_mask_pb2
from dfcx_scrapi.core import scrapi_base
# logging config
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)-8s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
class Webhooks(scrapi_base.ScrapiBase):
"""Core Class for CX Webhook Resource functions."""
def __init__(
self,
creds_path: str = None,
creds_dict: Dict = None,
creds=None,
scope=False,
webhook_id: str = None,
agent_id: str = None,
):
super().__init__(
creds_path=creds_path,
creds_dict=creds_dict,
creds=creds,
scope=scope,
)
if webhook_id:
self.webhook_id = webhook_id
self.client_options = self._set_region(webhook_id)
if agent_id:
self.agent_id = agent_id
def get_webhooks_map(
self,
agent_id: str = None,
reverse=False):
"""Exports Agent Webhook Names and UUIDs into a user friendly dict.
Args:
agent_id: the formatted CX Agent ID to use
reverse: (Optional) Boolean flag to swap key:value -> value:key
Returns:
Dictionary containing Webhook UUIDs as keys and
webhook display names as values
"""
if not agent_id:
agent_id = self.agent_id
if reverse:
webhooks_dict = {
webhook.display_name: webhook.name
for webhook in self.list_webhooks(agent_id)
}
else:
webhooks_dict = {
webhook.name: webhook.display_name
for webhook in self.list_webhooks(agent_id)
}
return webhooks_dict
@scrapi_base.api_call_counter_decorator
def list_webhooks(self, agent_id: str = None):
"""List all Webhooks in the specified CX Agent.
Args:
agent_id: the formated CX Agent ID to use
Returns:
List of webhook objects
"""
if not agent_id:
agent_id = self.agent_id
request = types.webhook.ListWebhooksRequest()
request.parent = agent_id
client_options = self._set_region(agent_id)
client = services.webhooks.WebhooksClient(
credentials=self.creds, client_options=client_options
)
response = client.list_webhooks(request)
cx_webhooks = []
for page in response.pages:
for cx_webhook in page.webhooks:
cx_webhooks.append(cx_webhook)
return cx_webhooks
@scrapi_base.api_call_counter_decorator
def create_webhook(
self,
agent_id: str,
obj: types.Webhook = None,
**kwargs):
"""Create a single webhook resource on a given CX Agent.
Args:
agent_id: the formatted CX Agent ID to create the webhook on
obj: (Optional) the Webhook object of type
types.Webhook that you want to create the webhook from
Returns:
The successfully created webhook object
"""
if obj:
webhook = obj
webhook.name = ""
else:
webhook = types.webhook.Webhook()
# set optional kwargs to webhook attributes
for key, value in kwargs.items():
setattr(webhook, key, value)
client_options = self._set_region(agent_id)
client = services.webhooks.WebhooksClient(
client_options=client_options, credentials=self.creds)
response = client.create_webhook(parent=agent_id, webhook=webhook)
return response
@scrapi_base.api_call_counter_decorator
def get_webhook(self, webhook_id:str):
"""Retrieves the specified webhook.
Args:
webhook_id: The ID of the webhook. Format:
projects/<Project ID>/locations/<Location ID>/agents/
<Agent ID>/webhooks/<Webhook
Returns:
The Webhook object.
"""
request = types.webhook.GetWebhookRequest()
request.name = webhook_id
client_options = self._set_region(webhook_id)
client = services.webhooks.WebhooksClient(
client_options=client_options, credentials=self.creds)
response = client.get_webhook(request)
return response
def get_webhook_by_display_name(
self,
webhook_display_name:str,
agent_id:str = None):
"""Retrieves the specified webhook.
Args:
webhook_webhook_name: The display name of the webhook.
agent_id: Optional. The formatted CX Agent ID.
Returns:
The Webhook object of the specified webhook.
"""
if not agent_id:
agent_id = self.agent_id
webhook_map = self.get_webhooks_map(agent_id=agent_id,reverse=True)
if webhook_display_name in webhook_map:
webhook_obj = self.get_webhook(webhook_map[webhook_display_name])
else:
raise ValueError(
f"Webhook \"{webhook_display_name}\" does not exist in the \
specified Agent."
)
return webhook_obj
@scrapi_base.api_call_counter_decorator
def update_webhook(
self,
webhook_id:str,
webhook_obj:types.Webhook = None,
**kwargs):
"""Update the values of an existing webhook.
Args:
webhook_id: The ID of the webhook. Format:
projects/<Project ID>/locations/<Location ID>/agents/
<Agent ID>/webhooks/<Webhook ID>
webhook_obj: Optional Webhook object of types.Webhook
that can be provided when you are planning to replace the full
object vs. just partial updates.
Returns:
The Webhook object with specified changes.
"""
if not webhook_obj:
webhook_obj = types.Webhook()
webhook_obj.name = webhook_id
# set environment attributes from kwargs
for key, value in kwargs.items():
setattr(webhook_obj, key, value)
paths = kwargs.keys()
mask = field_mask_pb2.FieldMask(paths=paths)
client_options = self._set_region(webhook_id)
client = services.webhooks.WebhooksClient(
client_options=client_options, credentials=self.creds)
request = types.webhook.UpdateWebhookRequest()
request.webhook = webhook_obj
request.update_mask = mask
response = client.update_webhook(request)
return response
@scrapi_base.api_call_counter_decorator
def delete_webhook(
self, webhook_id: str = None,
obj: types.Webhook = None, force: bool = False
):
"""Deletes a single Webhookd resource object.
Args:
webhook_id: intent to delete
obj: (Optional) a CX Webhook object of types.Webhook
force: (Optional) This field has no effect for webhook not being
used. For webhooks that are used by pages/flows/transition route
groups:
- If ``force`` is set to false, an error will be returned
with message indicating the referenced resources.
- If ``force`` is set to true, Dialogflow will remove the
webhook, as well as any references to the webhook and tags in
fulfillments that point to this webhook will be removed.
"""
if not webhook_id:
webhook_id = self.webhook_id
if obj:
webhook_id = obj.name
client_options = self._set_region(webhook_id)
client = services.webhooks.WebhooksClient(
client_options=client_options, credentials=self.creds)
req = types.DeleteWebhookRequest(name=webhook_id, force=force)
client.delete_webhook(request=req)