Renaming API.AI to Dialogflow (#10006)

* Rename API.AI to Dialogflow

* Rename API.AI to Dialogflow
This commit is contained in:
Fabian Affolter 2017-10-21 22:12:23 +02:00 committed by Paulus Schoutsen
parent bf26b75d27
commit 28b7a3da32
2 changed files with 53 additions and 49 deletions

View file

@ -1,8 +1,8 @@
""" """
Support for API.AI webhook. Support for Dialogflow webhook.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/apiai/ https://home-assistant.io/components/dialogflow/
""" """
import asyncio import asyncio
import logging import logging
@ -15,17 +15,16 @@ from homeassistant.components.http import HomeAssistantView
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
INTENTS_API_ENDPOINT = '/api/apiai'
CONF_INTENTS = 'intents' CONF_INTENTS = 'intents'
CONF_SPEECH = 'speech' CONF_SPEECH = 'speech'
CONF_ACTION = 'action' CONF_ACTION = 'action'
CONF_ASYNC_ACTION = 'async_action' CONF_ASYNC_ACTION = 'async_action'
DEFAULT_CONF_ASYNC_ACTION = False DEFAULT_CONF_ASYNC_ACTION = False
DOMAIN = 'apiai'
DEPENDENCIES = ['http'] DEPENDENCIES = ['http']
DOMAIN = 'dialogflow'
INTENTS_API_ENDPOINT = '/api/dialogflow'
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: {} DOMAIN: {}
@ -34,30 +33,30 @@ CONFIG_SCHEMA = vol.Schema({
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Activate API.AI component.""" """Set up Dialogflow component."""
hass.http.register_view(ApiaiIntentsView) hass.http.register_view(DialogflowIntentsView)
return True return True
class ApiaiIntentsView(HomeAssistantView): class DialogflowIntentsView(HomeAssistantView):
"""Handle API.AI requests.""" """Handle Dialogflow requests."""
url = INTENTS_API_ENDPOINT url = INTENTS_API_ENDPOINT
name = 'api:apiai' name = 'api:dialogflow'
@asyncio.coroutine @asyncio.coroutine
def post(self, request): def post(self, request):
"""Handle API.AI.""" """Handle Dialogflow."""
hass = request.app['hass'] hass = request.app['hass']
data = yield from request.json() data = yield from request.json()
_LOGGER.debug("Received api.ai request: %s", data) _LOGGER.debug("Received Dialogflow request: %s", data)
req = data.get('result') req = data.get('result')
if req is None: if req is None:
_LOGGER.error("Received invalid data from api.ai: %s", data) _LOGGER.error("Received invalid data from Dialogflow: %s", data)
return self.json_message( return self.json_message(
"Expected result value not received", HTTP_BAD_REQUEST) "Expected result value not received", HTTP_BAD_REQUEST)
@ -68,13 +67,13 @@ class ApiaiIntentsView(HomeAssistantView):
action = req.get('action') action = req.get('action')
parameters = req.get('parameters') parameters = req.get('parameters')
apiai_response = ApiaiResponse(parameters) dialogflow_response = DialogflowResponse(parameters)
if action == "": if action == "":
_LOGGER.warning("Received intent with empty action") _LOGGER.warning("Received intent with empty action")
apiai_response.add_speech( dialogflow_response.add_speech(
"You have not defined an action in your api.ai intent.") "You have not defined an action in your Dialogflow intent.")
return self.json(apiai_response) return self.json(dialogflow_response)
try: try:
intent_response = yield from intent.async_handle( intent_response = yield from intent.async_handle(
@ -83,31 +82,31 @@ class ApiaiIntentsView(HomeAssistantView):
in parameters.items()}) in parameters.items()})
except intent.UnknownIntent as err: except intent.UnknownIntent as err:
_LOGGER.warning('Received unknown intent %s', action) _LOGGER.warning("Received unknown intent %s", action)
apiai_response.add_speech( dialogflow_response.add_speech(
"This intent is not yet configured within Home Assistant.") "This intent is not yet configured within Home Assistant.")
return self.json(apiai_response) return self.json(dialogflow_response)
except intent.InvalidSlotInfo as err: except intent.InvalidSlotInfo as err:
_LOGGER.error('Received invalid slot data: %s', err) _LOGGER.error("Received invalid slot data: %s", err)
return self.json_message('Invalid slot data received', return self.json_message('Invalid slot data received',
HTTP_BAD_REQUEST) HTTP_BAD_REQUEST)
except intent.IntentError: except intent.IntentError:
_LOGGER.exception('Error handling request for %s', action) _LOGGER.exception("Error handling request for %s", action)
return self.json_message('Error handling intent', HTTP_BAD_REQUEST) return self.json_message('Error handling intent', HTTP_BAD_REQUEST)
if 'plain' in intent_response.speech: if 'plain' in intent_response.speech:
apiai_response.add_speech( dialogflow_response.add_speech(
intent_response.speech['plain']['speech']) intent_response.speech['plain']['speech'])
return self.json(apiai_response) return self.json(dialogflow_response)
class ApiaiResponse(object): class DialogflowResponse(object):
"""Help generating the response for API.AI.""" """Help generating the response for Dialogflow."""
def __init__(self, parameters): def __init__(self, parameters):
"""Initialize the response.""" """Initialize the Dialogflow response."""
self.speech = None self.speech = None
self.parameters = {} self.parameters = {}
# Parameter names replace '.' and '-' for '_' # Parameter names replace '.' and '-' for '_'
@ -125,7 +124,7 @@ class ApiaiResponse(object):
self.speech = text self.speech = text
def as_dict(self): def as_dict(self):
"""Return response in an API.AI valid dict.""" """Return response in a Dialogflow valid dictionary."""
return { return {
'speech': self.speech, 'speech': self.speech,
'displayText': self.speech, 'displayText': self.speech,

View file

@ -1,4 +1,4 @@
"""The tests for the APIAI component.""" """The tests for the Dialogflow component."""
# pylint: disable=protected-access # pylint: disable=protected-access
import json import json
import unittest import unittest
@ -7,14 +7,14 @@ import requests
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant import setup, const from homeassistant import setup, const
from homeassistant.components import apiai, http from homeassistant.components import dialogflow, http
from tests.common import get_test_instance_port, get_test_home_assistant from tests.common import get_test_instance_port, get_test_home_assistant
API_PASSWORD = "test1234" API_PASSWORD = 'test1234'
SERVER_PORT = get_test_instance_port() SERVER_PORT = get_test_instance_port()
BASE_API_URL = "http://127.0.0.1:{}".format(SERVER_PORT) BASE_API_URL = "http://127.0.0.1:{}".format(SERVER_PORT)
INTENTS_API_URL = "{}{}".format(BASE_API_URL, apiai.INTENTS_API_ENDPOINT) INTENTS_API_URL = "{}{}".format(BASE_API_URL, dialogflow.INTENTS_API_ENDPOINT)
HA_HEADERS = { HA_HEADERS = {
const.HTTP_HEADER_HA_AUTH: API_PASSWORD, const.HTTP_HEADER_HA_AUTH: API_PASSWORD,
@ -27,9 +27,9 @@ INTENT_NAME = "tests"
REQUEST_ID = "19ef7e78-fe15-4e94-99dd-0c0b1e8753c3" REQUEST_ID = "19ef7e78-fe15-4e94-99dd-0c0b1e8753c3"
REQUEST_TIMESTAMP = "2017-01-21T17:54:18.952Z" REQUEST_TIMESTAMP = "2017-01-21T17:54:18.952Z"
CONTEXT_NAME = "78a5db95-b7d6-4d50-9c9b-2fc73a5e34c3_id_dialog_context" CONTEXT_NAME = "78a5db95-b7d6-4d50-9c9b-2fc73a5e34c3_id_dialog_context"
MAX_RESPONSE_TIME = 5 # https://docs.api.ai/docs/webhook MAX_RESPONSE_TIME = 5 # https://dialogflow.com/docs/fulfillment
# An unknown action takes 8s to return. Request timeout should be bigger to # An unknown action takes 8 s to return. Request timeout should be bigger to
# allow the test to finish # allow the test to finish
REQUEST_TIMEOUT = 15 REQUEST_TIMEOUT = 15
@ -46,19 +46,23 @@ def setUpModule():
hass = get_test_home_assistant() hass = get_test_home_assistant()
setup.setup_component( setup.setup_component(
hass, http.DOMAIN, hass, http.DOMAIN, {
{http.DOMAIN: {http.CONF_API_PASSWORD: API_PASSWORD, http.DOMAIN: {
http.CONF_SERVER_PORT: SERVER_PORT}}) http.CONF_API_PASSWORD: API_PASSWORD,
http.CONF_SERVER_PORT: SERVER_PORT,
}
}
)
@callback @callback
def mock_service(call): def mock_service(call):
"""Mock action call.""" """Mock action call."""
calls.append(call) calls.append(call)
hass.services.register("test", "apiai", mock_service) hass.services.register('test', 'dialogflow', mock_service)
assert setup.setup_component(hass, apiai.DOMAIN, { assert setup.setup_component(hass, dialogflow.DOMAIN, {
"apiai": {}, "dialogflow": {},
}) })
assert setup.setup_component(hass, "intent_script", { assert setup.setup_component(hass, "intent_script", {
"intent_script": { "intent_script": {
@ -92,7 +96,7 @@ def setUpModule():
"text": "Service called", "text": "Service called",
}, },
"action": { "action": {
"service": "test.apiai", "service": "test.dialogflow",
"data_template": { "data_template": {
"hello": "{{ ZodiacSign }}" "hello": "{{ ZodiacSign }}"
}, },
@ -112,12 +116,13 @@ def tearDownModule():
def _intent_req(data): def _intent_req(data):
return requests.post(INTENTS_API_URL, data=json.dumps(data), return requests.post(
timeout=REQUEST_TIMEOUT, headers=HA_HEADERS) INTENTS_API_URL, data=json.dumps(data), timeout=REQUEST_TIMEOUT,
headers=HA_HEADERS)
class TestApiai(unittest.TestCase): class TestDialogflow(unittest.TestCase):
"""Test APIAI.""" """Test Dialogflow."""
def tearDown(self): def tearDown(self):
"""Stop everything that was started.""" """Stop everything that was started."""
@ -167,7 +172,7 @@ class TestApiai(unittest.TestCase):
self.assertEqual("", req.text) self.assertEqual("", req.text)
def test_intent_slot_filling(self): def test_intent_slot_filling(self):
"""Test when API.AI asks for slot-filling return none.""" """Test when Dialogflow asks for slot-filling return none."""
data = { data = {
"id": REQUEST_ID, "id": REQUEST_ID,
"timestamp": REQUEST_TIMESTAMP, "timestamp": REQUEST_TIMESTAMP,
@ -424,7 +429,7 @@ class TestApiai(unittest.TestCase):
self.assertEqual(call_count + 1, len(calls)) self.assertEqual(call_count + 1, len(calls))
call = calls[-1] call = calls[-1]
self.assertEqual("test", call.domain) self.assertEqual("test", call.domain)
self.assertEqual("apiai", call.service) self.assertEqual("dialogflow", call.service)
self.assertEqual(["switch.test"], call.data.get("entity_id")) self.assertEqual(["switch.test"], call.data.get("entity_id"))
self.assertEqual("virgo", call.data.get("hello")) self.assertEqual("virgo", call.data.get("hello"))
@ -471,7 +476,7 @@ class TestApiai(unittest.TestCase):
self.assertEqual(200, req.status_code) self.assertEqual(200, req.status_code)
text = req.json().get("speech") text = req.json().get("speech")
self.assertEqual( self.assertEqual(
"You have not defined an action in your api.ai intent.", text) "You have not defined an action in your Dialogflow intent.", text)
def test_intent_with_unknown_action(self): def test_intent_with_unknown_action(self):
"""Test a intent with an action not defined in the conf.""" """Test a intent with an action not defined in the conf."""