webhooks: Migrate most integrations to use check_send_webhook_message.

This commit migrates all of our webhooks to use
check_send_webhook_message, except the following:

beeminder: Rishi wanted to wait on this one.
teamcity: This one is slightly more work.

yo: This one is PM-only. I am still trying to decide whether we
    should have a force_private argument or something in
    check_send_webhook_message.

facebook: No point in migrating this, will be removed as part of
          #8433.

slack: Slightly more work too with the `channel_to_topics` feature.
       Warrants a longer discussion.
This commit is contained in:
Eeshan Garg
2018-03-16 19:23:50 -02:30
parent a1e3c91213
commit a4979410f9
57 changed files with 227 additions and 293 deletions

View File

@@ -8,10 +8,10 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import authenticated_rest_api_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.notifications import convert_html_to_markdown
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile, get_client
class TicketDict(Dict[str, Any]):
@@ -106,8 +106,7 @@ def format_freshdesk_ticket_creation_message(ticket: TicketDict) -> str:
@authenticated_rest_api_view(is_webhook=True)
@has_request_variables
def api_freshdesk_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='freshdesk')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
ticket_data = payload["freshdesk_webhook"]
required_keys = [
@@ -137,6 +136,5 @@ def api_freshdesk_webhook(request: HttpRequest, user_profile: UserProfile,
# Not an event we know handle; do nothing.
return json_success()
check_send_stream_message(user_profile, get_client("ZulipFreshdeskWebhook"),
stream, subject, content)
check_send_webhook_message(request, user_profile, subject, content)
return json_success()

View File

@@ -5,7 +5,7 @@ from zerver.lib.test_classes import WebhookTestCase
class FrontHookTests(WebhookTestCase):
STREAM_NAME = 'front'
URL_TEMPLATE = "/api/v1/external/front?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/front?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'front'
def _test_no_message_data(self, fixture_name: Text) -> None:

View File

@@ -4,9 +4,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
def get_message_data(payload: Dict[Text, Any]) -> Optional[Tuple[Text, Text, Text, Text]]:
@@ -57,9 +57,7 @@ def get_tag(payload: Dict[Text, Any]) -> Optional[Text]:
@api_key_only_webhook_view('Front')
@has_request_variables
def api_front_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[Text, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='front'),
topic: Optional[Text]=REQ(default='cnv_id')) -> HttpResponse:
payload: Dict[Text, Any]=REQ(argument_type='body')) -> HttpResponse:
try:
event_type = payload['type']
conversation_id = payload['conversation']['id']
@@ -183,6 +181,6 @@ def api_front_webhook(request: HttpRequest, user_profile: UserProfile,
else:
return json_error(_("Unknown webhook request"))
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -3,9 +3,9 @@ from typing import Any, Dict, Optional, Text
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
GCI_MESSAGE_TEMPLATE = u'**{actor}** {action} the task [{task_name}]({task_url}).'
@@ -102,7 +102,7 @@ def get_outoftime_event_body(payload: Dict[Text, Any]) -> Text:
@api_key_only_webhook_view("Google-Code-In")
@has_request_variables
def api_gci_webhook(request: HttpRequest, user_profile: UserProfile, stream: Text=REQ(default='gci'),
def api_gci_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[Text, Any]=REQ(argument_type='body')) -> HttpResponse:
event = get_event(payload)
if event is not None:
@@ -110,8 +110,7 @@ def api_gci_webhook(request: HttpRequest, user_profile: UserProfile, stream: Tex
subject = GCI_SUBJECT_TEMPLATE.format(
student_name=payload['task_claimed_by']
)
check_send_stream_message(user_profile, request.client,
stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
return json_success()

View File

@@ -208,70 +208,70 @@ class GithubWebhookTest(WebhookTestCase):
HTTP_X_GITHUB_EVENT='pull_request'
)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_pull_request_labeled_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
payload = self.get_body('labeled_pull_request')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='pull_request', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_pull_request_unlabeled_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
payload = self.get_body('unlabeled_pull_request')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='pull_request', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_pull_request_request_review_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
payload = self.get_body('request_review_pull_request')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='pull_request', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_pull_request_request_review_remove_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
payload = self.get_body('request_review_removed_pull_request')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='pull_request', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_push_1_commit_filtered_by_branches_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
self.url = self.build_webhook_url(branches='master,development')
payload = self.get_body('push_1_commit')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='push', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_push_50_commits_filtered_by_branches_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
self.url = self.build_webhook_url(branches='master,development')
payload = self.get_body('push_50_commits')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='push', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_push_multiple_comitters_filtered_by_branches_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
self.url = self.build_webhook_url(branches='master,development')
payload = self.get_body('push_multiple_committers')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='push', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.github_webhook.view.check_send_stream_message')
@patch('zerver.webhooks.github_webhook.view.check_send_webhook_message')
def test_push_multiple_comitters_with_others_filtered_by_branches_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
self.url = self.build_webhook_url(branches='master,development')
payload = self.get_body('push_multiple_committers_with_others')
result = self.client_post(self.url, payload, HTTP_X_GITHUB_EVENT='push', content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)

View File

@@ -6,9 +6,9 @@ from typing import Any, Callable, Dict, Optional, Text
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, JsonableError, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.webhooks.git import CONTENT_MESSAGE_TEMPLATE, \
SUBJECT_WITH_BRANCH_TEMPLATE, SUBJECT_WITH_PR_OR_ISSUE_INFO_TEMPLATE, \
get_commits_comment_action_message, get_issue_event_message, \
@@ -368,13 +368,14 @@ EVENT_FUNCTION_MAPPER = {
@api_key_only_webhook_view('GitHub')
@has_request_variables
def api_github_webhook(
request: HttpRequest, user_profile: UserProfile, payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='github'), branches: Text=REQ(default=None)) -> HttpResponse:
request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
branches: Text=REQ(default=None)) -> HttpResponse:
event = get_event(request, payload, branches)
if event is not None:
subject = get_subject_based_on_type(payload, event)
body = get_body_function_based_on_type(event)(payload)
check_send_stream_message(user_profile, request.client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
return json_success()
def get_event(request: HttpRequest, payload: Dict[str, Any], branches: Text) -> Optional[str]:

View File

@@ -8,7 +8,7 @@ from zerver.lib.webhooks.git import COMMITS_LIMIT
class GogsHookTests(WebhookTestCase):
STREAM_NAME = 'commits'
URL_TEMPLATE = "/api/v1/external/gogs?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/gogs?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'gogs'
def test_push(self) -> None:
@@ -81,31 +81,31 @@ from `feature` to `master`"""
from `feature` to `master`"""
self.send_and_test_stream_message('pull_request_merged', expected_subject, expected_message, HTTP_X_GOGS_EVENT='pull_request')
@patch('zerver.webhooks.gogs.view.check_send_stream_message')
def test_push_filtered_by_branches_ignore(self, check_send_stream_message_mock: MagicMock) -> None:
@patch('zerver.webhooks.gogs.view.check_send_webhook_message')
def test_push_filtered_by_branches_ignore(self, check_send_webhook_message_mock: MagicMock) -> None:
self.url = self.build_webhook_url(branches='changes,development')
payload = self.get_body('push')
result = self.client_post(self.url, payload, HTTP_X_GOGS_EVENT='push',
content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.gogs.view.check_send_stream_message')
@patch('zerver.webhooks.gogs.view.check_send_webhook_message')
def test_push_commits_more_than_limits_filtered_by_branches_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
self.url = self.build_webhook_url(branches='changes,development')
payload = self.get_body('push_commits_more_than_limits')
result = self.client_post(self.url, payload, HTTP_X_GOGS_EVENT='push',
content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.gogs.view.check_send_stream_message')
@patch('zerver.webhooks.gogs.view.check_send_webhook_message')
def test_push_multiple_committers_filtered_by_branches_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
self.url = self.build_webhook_url(branches='changes,development')
payload = self.get_body('push_commits_multiple_committers')
result = self.client_post(self.url, payload, HTTP_X_GOGS_EVENT='push',
content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)

View File

@@ -6,9 +6,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.webhooks.git import SUBJECT_WITH_BRANCH_TEMPLATE, \
SUBJECT_WITH_PR_OR_ISSUE_INFO_TEMPLATE, get_create_branch_event_message, \
get_pull_request_event_message, get_push_commits_event_message
@@ -63,7 +63,6 @@ def format_pull_request_event(payload: Dict[str, Any]) -> Text:
@has_request_variables
def api_gogs_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='commits'),
branches: Optional[Text]=REQ(default=None)) -> HttpResponse:
repo = payload['repository']['name']
@@ -94,5 +93,5 @@ def api_gogs_webhook(request: HttpRequest, user_profile: UserProfile,
else:
return json_error(_('Invalid event "{}" in request headers').format(event))
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -4,9 +4,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
BODY_TEMPLATE = '[{website_name}]({website_url}) has {user_num} visitors online.'
@@ -14,18 +14,13 @@ BODY_TEMPLATE = '[{website_name}]({website_url}) has {user_num} visitors online.
@api_key_only_webhook_view('GoSquared')
@has_request_variables
def api_gosquared_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Dict[str, Any]]=REQ(argument_type='body'),
stream: Text=REQ(default='gosquared'),
topic: Text=REQ(default=None)) -> HttpResponse:
payload: Dict[str, Dict[str, Any]]=REQ(argument_type='body')) -> HttpResponse:
domain_name = payload['siteDetails']['domain']
user_num = payload['concurrents']
user_acc = payload['siteDetails']['acct']
acc_url = 'https://www.gosquared.com/now/' + user_acc
body = BODY_TEMPLATE.format(website_name=domain_name, website_url=acc_url, user_num=user_num)
# allows for customisable topics
if topic is None:
topic = 'GoSquared - {website_name}'.format(website_name=domain_name)
check_send_stream_message(user_profile, request.client, stream,
topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -5,9 +5,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
MESSAGE_TEMPLATE = "Applying for role:\n{}\n**Emails:**\n{}\n\n>**Attachments:**\n{}"
@@ -34,9 +34,7 @@ def message_creator(action: str, application: Dict[str, Any]) -> str:
@api_key_only_webhook_view('Greenhouse')
@has_request_variables
def api_greenhouse_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: str=REQ(default='greenhouse'),
topic: str=REQ(default=None)) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
if payload['action'] == 'update_candidate':
candidate = payload['payload']['candidate']
else:
@@ -50,8 +48,7 @@ def api_greenhouse_webhook(request: HttpRequest, user_profile: UserProfile,
message_creator(payload['action'],
payload['payload']['application']))
if topic is None:
topic = "{} - {}".format(action, str(candidate['id']))
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -7,9 +7,9 @@ from django.utils.translation import ugettext as _
import logging
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
def ticket_started_body(payload: Dict[str, Any]) -> Text:
@@ -78,9 +78,7 @@ def note_added_body(payload: Dict[str, Any]) -> Text:
@api_key_only_webhook_view('Groove')
@has_request_variables
def api_groove_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='groove'),
topic: Optional[Text]=REQ(default='notifications')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
try:
# The event identifier is stored in the X_GROOVE_EVENT header.
event = request.META['X_GROOVE_EVENT']
@@ -96,7 +94,8 @@ def api_groove_webhook(request: HttpRequest, user_profile: UserProfile,
logging.error('Required key not found : ' + e.args[0])
return json_error(_('Missing required data'))
if body is not None:
check_send_stream_message(user_profile, request.client, stream, topic, body)
topic = 'notifications'
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -4,9 +4,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
def format_body(signatories: List[Dict[str, Any]], model_payload: Dict[str, Any]) -> str:
@@ -41,11 +41,9 @@ def ready_payload(signatories: List[Dict[str, Any]],
@api_key_only_webhook_view('HelloSign')
@has_request_variables
def api_hellosign_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Dict[str, Any]]=REQ(argument_type='body'),
stream: str=REQ(default='hellosign'),
topic: str=REQ(default=None)) -> HttpResponse:
payload: Dict[str, Dict[str, Any]]=REQ(argument_type='body')) -> HttpResponse:
model_payload = ready_payload(payload['signature_request']['signatures'], payload)
body = format_body(payload['signature_request']['signatures'], model_payload)
topic = topic or model_payload['contract_title']
check_send_stream_message(user_profile, request.client, stream, topic, body)
topic = model_payload['contract_title']
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -4,19 +4,18 @@ from typing import Text
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view("Heroku")
@has_request_variables
def api_heroku_webhook(request: HttpRequest, user_profile: UserProfile,
stream: Text=REQ(default="heroku"), head: Text=REQ(),
app: Text=REQ(), user: Text=REQ(),
head: Text=REQ(), app: Text=REQ(), user: Text=REQ(),
url: Text=REQ(), git_log: Text=REQ()) -> HttpResponse:
template = "{} deployed version {} of [{}]({})\n> {}"
content = template.format(user, head, app, url, git_log)
check_send_stream_message(user_profile, request.client, stream, app, content)
check_send_webhook_message(request, user_profile, app, content)
return json_success()

View File

@@ -4,7 +4,7 @@ from zerver.lib.test_classes import WebhookTestCase
class HomeAssistantHookTests(WebhookTestCase):
STREAM_NAME = 'homeassistant'
URL_TEMPLATE = "/api/v1/external/homeassistant?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/homeassistant?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'homeassistant'
def test_simplereq(self) -> None:

View File

@@ -4,17 +4,16 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.validator import check_dict, check_string
from zerver.models import UserProfile
@api_key_only_webhook_view('HomeAssistant')
@has_request_variables
def api_homeassistant_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, str]=REQ(argument_type='body'),
stream: Text=REQ(default="homeassistant")) -> HttpResponse:
payload: Dict[str, str]=REQ(argument_type='body')) -> HttpResponse:
# construct the body of the message
body = payload["message"]
@@ -26,7 +25,7 @@ def api_homeassistant_webhook(request: HttpRequest, user_profile: UserProfile,
topic = "homeassistant"
# send the message
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
# return json result
return json_success()

View File

@@ -4,21 +4,20 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view('IFTTT')
@has_request_variables
def api_iftt_app_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: str=REQ(default='ifttt')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
subject = payload.get('subject')
content = payload.get('content')
if subject is None:
return json_error(_("Subject can't be empty"))
if content is None:
return json_error(_("Content can't be empty"))
check_send_stream_message(user_profile, request.client, stream, subject, content)
check_send_webhook_message(request, user_profile, subject, content)
return json_success()

View File

@@ -6,7 +6,7 @@ from zerver.lib.test_classes import WebhookTestCase
class InspingHookTests(WebhookTestCase):
STREAM_NAME = 'test'
URL_TEMPLATE = "/api/v1/external/insping?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/insping?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'insping'
def test_website_state_available_message(self) -> None:

View File

@@ -1,6 +1,6 @@
from django.utils.translation import ugettext as _
from zerver.lib.actions import check_send_stream_message
from zerver.lib.response import json_success, json_error
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.decorator import REQ, has_request_variables, \
api_key_only_webhook_view
from zerver.lib.validator import check_dict, check_string
@@ -17,9 +17,7 @@ import time
@has_request_variables
def api_insping_webhook(
request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Dict[str, Any]]=REQ(argument_type='body'),
stream: Text=REQ(default='test'),
topic: Text=REQ(default='insping')
payload: Dict[str, Dict[str, Any]]=REQ(argument_type='body')
) -> HttpResponse:
data = payload['webhook_event_data']
@@ -37,8 +35,8 @@ URL: {}
Response time: {} ms
Timestamp: {}
""".format(state_name, url_tested, response_time, time_formatted)
topic = 'insping'
check_send_stream_message(user_profile, request.client,
stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -4,16 +4,15 @@ from typing import Any, Dict, Text
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view('Intercom')
@has_request_variables
def api_intercom_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any] = REQ(argument_type='body'),
stream: Text = REQ(default='intercom')) -> HttpResponse:
payload: Dict[str, Any] = REQ(argument_type='body')) -> HttpResponse:
topic = payload['topic']
topic = topic.replace('.', ' ')
@@ -26,5 +25,5 @@ def api_intercom_webhook(request: HttpRequest, user_profile: UserProfile,
' - User Email: {}\n' \
' - User Phone: {}\n'.format(data['name'], data['email'], data['phone'])
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -5,7 +5,7 @@ from zerver.lib.test_classes import WebhookTestCase
class JiraHookTests(WebhookTestCase):
STREAM_NAME = 'jira'
URL_TEMPLATE = u"/api/v1/external/jira?api_key={api_key}"
URL_TEMPLATE = u"/api/v1/external/jira?api_key={api_key}&stream={stream}"
def test_unknown(self) -> None:
url = self.build_webhook_url()

View File

@@ -10,9 +10,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import Realm, UserProfile, get_user
IGNORED_EVENTS = [
@@ -223,8 +223,7 @@ def handle_deleted_issue_event(payload: Dict[str, Any]) -> Text:
@api_key_only_webhook_view("JIRA")
@has_request_variables
def api_jira_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='jira')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
event = get_event_type(payload)
if event == 'jira:issue_created':
@@ -249,5 +248,5 @@ def api_jira_webhook(request: HttpRequest, user_profile: UserProfile,
logging.warning("Got JIRA event type we don't support: {}".format(event))
return json_success()
check_send_stream_message(user_profile, request.client, stream, subject, content)
check_send_webhook_message(request, user_profile, subject, content)
return json_success()

View File

@@ -7,9 +7,9 @@ from django.utils.timezone import utc as timezone_utc
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
ALERT_CLEAR = 'clear'
@@ -144,8 +144,7 @@ class LibratoWebhookHandler(LibratoWebhookParser):
@api_key_only_webhook_view('Librato')
@has_request_variables
def api_librato_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(converter=ujson.loads, default={}),
stream: Text=REQ(default='librato'), topic: Text=REQ(default=None)) -> HttpResponse:
payload: Dict[str, Any]=REQ(converter=ujson.loads, default={})) -> HttpResponse:
try:
attachments = ujson.loads(request.body).get('attachments', [])
except ValueError:
@@ -155,8 +154,6 @@ def api_librato_webhook(request: HttpRequest, user_profile: UserProfile,
return json_error(_("Malformed JSON input"))
message_handler = LibratoWebhookHandler(payload, attachments)
if not topic:
topic = message_handler.generate_topic()
try:
@@ -164,5 +161,5 @@ def api_librato_webhook(request: HttpRequest, user_profile: UserProfile,
except Exception as e:
return json_error(_(str(e)))
check_send_stream_message(user_profile, request.client, stream, topic, content)
check_send_webhook_message(request, user_profile, topic, content)
return json_success()

View File

@@ -5,25 +5,26 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.validator import check_dict, check_string
from zerver.models import UserProfile
@api_key_only_webhook_view('Mention')
@has_request_variables
def api_mention_webhook(request: HttpRequest, user_profile: UserProfile,
def api_mention_webhook(
request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Iterable[Dict[str, Any]]] = REQ(argument_type='body'),
stream: Text = REQ(default='mention'),
topic: Text = REQ(default='news')) -> HttpResponse:
) -> HttpResponse:
title = payload["title"]
source_url = payload["url"]
description = payload["description"]
# construct the body of the message
body = '**[%s](%s)**:\n%s' % (title, source_url, description)
topic = 'news'
# send the message
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -5,16 +5,15 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.validator import check_dict
from zerver.models import Stream, UserProfile
@api_key_only_webhook_view("NewRelic")
@has_request_variables
def api_newrelic_webhook(request: HttpRequest, user_profile: UserProfile,
stream: Text=REQ(default='newrelic'),
alert: Optional[Dict[str, Any]]=REQ(validator=check_dict([]), default=None),
deployment: Optional[Dict[str, Any]]=REQ(validator=check_dict([]), default=None)
)-> HttpResponse:
@@ -33,5 +32,5 @@ def api_newrelic_webhook(request: HttpRequest, user_profile: UserProfile,
else:
return json_error(_("Unknown webhook request"))
check_send_stream_message(user_profile, request.client, stream, subject, content)
check_send_webhook_message(request, user_profile, subject, content)
return json_success()

View File

@@ -7,7 +7,7 @@ from zerver.webhooks.opbeat.view import get_value
class OpbeatHookTests(WebhookTestCase):
STREAM_NAME = 'opbeat'
URL_TEMPLATE = u"/api/v1/external/opbeat?api_key={api_key}"
URL_TEMPLATE = u"/api/v1/external/opbeat?api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'opbeat'
def test_comment(self) -> None:

View File

@@ -4,9 +4,9 @@ from typing import Text, Dict, Any, List, Tuple, Union
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile, get_client
subject_types = {
@@ -99,12 +99,8 @@ def format_object(
@api_key_only_webhook_view("Opbeat")
@has_request_variables
def api_opbeat_webhook(
request: HttpRequest,
user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: str=REQ(default="opbeat")
) -> HttpResponse:
def api_opbeat_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
"""
This uses the subject name from opbeat to make the subject,
and the summary from Opbeat as the message body, with
@@ -115,6 +111,5 @@ def api_opbeat_webhook(
message = format_object(payload, 'base', '')
check_send_stream_message(user_profile, get_client('ZulipOpbeatWebhook'),
stream, message_subject, message)
check_send_webhook_message(request, user_profile, message_subject, message)
return json_success()

View File

@@ -5,7 +5,7 @@ from zerver.lib.test_classes import WebhookTestCase
class OpsGenieHookTests(WebhookTestCase):
STREAM_NAME = 'opsgenie'
URL_TEMPLATE = "/api/v1/external/opsgenie?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/opsgenie?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'opsgenie'
def test_acknowledge_alert(self) -> None:

View File

@@ -4,17 +4,16 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.validator import check_dict, check_string
from zerver.models import UserProfile
@api_key_only_webhook_view('OpsGenie')
@has_request_variables
def api_opsgenie_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='opsgenie')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
# construct the body of the message
info = {"additional_info": '',
@@ -48,6 +47,6 @@ def api_opsgenie_webhook(request: HttpRequest, user_profile: UserProfile,
"{tags}"
body += body_template.format(**info)
# send the message
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -7,9 +7,9 @@ import ujson
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import Client, UserProfile
PAGER_DUTY_EVENT_NAMES = {
@@ -69,26 +69,22 @@ def build_pagerduty_formatdict(message: Dict[str, Any]) -> Dict[str, Any]:
return format_dict
def send_raw_pagerduty_json(user_profile: UserProfile,
client: Client,
stream: Text,
message: Dict[str, Any],
topic: Optional[Text]) -> None:
subject = topic or 'pagerduty'
def send_raw_pagerduty_json(request: HttpRequest,
user_profile: UserProfile,
message: Dict[str, Any]) -> None:
subject = 'pagerduty'
body = (
u'Unknown pagerduty message\n'
u'```\n'
u'%s\n'
u'```') % (ujson.dumps(message, indent=2),)
check_send_stream_message(user_profile, client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
def send_formated_pagerduty(user_profile: UserProfile,
client: Client,
stream: Text,
def send_formated_pagerduty(request: HttpRequest,
user_profile: UserProfile,
message_type: Text,
format_dict: Dict[str, Any],
topic: Optional[Text]) -> None:
format_dict: Dict[str, Any]) -> None:
if message_type in ('incident.trigger', 'incident.unacknowledge'):
template = (u':imp: Incident '
u'[{incident_num}]({incident_url}) {action} by '
@@ -106,29 +102,29 @@ def send_formated_pagerduty(user_profile: UserProfile,
template = (u':no_good: Incident [{incident_num}]({incident_url}) '
u'{action} by [{assigned_to_username}@]({assigned_to_url})\n\n>{trigger_message}')
subject = topic or u'incident {incident_num}'.format(**format_dict)
subject = u'incident {incident_num}'.format(**format_dict)
body = template.format(**format_dict)
check_send_stream_message(user_profile, client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
@api_key_only_webhook_view('PagerDuty')
@has_request_variables
def api_pagerduty_webhook(request: HttpRequest, user_profile: UserProfile,
def api_pagerduty_webhook(
request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Iterable[Dict[str, Any]]]=REQ(argument_type='body'),
stream: Text=REQ(default='pagerduty'),
topic: Optional[Text]=REQ(default=None)) -> HttpResponse:
) -> HttpResponse:
for message in payload['messages']:
message_type = message['type']
if message_type not in PAGER_DUTY_EVENT_NAMES:
send_raw_pagerduty_json(user_profile, request.client, stream, message, topic)
send_raw_pagerduty_json(request, user_profile, message)
try:
format_dict = build_pagerduty_formatdict(message)
except Exception:
send_raw_pagerduty_json(user_profile, request.client, stream, message, topic)
send_raw_pagerduty_json(request, user_profile, message)
else:
send_formated_pagerduty(user_profile, request.client, stream, message_type, format_dict, topic)
send_formated_pagerduty(request, user_profile, message_type, format_dict)
return json_success()

View File

@@ -4,7 +4,7 @@ from zerver.lib.test_classes import WebhookTestCase
class PapertrailHookTests(WebhookTestCase):
STREAM_NAME = 'papertrail'
URL_TEMPLATE = "/api/v1/external/papertrail?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/papertrail?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'papertrail'
# Note: Include a test function per each distinct message condition your integration supports

View File

@@ -4,18 +4,16 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.validator import check_dict, check_string
from zerver.models import UserProfile
@api_key_only_webhook_view('Papertrail')
@has_request_variables
def api_papertrail_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='papertrail'),
topic: Text=REQ(default='logs')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
# construct the message of the message
message_template = '**"{}"** search found **{}** matches - {}\n```'
@@ -35,8 +33,10 @@ def api_papertrail_webhook(request: HttpRequest, user_profile: UserProfile,
message.append('```')
post = '\n'.join(message)
topic = 'logs'
# send the message
check_send_stream_message(user_profile, request.client, stream, topic, post)
check_send_webhook_message(request, user_profile, topic, post)
# return json result
return json_success()

View File

@@ -6,9 +6,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
PINGDOM_SUBJECT_TEMPLATE = '{name} status.'
@@ -34,8 +34,7 @@ SUPPORTED_CHECK_TYPES = (
@api_key_only_webhook_view('Pingdom')
@has_request_variables
def api_pingdom_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='pingdom')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
check_type = get_check_type(payload)
if check_type in SUPPORTED_CHECK_TYPES:
@@ -44,7 +43,7 @@ def api_pingdom_webhook(request: HttpRequest, user_profile: UserProfile,
else:
return json_error(_('Unsupported check_type: {check_type}').format(check_type=check_type))
check_send_stream_message(user_profile, request.client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
return json_success()

View File

@@ -10,13 +10,12 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
def api_pivotal_webhook_v3(request: HttpRequest, user_profile: UserProfile,
stream: Text) -> Tuple[Text, Text]:
def api_pivotal_webhook_v3(request: HttpRequest, user_profile: UserProfile) -> Tuple[Text, Text]:
payload = xml_fromstring(request.body)
def get_text(attrs: List[str]) -> str:
@@ -69,8 +68,7 @@ def api_pivotal_webhook_v3(request: HttpRequest, user_profile: UserProfile,
more_info)
return subject, content
def api_pivotal_webhook_v5(request: HttpRequest, user_profile: UserProfile,
stream: Text) -> Tuple[Text, Text]:
def api_pivotal_webhook_v5(request: HttpRequest, user_profile: UserProfile) -> Tuple[Text, Text]:
payload = ujson.loads(request.body)
event_type = payload["kind"]
@@ -160,16 +158,16 @@ def api_pivotal_webhook_v5(request: HttpRequest, user_profile: UserProfile,
@api_key_only_webhook_view("Pivotal")
@has_request_variables
def api_pivotal_webhook(request: HttpRequest, user_profile: UserProfile, stream: Text=REQ()) -> HttpResponse:
def api_pivotal_webhook(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
subject = content = None
try:
subject, content = api_pivotal_webhook_v3(request, user_profile, stream)
subject, content = api_pivotal_webhook_v3(request, user_profile)
except Exception:
# Attempt to parse v5 JSON payload
subject, content = api_pivotal_webhook_v5(request, user_profile, stream)
subject, content = api_pivotal_webhook_v5(request, user_profile)
if subject is None or content is None:
return json_error(_("Unable to handle Pivotal payload"))
check_send_stream_message(user_profile, request.client, stream, subject, content)
check_send_webhook_message(request, user_profile, subject, content)
return json_success()

View File

@@ -6,7 +6,7 @@ from zerver.lib.test_classes import WebhookTestCase
class RaygunHookTests(WebhookTestCase):
STREAM_NAME = 'raygun'
URL_TEMPLATE = "/api/v1/external/raygun?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/raygun?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'raygun'
def test_status_changed_message(self) -> None:

View File

@@ -3,9 +3,9 @@ from typing import Any, Dict, Optional, Text
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
import time
@@ -14,9 +14,7 @@ import time
@api_key_only_webhook_view('Raygun')
@has_request_variables
def api_raygun_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any] = REQ(argument_type='body'),
stream: Text = REQ(default='raygun'),
topic: Optional[Text] = REQ(default='test')) -> HttpResponse:
payload: Dict[str, Any] = REQ(argument_type='body')) -> HttpResponse:
# The payload contains 'event' key. This 'event' key has a value of either
# 'error_notification' or 'error_activity'. 'error_notification' happens
# when an error is caught in an application, where as 'error_activity'
@@ -35,8 +33,9 @@ def api_raygun_webhook(request: HttpRequest, user_profile: UserProfile,
else:
message = "Unsupported event type: {}".format(event)
check_send_stream_message(user_profile, request.client, stream, topic,
message)
topic = 'test'
check_send_webhook_message(request, user_profile, topic, message)
return json_success()

View File

@@ -7,16 +7,15 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile, get_client
@api_key_only_webhook_view('Semaphore')
@has_request_variables
def api_semaphore_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: str=REQ(default='builds')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
# semaphore only gives the last commit, even if there were multiple commits
# since the last build
@@ -50,5 +49,5 @@ def api_semaphore_webhook(request: HttpRequest, user_profile: UserProfile,
commit_url, message)
subject = u"%s/%s" % (project_name, branch_name)
check_send_stream_message(user_profile, request.client, stream, subject, content)
check_send_webhook_message(request, user_profile, subject, content)
return json_success()

View File

@@ -3,7 +3,7 @@ from zerver.lib.test_classes import WebhookTestCase
class SentryHookTests(WebhookTestCase):
STREAM_NAME = 'sentry'
URL_TEMPLATE = "/api/v1/external/sentry?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/sentry?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'sentry'
def test_error_issue_message(self) -> None:

View File

@@ -4,19 +4,18 @@ from typing import Any, Dict
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view('Sentry')
@has_request_variables
def api_sentry_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any] = REQ(argument_type='body'),
stream: str = REQ(default='sentry')) -> HttpResponse:
payload: Dict[str, Any] = REQ(argument_type='body')) -> HttpResponse:
subject = "{}".format(payload.get('project_name'))
body = "New {} [issue]({}): {}.".format(payload['level'].upper(),
payload.get('url'),
payload.get('message'))
check_send_stream_message(user_profile, request.client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
return json_success()

View File

@@ -6,7 +6,7 @@ from zerver.lib.test_classes import WebhookTestCase
class SolanoHookTests(WebhookTestCase):
STREAM_NAME = 'solano labs'
URL_TEMPLATE = u"/api/v1/external/solano?api_key={api_key}"
URL_TEMPLATE = u"/api/v1/external/solano?api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'solano'
def test_solano_message_001(self) -> None:

View File

@@ -6,20 +6,19 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import Client, UserProfile
@api_key_only_webhook_view('SolanoLabs')
@has_request_variables
def api_solano_webhook(request: HttpRequest, user_profile: UserProfile,
stream: str=REQ(default='solano labs'),
topic: str=REQ(default='build update'),
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
event = payload.get('event')
topic = 'build update'
if event == 'test':
return handle_test_event(user_profile, request.client, stream, topic)
return handle_test_event(request, user_profile, topic)
try:
author = payload['committers'][0]
except KeyError:
@@ -60,11 +59,11 @@ def api_solano_webhook(request: HttpRequest, user_profile: UserProfile,
body = template.format(author, commit_id, commit_url, status, emoji, build_log)
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()
def handle_test_event(user_profile: UserProfile, client: Client, stream: str,
def handle_test_event(request: HttpRequest, user_profile: UserProfile,
topic: str) -> HttpResponse:
body = 'Solano webhook set up correctly'
check_send_stream_message(user_profile, client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -5,18 +5,16 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.validator import check_dict, check_string
from zerver.models import MAX_SUBJECT_LENGTH, UserProfile
@api_key_only_webhook_view('Splunk')
@has_request_variables
def api_splunk_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='splunk'),
topic: Optional[Text]=REQ(default=None)) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
# use default values if expected data is not provided
search_name = payload.get('search_name', 'Missing search_name')
@@ -25,8 +23,7 @@ def api_splunk_webhook(request: HttpRequest, user_profile: UserProfile,
source = payload.get('result', {}).get('source', 'Missing source')
raw = payload.get('result', {}).get('_raw', 'Missing _raw')
# if no topic provided, use search name but truncate if too long
if topic is None:
# for the default topic, use search name but truncate if too long
if len(search_name) >= MAX_SUBJECT_LENGTH:
topic = "{}...".format(search_name[:(MAX_SUBJECT_LENGTH - 3)])
else:
@@ -40,6 +37,6 @@ def api_splunk_webhook(request: HttpRequest, user_profile: UserProfile,
host = host, source = source, raw = raw)
# send the message
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -4,7 +4,7 @@ from zerver.lib.test_classes import WebhookTestCase
class StatuspageHookTests(WebhookTestCase):
STREAM_NAME = 'statuspage-test'
URL_TEMPLATE = u"/api/v1/external/statuspage?api_key={api_key}"
URL_TEMPLATE = u"/api/v1/external/statuspage?api_key={api_key}&stream={stream}"
def test_statuspage_incident(self) -> None:
expected_subject = u"Database query delays: All Systems Operational"

View File

@@ -1,7 +1,7 @@
# Webhooks for external integrations.
from django.utils.translation import ugettext as _
from zerver.lib.actions import check_send_stream_message
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
from zerver.models import get_client, UserProfile
from django.http import HttpRequest, HttpResponse
@@ -40,8 +40,7 @@ def get_component_topic(payload: Dict[Text, Any]) -> Text:
@api_key_only_webhook_view('Statuspage')
@has_request_variables
def api_statuspage_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: str=REQ(default='statuspage-test')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
status = payload["page"]["status_indicator"]
@@ -52,9 +51,5 @@ def api_statuspage_webhook(request: HttpRequest, user_profile: UserProfile,
topic = get_component_topic(payload)
body = get_components_update_body(payload)
check_send_stream_message(user_profile,
request.client,
stream,
topic,
body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -7,7 +7,7 @@ from zerver.lib.test_classes import WebhookTestCase
class StripeHookTests(WebhookTestCase):
STREAM_NAME = 'test'
URL_TEMPLATE = "/api/v1/external/stripe?&api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/stripe?&api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'stripe'
def test_charge_dispute_closed(self) -> None:

View File

@@ -7,17 +7,16 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view('Stripe')
@has_request_variables
def api_stripe_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='test'),
topic: Optional[Text]=REQ(default=None)) -> HttpResponse:
stream: Text=REQ(default='test')) -> HttpResponse:
body = None
event_type = payload["type"]
data_object = payload["data"]["object"]
@@ -56,7 +55,6 @@ def api_stripe_webhook(request: HttpRequest, user_profile: UserProfile,
verb = "succeeded"
body = body_template.format(charge_id=charge_id, link=link, amount=amount_string, verb=verb)
if topic is None:
topic = "Charge {}".format(charge_id)
elif event_type.startswith('customer'):
@@ -106,7 +104,6 @@ def api_stripe_webhook(request: HttpRequest, user_profile: UserProfile,
rest = "has been deleted"
body = body_template.format(beginning=beginning, id=object_id, link=link, rest=rest)
if topic is None:
topic = "Customer {}".format(object_id)
elif event_type == "invoice.payment_failed":
@@ -116,8 +113,6 @@ def api_stripe_webhook(request: HttpRequest, user_profile: UserProfile,
body_template = "An invoice payment on invoice with id **[{id}]({link})** and "\
"with **{amount}** due has failed."
body = body_template.format(id=object_id, amount=amount_string, link=link)
if topic is None:
topic = "Invoice {}".format(object_id)
elif event_type.startswith('order'):
@@ -141,8 +136,6 @@ def api_stripe_webhook(request: HttpRequest, user_profile: UserProfile,
link=link,
amount=amount_string,
end=end)
if topic is None:
topic = "Order {}".format(object_id)
elif event_type.startswith('transfer'):
@@ -162,14 +155,12 @@ def api_stripe_webhook(request: HttpRequest, user_profile: UserProfile,
amount=amount_string,
end=end
)
if topic is None:
topic = "Transfer {}".format(object_id)
if body is None:
return json_error(_("We don't support {} event".format(event_type)))
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -25,25 +25,24 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view('Taiga')
@has_request_variables
def api_taiga_webhook(request: HttpRequest, user_profile: UserProfile,
message: Dict[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='taiga'),
topic: Text=REQ(default='General')) -> HttpResponse:
message: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
parsed_events = parse_message(message)
content_lines = []
for event in parsed_events:
content_lines.append(generate_content(event) + '\n')
content = "".join(sorted(content_lines))
topic = 'General'
check_send_stream_message(user_profile, request.client, stream, topic, content)
check_send_webhook_message(request, user_profile, topic, content)
return json_success()

View File

@@ -5,9 +5,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view('Transifex')
@@ -15,8 +15,7 @@ from zerver.models import UserProfile
def api_transifex_webhook(request: HttpRequest, user_profile: UserProfile,
project: str=REQ(), resource: str=REQ(),
language: str=REQ(), translated: Optional[int]=REQ(default=None),
reviewed: Optional[int]=REQ(default=None),
stream: str=REQ(default='transifex')) -> HttpResponse:
reviewed: Optional[int]=REQ(default=None)) -> HttpResponse:
subject = "{} in {}".format(project, language)
if translated:
body = "Resource {} fully translated.".format(resource)
@@ -24,5 +23,5 @@ def api_transifex_webhook(request: HttpRequest, user_profile: UserProfile,
body = "Resource {} fully reviewed.".format(resource)
else:
return json_error(_("Transifex wrong request"))
check_send_stream_message(user_profile, request.client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
return json_success()

View File

@@ -7,7 +7,7 @@ from zerver.models import get_realm, get_user
class TravisHookTests(WebhookTestCase):
STREAM_NAME = 'travis'
URL_TEMPLATE = u"/api/v1/external/travis?stream={stream}&api_key={api_key}&topic=builds"
URL_TEMPLATE = u"/api/v1/external/travis?stream={stream}&api_key={api_key}"
FIXTURE_DIR_NAME = 'travis'
TOPIC = 'builds'

View File

@@ -6,9 +6,9 @@ import ujson
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.lib.validator import check_bool, check_dict, check_string
from zerver.models import UserProfile
@@ -24,8 +24,6 @@ MESSAGE_TEMPLATE = (
@api_key_only_webhook_view('Travis')
@has_request_variables
def api_travis_webhook(request: HttpRequest, user_profile: UserProfile,
stream: str = REQ(default='travis'),
topic: str = REQ(default=None),
ignore_pull_requests: bool = REQ(validator=check_bool, default=True),
message: Dict[str, str]=REQ('payload', validator=check_dict([
('author_name', check_string),
@@ -51,6 +49,7 @@ def api_travis_webhook(request: HttpRequest, user_profile: UserProfile,
message['compare_url'],
message['build_url']
)
topic = 'builds'
check_send_stream_message(user_profile, request.client, stream, topic, body)
check_send_webhook_message(request, user_profile, topic, body)
return json_success()

View File

@@ -88,20 +88,20 @@ class TrelloHookTests(WebhookTestCase):
expected_message = u"TomaszKolek renamed the board from Welcome Board to [New name](https://trello.com/b/iqXXzYEj)."
self.send_and_test_stream_message('renaming_board', u"New name", expected_message)
@patch('zerver.webhooks.trello.view.check_send_stream_message')
@patch('zerver.webhooks.trello.view.check_send_webhook_message')
def test_trello_webhook_when_card_is_moved_within_single_list_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
payload = self.get_body('moving_card_within_single_list')
result = self.client_post(self.url, payload, content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
@patch('zerver.webhooks.trello.view.check_send_stream_message')
@patch('zerver.webhooks.trello.view.check_send_webhook_message')
def test_trello_webhook_when_board_background_is_changed_ignore(
self, check_send_stream_message_mock: MagicMock) -> None:
self, check_send_webhook_message_mock: MagicMock) -> None:
payload = self.get_body('change_board_background_image')
result = self.client_post(self.url, payload, content_type="application/json")
self.assertFalse(check_send_stream_message_mock.called)
self.assertFalse(check_send_webhook_message_mock.called)
self.assert_json_success(result)
def test_trello_webhook_when_description_was_added_to_card(self) -> None:

View File

@@ -4,9 +4,9 @@ from typing import Mapping, Any, Tuple, Text, Optional
from django.utils.translation import ugettext as _
from django.http import HttpRequest, HttpResponse
from zerver.decorator import api_key_only_webhook_view, return_success_on_head_request
from zerver.lib.actions import check_send_stream_message
from zerver.lib.response import json_success, json_error
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
from .card_actions import SUPPORTED_CARD_ACTIONS, process_card_action
@@ -18,8 +18,7 @@ from .exceptions import UnsupportedAction
@has_request_variables
def api_trello_webhook(request: HttpRequest,
user_profile: UserProfile,
payload: Mapping[str, Any]=REQ(argument_type='body'),
stream: Text=REQ(default='trello')) -> HttpResponse:
payload: Mapping[str, Any]=REQ(argument_type='body')) -> HttpResponse:
payload = ujson.loads(request.body)
action_type = payload['action'].get('type')
try:
@@ -31,7 +30,7 @@ def api_trello_webhook(request: HttpRequest,
except UnsupportedAction:
return json_error(_('Unsupported action_type: {action_type}'.format(action_type=action_type)))
check_send_stream_message(user_profile, request.client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
return json_success()
def get_subject_and_body(payload: Mapping[str, Any], action_type: Text) -> Optional[Tuple[Text, Text]]:

View File

@@ -7,20 +7,20 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.exceptions import JsonableError
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import Client, UserProfile
SUBJECT_TEMPLATE = "{service_url}"
def send_message_for_event(event: Dict[str, Any], user_profile: UserProfile,
client: Client, stream: str) -> None:
def send_message_for_event(request: HttpRequest, user_profile: UserProfile,
event: Dict[str, Any]) -> None:
event_type = get_event_type(event)
subject = SUBJECT_TEMPLATE.format(service_url=event['check']['url'])
body = EVENT_TYPE_BODY_MAPPER[event_type](event)
check_send_stream_message(user_profile, client, stream, subject, body)
check_send_webhook_message(request, user_profile, subject, body)
def get_body_for_up_event(event: Dict[str, Any]) -> str:
body = "Service is `up`"
@@ -58,11 +58,12 @@ def get_body_for_down_event(event: Dict[str, Any]) -> str:
@api_key_only_webhook_view('Updown')
@has_request_variables
def api_updown_webhook(request: HttpRequest, user_profile: UserProfile,
payload: List[Dict[str, Any]]=REQ(argument_type='body'),
stream: str=REQ(default='updown')) -> HttpResponse:
def api_updown_webhook(
request: HttpRequest, user_profile: UserProfile,
payload: List[Dict[str, Any]]=REQ(argument_type='body')
) -> HttpResponse:
for event in payload:
send_message_for_event(event, user_profile, request.client, stream)
send_message_for_event(request, user_profile, event)
return json_success()
EVENT_TYPE_BODY_MAPPER = {

View File

@@ -4,7 +4,7 @@ from zerver.models import get_realm, get_user
class WordPressHookTests(WebhookTestCase):
STREAM_NAME = 'wordpress'
URL_TEMPLATE = "/api/v1/external/wordpress?api_key={api_key}"
URL_TEMPLATE = "/api/v1/external/wordpress?api_key={api_key}&stream={stream}"
FIXTURE_DIR_NAME = 'wordpress'
def test_publish_post(self) -> None:

View File

@@ -3,9 +3,9 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile, get_client
PUBLISH_POST_OR_PAGE_TEMPLATE = 'New {type} published.\n[{title}]({url})'
@@ -15,8 +15,6 @@ WP_LOGIN_TEMPLATE = 'User {name} logged in.'
@api_key_only_webhook_view("Wordpress")
@has_request_variables
def api_wordpress_webhook(request: HttpRequest, user_profile: UserProfile,
stream: str=REQ(default="wordpress"),
topic: str=REQ(default="WordPress Notification"),
hook: str=REQ(default="WordPress Action"),
post_title: str=REQ(default="New WordPress Post"),
post_type: str=REQ(default="post"),
@@ -39,6 +37,7 @@ def api_wordpress_webhook(request: HttpRequest, user_profile: UserProfile,
else:
return json_error(_("Unknown WordPress webhook action: " + hook))
check_send_stream_message(user_profile, get_client("ZulipWordPressWebhook"),
stream, topic, data)
topic = 'WordPress Notification'
check_send_webhook_message(request, user_profile, topic, data)
return json_success()

View File

@@ -4,21 +4,20 @@ from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from zerver.decorator import api_key_only_webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_error, json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile
@api_key_only_webhook_view('Zapier')
@has_request_variables
def api_zapier_webhook(request: HttpRequest, user_profile: UserProfile,
payload: Dict[str, Any]=REQ(argument_type='body'),
stream: str=REQ(default='zapier')) -> HttpResponse:
payload: Dict[str, Any]=REQ(argument_type='body')) -> HttpResponse:
subject = payload.get('subject')
content = payload.get('content')
if subject is None:
return json_error(_("Subject can't be empty"))
if content is None:
return json_error(_("Content can't be empty"))
check_send_stream_message(user_profile, request.client, stream, subject, content)
check_send_webhook_message(request, user_profile, subject, content)
return json_success()

View File

@@ -5,7 +5,7 @@ from zerver.lib.test_classes import WebhookTestCase
class ZenDeskHookTests(WebhookTestCase):
STREAM_NAME = 'zendesk'
URL_TEMPLATE = u"/api/v1/external/zendesk"
URL_TEMPLATE = u"/api/v1/external/zendesk?stream={stream}"
DEFAULT_TICKET_TITLE = 'User can\'t login'
TICKET_TITLE = DEFAULT_TICKET_TITLE

View File

@@ -4,9 +4,9 @@ from typing import Text
from django.http import HttpRequest, HttpResponse
from zerver.decorator import authenticated_rest_api_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile, get_client
def truncate(string: Text, length: int) -> Text:
@@ -18,13 +18,12 @@ def truncate(string: Text, length: int) -> Text:
@has_request_variables
def api_zendesk_webhook(request: HttpRequest, user_profile: UserProfile,
ticket_title: str=REQ(), ticket_id: str=REQ(),
message: str=REQ(), stream: str=REQ(default="zendesk")) -> HttpResponse:
message: str=REQ()) -> HttpResponse:
"""
Zendesk uses trigers with message templates. This webhook uses the
ticket_id and ticket_title to create a subject. And passes with zendesk
user's configured message to zulip.
"""
subject = truncate('#%s: %s' % (ticket_id, ticket_title), 60)
check_send_stream_message(user_profile, get_client('ZulipZenDeskWebhook'),
stream, subject, message)
check_send_webhook_message(request, user_profile, subject, message)
return json_success()