snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

View File

View File

@@ -0,0 +1,27 @@
Get personal message notifications in Zulip for the results of your
Dialogflow queries!
1. {!create-channel.md!}
1. {!create-an-incoming-webhook.md!}
The API key for an incoming webhook bot cannot be used to read messages out
of Zulip. Thus, using an incoming webhook bot lowers the security risk of
exposing the bot's API key to a third-party service.
Construct the URL for the Dialogflow bot using the bot's API key and your
Zulip email. The webhook URL should look like:
`{{api_url}}?api_key=BOT'S_API_KEY&email=foo@example.com`
Modify the parameters of the URL above where `api_key` is the API key of your Zulip bot
and `email` is your Zulip email.
1. Go to the **Fulfillment** settings of your Dialogflow app and enable **Webhooks**.
Set **URL** to the URL constructed above.
Go to **Intents** and at the bottom, check the box **Use webhook**
under **Fulfillment**.
{!congrats.md!}
![](/static/images/integrations/dialogflow/001.png)

View File

@@ -0,0 +1,45 @@
{
"id": "69316a96-cce1-4322-9bdc-d94e8298f0d2",
"timestamp": "2018-01-12T12:22:31.283Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "what's the weather in New Delhi",
"action": "yahooWeatherForecast",
"actionIncomplete": false,
"parameters": {
"geo-city": "New Delhi"
},
"contexts": [],
"metadata": {
"intentId": "a61266c2-b6af-4dc8-a7b9-72dfb11b72d8",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"webhookResponseTime": 115,
"intentName": "weather-intent"
},
"fulfillment": {
"speech": "",
"source": "apiai-weather-webhook-sample",
"displayText": "",
"messages": [
{
"type": 0,
"speech": ""
}
]
},
"score": 0.7099999785423279
},
"alternateResult": {
"fulfillment": {
"speech": "Weather in New Delhi is nice!"
}
},
"status": {
"code": 200,
"errorType": "success",
"webhookTimedOut": false
},
"sessionId": "2507496e-8028-4be5-ac52-1624f752b188"
}

View File

@@ -0,0 +1,37 @@
{
"id": "1faaa328-dad8-4532-be7e-c4103dfdbf40",
"timestamp": "2018-01-12T12:09:15.699Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "how is the weather in Sunnyvale",
"action": "",
"actionIncomplete": false,
"parameters": {
"geo-city": "Sunnyvale"
},
"contexts": [],
"metadata": {
"intentId": "a61266c2-b6af-4dc8-a7b9-72dfb11b72d8",
"webhookUsed": "false",
"webhookForSlotFillingUsed": "false",
"intentName": "weather-intent"
},
"fulfillment": {
"speech": "The weather sure looks great !",
"messages": [
{
"type": 0,
"speech": "The weather sure looks great !"
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success",
"webhookTimedOut": false
},
"sessionId": "2507496e-8028-4be5-ac52-1624f752b188"
}

View File

@@ -0,0 +1,14 @@
{
"id": "69316a96-cce1-4322-9bdc-d94e8298f0d2",
"timestamp": "2018-01-12T12:22:31.283Z",
"lang": "en",
"result": {
"resolvedQuery": "what's the weather in New Delhi"
},
"status": {
"code": 403,
"errorType": "fail",
"errorDetails": "Access Denied"
},
"sessionId": "2507496e-8028-4be5-ac52-1624f752b188"
}

View File

@@ -0,0 +1,45 @@
{
"id": "69316a96-cce1-4322-9bdc-d94e8298f0d2",
"timestamp": "2018-01-12T12:22:31.283Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "what's the weather in New Delhi",
"action": "yahooWeatherForecast",
"actionIncomplete": false,
"parameters": {
"geo-city": "New Delhi"
},
"contexts": [],
"metadata": {
"intentId": "a61266c2-b6af-4dc8-a7b9-72dfb11b72d8",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"webhookResponseTime": 115,
"intentName": "weather-intent"
},
"fulfillment": {
"speech": "",
"source": "apiai-weather-webhook-sample",
"displayText": "",
"messages": [
{
"type": 0,
"speech": ""
}
]
},
"score": 0.7099999785423279
},
"alternateResult": {
"fulfillment": {
"speech": ""
}
},
"status": {
"code": 200,
"errorType": "success",
"webhookTimedOut": false
},
"sessionId": "2507496e-8028-4be5-ac52-1624f752b188"
}

View File

@@ -0,0 +1,40 @@
{
"id": "69316a96-cce1-4322-9bdc-d94e8298f0d2",
"timestamp": "2018-01-12T12:22:31.283Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "what's the weather in New Delhi",
"action": "yahooWeatherForecast",
"actionIncomplete": false,
"parameters": {
"geo-city": "New Delhi"
},
"contexts": [],
"metadata": {
"intentId": "a61266c2-b6af-4dc8-a7b9-72dfb11b72d8",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"webhookResponseTime": 115,
"intentName": "weather-intent"
},
"fulfillment": {
"speech": "Today the weather in Delhi: Sunny, And the temperature is 65 F",
"source": "apiai-weather-webhook-sample",
"displayText": "Today the weather in Delhi: Sunny, And the temperature is 65 F",
"messages": [
{
"type": 0,
"speech": "Today the weather in Delhi: Sunny, And the temperature is 65 F"
}
]
},
"score": 0.7099999785423279
},
"status": {
"code": 200,
"errorType": "success",
"webhookTimedOut": false
},
"sessionId": "2507496e-8028-4be5-ac52-1624f752b188"
}

View File

@@ -0,0 +1,45 @@
from zerver.lib.test_classes import WebhookTestCase
class DialogflowHookTests(WebhookTestCase):
URL_TEMPLATE = "/api/v1/external/dialogflow?api_key={api_key}&email=AARON@zulip.com"
def test_dialogflow_default(self) -> None:
email = self.example_user("aaron").email
self.url = self.build_webhook_url(
email=email,
username="aaron",
user_ip="127.0.0.1",
)
expected_message = "The weather sure looks great !"
self.send_and_test_private_message("default", expected_message)
def test_dialogflow_alternate_result(self) -> None:
email = self.example_user("aaron").email
self.url = self.build_webhook_url(
email=email,
username="aaron",
user_ip="127.0.0.1",
)
expected_message = "Weather in New Delhi is nice!"
self.send_and_test_private_message("alternate_result", expected_message)
def test_dialogflow_error_status(self) -> None:
email = self.example_user("aaron").email
self.url = self.build_webhook_url(
email=email,
username="aaron",
user_ip="127.0.0.1",
)
expected_message = "403 - Access Denied"
self.send_and_test_private_message("error_status", expected_message)
def test_dialogflow_exception(self) -> None:
email = self.example_user("aaron").email
self.url = self.build_webhook_url(
email=email,
username="aaron",
user_ip="127.0.0.1",
)
expected_message = "Dialogflow couldn't process your query."
self.send_and_test_private_message("exception", expected_message)

View File

@@ -0,0 +1,45 @@
# Webhooks for external integrations.
from django.http import HttpRequest, HttpResponse
from zerver.actions.message_send import check_send_private_message
from zerver.decorator import webhook_view
from zerver.lib.request import RequestNotes
from zerver.lib.response import json_success
from zerver.lib.typed_endpoint import JsonBodyPayload, typed_endpoint
from zerver.lib.validator import WildValue, check_int, check_string
from zerver.models import UserProfile
from zerver.models.users import get_user
@webhook_view("Dialogflow")
@typed_endpoint
def api_dialogflow_webhook(
request: HttpRequest,
user_profile: UserProfile,
*,
payload: JsonBodyPayload[WildValue],
email: str,
) -> HttpResponse:
status = payload["status"]["code"].tame(check_int)
if status == 200:
result = payload["result"]["fulfillment"]["speech"].tame(check_string)
if not result:
alternate_result = payload["alternateResult"]["fulfillment"]["speech"].tame(
check_string
)
if not alternate_result:
body = "Dialogflow couldn't process your query."
else:
body = alternate_result
else:
body = result
else:
error_status = payload["status"]["errorDetails"].tame(check_string)
body = f"{status} - {error_status}"
receiving_user = get_user(email, user_profile.realm)
client = RequestNotes.get_notes(request).client
assert client is not None
check_send_private_message(user_profile, client, receiving_user, body)
return json_success(request)