Repository: zulip/zulip

Issue:
Support Dialogflow (API.AI)
Zulip is not listed as a supported integration in Dialogflow(previously API.AI). Figure out what to do to add Zulip to this list and do the same.

https://dialogflow.com/docs/integrations/


Discussion:
Hello @zulip/server-integrations members, this issue was labeled with the **area: integrations** label, so you may want to check it out!
@hackerkid do you have a sense how much work adding this would be / how much that service is used?  I'm trying to think about how to prioritize this.
@timabbott I am not aware of how much work is needed for this. I will do some research and get back to this. 
@zulipbot claim

Resolving patch:
diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py
--- a/zerver/lib/integrations.py
+++ b/zerver/lib/integrations.py
@@ -284,6 +284,7 @@ def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
     WebhookIntegration('circleci', ['continuous-integration'], display_name='CircleCI'),
     WebhookIntegration('codeship', ['continuous-integration', 'deployment']),
     WebhookIntegration('crashlytics', ['monitoring']),
+    WebhookIntegration('dialogflow', ['customer-support'], display_name='Dialogflow'),
     WebhookIntegration('delighted', ['customer-support', 'marketing'], display_name='Delighted'),
     WebhookIntegration(
         'deskdotcom',
diff --git a/zerver/webhooks/dialogflow/__init__.py b/zerver/webhooks/dialogflow/__init__.py
new file mode 100644
diff --git a/zerver/webhooks/dialogflow/view.py b/zerver/webhooks/dialogflow/view.py
new file mode 100644
--- /dev/null
+++ b/zerver/webhooks/dialogflow/view.py
@@ -0,0 +1,33 @@
+# Webhooks for external integrations.
+from typing import Text, Any, Dict
+from django.http import HttpRequest, HttpResponse
+from zerver.decorator import api_key_only_webhook_view
+from zerver.lib.actions import check_send_private_message
+from zerver.lib.request import REQ, has_request_variables
+from zerver.lib.response import json_success
+from zerver.models import UserProfile, get_user_profile_by_email
+
+@api_key_only_webhook_view("dialogflow")
+@has_request_variables
+def api_dialogflow_webhook(request: HttpRequest, user_profile: UserProfile,
+                           payload: Dict[str, Any]=REQ(argument_type='body'),
+                           email: str=REQ(default='foo')) -> HttpResponse:
+    status = payload["status"]["code"]
+
+    if status == 200:
+        result = payload["result"]["fulfillment"]["speech"]
+        if not result:
+            alternate_result = payload["alternateResult"]["fulfillment"]["speech"]
+            if not alternate_result:
+                body = u"DialogFlow couldn't process your query."
+            else:
+                body = alternate_result
+        else:
+            body = result
+    else:
+        error_status = payload["status"]["errorDetails"]
+        body = u"{} - {}".format(status, error_status)
+
+    profile = get_user_profile_by_email(email)
+    check_send_private_message(user_profile, request.client, profile, body)
+    return json_success()


Test patch:
diff --git a/zerver/webhooks/dialogflow/tests.py b/zerver/webhooks/dialogflow/tests.py
new file mode 100644
--- /dev/null
+++ b/zerver/webhooks/dialogflow/tests.py
@@ -0,0 +1,66 @@
+# -*- coding: utf -*-
+from typing import Text
+from zerver.lib.test_classes import WebhookTestCase
+
+class DialogflowHookTests(WebhookTestCase):
+    URL_TEMPLATE = u"/api/v1/external/dialogflow?api_key={api_key}&email=AARON@zulip.com"
+
+    def test_dialogflow_default(self) -> None:
+        self.url = self.build_webhook_url(
+            email="AARON@zulip.com",
+            username="aaron",
+            user_ip="127.0.0.1"
+        )
+        expected_message = u"Today the weather in Delhi: Sunny, And the tempreture is 65F"
+        self.send_and_test_private_message('default',
+                                           expected_message,
+                                           content_type="application/json")
+
+    def test_dialogflow_weather_app(self) -> None:
+        self.url = self.build_webhook_url(
+            email="AARON@zulip.com",
+            username="aaron",
+            user_ip="127.0.0.1"
+        )
+        expected_message = u"The weather sure looks great !"
+        self.send_and_test_private_message('weather_app',
+                                           expected_message,
+                                           content_type="application/json")
+
+    def test_dialogflow_alternate_result(self) -> None:
+        self.url = self.build_webhook_url(
+            email="AARON@zulip.com",
+            username="aaron",
+            user_ip="127.0.0.1"
+        )
+        expected_message = u"Weather in New Delhi is nice!"
+        self.send_and_test_private_message('alternate_result',
+                                           expected_message,
+                                           content_type="application/json")
+
+    def test_dialogflow_error_status(self) -> None:
+        self.url = self.build_webhook_url(
+            email="AARON@zulip.com",
+            username="aaron",
+            user_ip="127.0.0.1"
+        )
+        expected_message = u"403 - Access Denied"
+        self.send_and_test_private_message('error_status',
+                                           expected_message,
+                                           content_type="application/json")
+
+    def test_dialogflow_exception(self) -> None:
+        self.url = self.build_webhook_url(
+            email="AARON@zulip.com",
+            username="aaron",
+            user_ip="127.0.0.1"
+        )
+        expected_message = u"DialogFlow couldn't process your query."
+        self.send_and_test_private_message('exception',
+                                           expected_message,
+                                           content_type="application/json")
+
+    def get_body(self, fixture_name: Text) -> Text:
+        return self.fixture_data("dialogflow",
+                                 fixture_name,
+                                 file_type="json")