dialogflow-cx/delegators/page_delegator.py (98 lines of code) (raw):
# Copyright 2022 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
#
# http://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.
"""Dialogflow Pages API interactions."""
import dialogflow_sample as ds
import google.api_core.exceptions
import google.cloud.dialogflowcx as cx
from .client_delegator import ClientDelegator
class PageDelegator(ClientDelegator):
"""Class for organizing interactions with the Dialogflow Pages API."""
_CLIENT_CLASS = cx.PagesClient
def __init__(self, controller: ds.DialogflowSample, **kwargs) -> None:
self._page = None
self._entry_fulfillment = None
super().__init__(controller, **kwargs)
@property
def page(self):
"""Page set in Dialogflow."""
if not self._page:
raise RuntimeError("Page not yet created")
return self._page
@property
def parent(self):
"""Accesses the parent of page; equivalent to the start_flow."""
return self.controller.start_flow
@property
def entry_fulfillment(self):
"""Accesses the entry fullfillment set for this page."""
return self._entry_fulfillment
def setup(self):
"""Initializes the page delegator."""
page = cx.Page(
display_name=self.display_name,
entry_fulfillment=self.entry_fulfillment,
)
try:
self._page = self.client.create_page(
parent=self.controller.start_flow,
page=page,
)
except google.api_core.exceptions.AlreadyExists:
request = cx.ListPagesRequest(parent=self.parent)
for curr_page in self.client.list_pages(request=request):
if curr_page.display_name == self.display_name:
request = cx.GetPageRequest(
name=curr_page.name,
)
self._page = self.client.get_page(request=request)
return
def tear_down(self, force=True):
"""Destroys the Dialogflow page."""
request = cx.DeletePageRequest(name=self.page.name, force=force)
try:
self.client.delete_page(request=request)
self._page = None
except google.api_core.exceptions.NotFound:
pass
def append_transition_route(
self, target_page, intent=None, condition=None, trigger_fulfillment=None
):
"""Appends a transition route to the page."""
transition_route = cx.TransitionRoute(
condition=condition,
trigger_fulfillment=trigger_fulfillment,
intent=intent,
target_page=target_page,
)
self.page.transition_routes.append(transition_route)
self.client.update_page(page=self.page)
def add_parameter(self, display_name, entity_type, fill_behavior, **kwargs):
"""Adds a form parameter to the page."""
parameter = cx.Form.Parameter(
display_name=display_name,
entity_type=entity_type,
fill_behavior=fill_behavior,
**kwargs
)
for page_idx, curr_parameter in enumerate(self.page.form.parameters):
if curr_parameter.display_name == display_name:
self.page.form.parameters[page_idx] = parameter
return
self.page.form.parameters.append(parameter)
class StartPageDelegator(PageDelegator):
"""Special delegator necessary when the start page is a transition target."""
@property
def page(self):
"""Mock out the page attribute with the expected name for this special case."""
return cx.Page(name=self.controller.start_flow_delegator.start_page_name)
class FulfillmentPageDelegator(PageDelegator):
"""Class for organizing interactions with the Dialogflow Pages API with fulfillments."""
def __init__(self, controller: ds.DialogflowSample, **kwargs) -> None:
self._entry_fulfillment_text = kwargs.pop("entry_fulfillment_text")
self._webhook_delegator = kwargs.pop("webhook_delegator", None)
self._tag = kwargs.pop("tag", None)
super().__init__(controller, **kwargs)
def setup(self):
"""Initializes the fulfillment page delegator."""
webhook_name = (
self._webhook_delegator.webhook.name if self._webhook_delegator else None
)
self._entry_fulfillment = cx.Fulfillment(
{
"messages": [
cx.ResponseMessage(
text=cx.ResponseMessage.Text(
text=[self._entry_fulfillment_text]
)
)
],
"webhook": webhook_name,
"tag": self._tag,
}
)
super().setup()