def send_formated_pagerduty(user_profile, client, stream, message_type, format_dict, topic): if message_type in ("incident.trigger", "incident.unacknowledge"): template = ( u":imp: Incident " u"[{incident_num}]({incident_url}) {action} by " u"[{service_name}]({service_url}) and assigned to " u"[{assigned_to_username}@]({assigned_to_url})\n\n>{trigger_message}" ) elif message_type == "incident.resolve" and format_dict["resolved_by_url"]: template = ( u":grinning: Incident " u"[{incident_num}]({incident_url}) resolved by " u"[{resolved_by_username}@]({resolved_by_url})\n\n>{trigger_message}" ) elif message_type == "incident.resolve" and not format_dict["resolved_by_url"]: template = u":grinning: Incident " u"[{incident_num}]({incident_url}) resolved\n\n>{trigger_message}" else: 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) body = template.format(**format_dict) check_send_message(user_profile, client, "stream", [stream], subject, body)
def api_stash_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='commits')): # type: (HttpRequest, UserProfile, Dict[str, Any], text_type) -> HttpResponse # We don't get who did the push, or we'd try to report that. try: repo_name = payload["repository"]["name"] project_name = payload["repository"]["project"]["name"] branch_name = payload["refChanges"][0]["refId"].split("/")[-1] commit_entries = payload["changesets"]["values"] commits = [(entry["toCommit"]["displayId"], entry["toCommit"]["message"].split("\n")[0]) for \ entry in commit_entries] head_ref = commit_entries[-1]["toCommit"]["displayId"] except KeyError as e: return json_error(_("Missing key %s in JSON") % (e.message,)) subject = "%s/%s: %s" % (project_name, repo_name, branch_name) content = "`%s` was pushed to **%s** in **%s/%s** with:\n\n" % ( head_ref, branch_name, project_name, repo_name) content += "\n".join("* `%s`: %s" % ( commit[0], commit[1]) for commit in commits) check_send_message(user_profile, get_client("ZulipStashWebhook"), "stream", [stream], subject, content) return json_success()
def api_yo_app_webhook(request, user_profile, email=REQ(default=None), username=REQ(default='Yo Bot'), topic=REQ(default='None'), user_ip=REQ(default='None')): body = ('Yo from %s') % (username,) check_send_message(user_profile, get_client('ZulipYoWebhook'), 'private', [email], topic, body) return json_success()
def api_beanstalk_webhook(request, user_profile, payload=REQ(validator=check_dict([]))): # Beanstalk supports both SVN and git repositories # We distinguish between the two by checking for a # 'uri' key that is only present for git repos git_repo = 'uri' in payload if git_repo: # To get a linkable url, subject, content = build_message_from_gitlog(user_profile, payload['repository']['name'], payload['ref'], payload['commits'], payload['before'], payload['after'], payload['repository']['url'], payload['pusher_name']) else: author = payload.get('author_full_name') url = payload.get('changeset_url') revision = payload.get('revision') (short_commit_msg, _, _) = payload.get('message').partition("\n") subject = "svn r%s" % (revision,) content = "%s pushed [revision %s](%s):\n\n> %s" % (author, revision, url, short_commit_msg) check_send_message(user_profile, get_client("ZulipBeanstalkWebhook"), "stream", ["commits"], subject, content) return json_success()
def api_splunk_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='splunk'), topic=REQ(default=None)): # type: (HttpRequest, UserProfile, Dict[str, Any], Text, Optional[Text]) -> HttpResponse # use default values if expected data is not provided search_name = payload.get('search_name', 'Missing search_name') results_link = payload.get('results_link', 'Missing results_link') host = payload.get('result', {}).get('host', 'Missing host') 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: if len(search_name) >= MAX_SUBJECT_LENGTH: topic = "{}...".format(search_name[:(MAX_SUBJECT_LENGTH - 3)]) else: topic = search_name # construct the message body body = "Splunk alert from saved search" body_template = ('\n[{search}]({link})\nhost: {host}' '\nsource: {source}\n\nraw: {raw}') body += body_template.format(search = search_name, link = results_link, host = host, source = source, raw = raw) # send the message check_send_message(user_profile, request.client, 'stream', [stream], topic, body) return json_success()
def api_newrelic_webhook(request, user_profile, alert=REQ(validator=check_dict([]), default=None), deployment=REQ(validator=check_dict([]), default=None)): try: stream = request.GET['stream'] except (AttributeError, KeyError): return json_error("Missing stream parameter.") if alert: # Use the message as the subject because it stays the same for # "opened", "acknowledged", and "closed" messages that should be # grouped. subject = alert['message'] content = "%(long_description)s\n[View alert](%(alert_url)s)" % (alert) elif deployment: subject = "%s deploy" % (deployment['application_name']) content = """`%(revision)s` deployed by **%(deployed_by)s** %(description)s %(changelog)s""" % (deployment) else: return json_error("Unknown webhook request") check_send_message(user_profile, get_client("ZulipNewRelicWebhook"), "stream", [stream], subject, content) return json_success()
def api_beanstalk_webhook(request, user_profile, payload=REQ(validator=check_dict([])), branches=REQ(default=None)): # type: (HttpRequest, UserProfile, Dict[str, Any], Optional[Text]) -> HttpResponse # Beanstalk supports both SVN and git repositories # We distinguish between the two by checking for a # 'uri' key that is only present for git repos git_repo = 'uri' in payload if git_repo: if branches is not None and branches.find(payload['branch']) == -1: return json_success() # To get a linkable url, for commit in payload['commits']: commit['author'] = {'username': commit['author']['name']} subject, content = build_message_from_gitlog(user_profile, payload['repository']['name'], payload['ref'], payload['commits'], payload['before'], payload['after'], payload['repository']['url'], payload['pusher_name']) else: author = payload.get('author_full_name') url = payload.get('changeset_url') revision = payload.get('revision') (short_commit_msg, _, _) = payload.get('message').partition("\n") subject = "svn r%s" % (revision,) content = "%s pushed [revision %s](%s):\n\n> %s" % (author, revision, url, short_commit_msg) check_send_message(user_profile, get_client("ZulipBeanstalkWebhook"), "stream", ["commits"], subject, content) return json_success()
def api_travis_webhook(request, user_profile, client, stream=REQ(default='travis'), topic=REQ(default=None), message=REQ('payload', validator=check_dict([ ('author_name', check_string), ('status_message', check_string), ('compare_url', check_string), ]))): author = message['author_name'] message_type = message['status_message'] changes = message['compare_url'] good_status = ['Passed', 'Fixed'] bad_status = ['Failed', 'Broken', 'Still Failing'] emoji = '' if message_type in good_status: emoji = ':thumbsup:' elif message_type in bad_status: emoji = ':thumbsdown:' else: emoji = "(No emoji specified for status '%s'.)" % (message_type,) build_url = message['build_url'] template = ( u'Author: %s\n' u'Build status: %s %s\n' u'Details: [changes](%s), [build log](%s)') body = template % (author, message_type, emoji, changes, build_url) check_send_message(user_profile, client, 'stream', [stream], topic, body) return json_success()
def api_deskdotcom_webhook(request, user_profile, data=REQ(), topic=REQ(default="Desk.com notification"), stream=REQ(default="desk.com")): # type: (HttpRequest, UserProfile, text_type, text_type, text_type) -> HttpResponse check_send_message(user_profile, get_client("ZulipDeskWebhook"), "stream", [stream], topic, data) return json_success()
def api_bitbucket_webhook(request, user_profile, payload=REQ(validator=check_dict([])), stream=REQ(default='commits')): # type: (HttpRequest, UserProfile, Mapping[Text, Any], Text) -> HttpResponse repository = payload['repository'] commits = [ { 'sha': commit.get('raw_node'), 'message': commit.get('message'), 'url': u'{}{}commits/{}'.format( payload.get('canon_url'), repository.get('absolute_url'), commit.get('raw_node')) } for commit in payload.get('commits') ] if len(commits) == 0: # Bitbucket doesn't give us enough information to really give # a useful message :/ subject = repository['name'] content = (u"%s [force pushed](%s)" % (payload['user'], payload['canon_url'] + repository['absolute_url'])) else: branch = payload['commits'][-1]['branch'] content = get_push_commits_event_message(payload.get('user'), None, branch, commits) subject = SUBJECT_WITH_BRANCH_TEMPLATE.format(repo=repository['name'], branch=branch) check_send_message(user_profile, get_client("ZulipBitBucketWebhook"), "stream", [stream], subject, content) return json_success()
def api_wordpress_webhook(request, user_profile, stream=REQ(default="wordpress"), topic=REQ(default="WordPress Notification"), hook=REQ(default="WordPress Action"), post_title=REQ(default="New WordPress Post"), post_type=REQ(default="post"), post_url=REQ(default="WordPress Post URL"), display_name=REQ(default="New User Name"), user_email=REQ(default="New User Email"), user_login=REQ(default="Logged in User")): # type: (HttpRequest, UserProfile, text_type, text_type, text_type, text_type, text_type, text_type, text_type, text_type, text_type) -> HttpResponse # remove trailing whitespace (issue for some test fixtures) hook = hook.rstrip() if hook == 'publish_post' or hook == 'publish_page': data = PUBLISH_POST_OR_PAGE_TEMPLATE.format(type=post_type, title=post_title, url=post_url) elif hook == 'user_register': data = USER_REGISTER_TEMPLATE.format(name=display_name, email=user_email) elif hook == 'wp_login': data = WP_LOGIN_TEMPLATE.format(name=user_login) else: return json_error(_("Unknown WordPress webhook action: " + hook)) check_send_message(user_profile, get_client("ZulipWordPressWebhook"), "stream", [stream], topic, data) return json_success()
def api_travis_webhook(request, user_profile, client, stream=REQ(default='travis'), topic=REQ(default=None), ignore_pull_requests=REQ(validator=check_bool, default=True), message=REQ('payload', validator=check_dict([ ('author_name', check_string), ('status_message', check_string), ('compare_url', check_string), ]))): # type: (HttpRequest, UserProfile, Client, str, str, str, Dict[str, str]) -> HttpResponse message_status = message['status_message'] if ignore_pull_requests and message['type'] == 'pull_request': return json_success() if message_status in GOOD_STATUSES: emoji = ':thumbsup:' elif message_status in BAD_STATUSES: emoji = ':thumbsdown:' else: emoji = "(No emoji specified for status '{}'.)".format(message_status) body = MESSAGE_TEMPLATE.format( message['author_name'], message_status, emoji, message['compare_url'], message['build_url'] ) check_send_message(user_profile, client, 'stream', [stream], topic, body) return json_success()
def api_stash_webhook(request, user_profile, stream=REQ(default='')): try: payload = ujson.loads(request.body) except ValueError: return json_error("Malformed JSON input") # We don't get who did the push, or we'd try to report that. try: repo_name = payload["repository"]["name"] project_name = payload["repository"]["project"]["name"] branch_name = payload["refChanges"][0]["refId"].split("/")[-1] commit_entries = payload["changesets"]["values"] commits = [(entry["toCommit"]["displayId"], entry["toCommit"]["message"].split("\n")[0]) for \ entry in commit_entries] head_ref = commit_entries[-1]["toCommit"]["displayId"] except KeyError as e: return json_error("Missing key %s in JSON" % (e.message,)) try: stream = request.GET['stream'] except (AttributeError, KeyError): stream = 'commits' subject = "%s/%s: %s" % (project_name, repo_name, branch_name) content = "`%s` was pushed to **%s** in **%s/%s** with:\n\n" % ( head_ref, branch_name, project_name, repo_name) content += "\n".join("* `%s`: %s" % ( commit[0], commit[1]) for commit in commits) check_send_message(user_profile, get_client("ZulipStashWebhook"), "stream", [stream], subject, content) return json_success()
def api_circleci_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='circleci')): payload = payload['payload'] subject = get_subject(payload) body = get_body(payload) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def api_papertrail_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='papertrail'), topic=REQ(default='logs')): # type: (HttpRequest, UserProfile, Dict[str, Any], Text, Text) -> HttpResponse # construct the message of the message try: message_template = '**"{}"** search found **{}** matches - {}\n```' message = [message_template.format(payload["saved_search"]["name"], str(len(payload["events"])), payload["saved_search"]["html_search_url"])] for i, event in enumerate(payload["events"]): event_text = '{} {} {}:\n {}'.format(event["display_received_at"], event["source_name"], payload["saved_search"]["query"], event["message"]) message.append(event_text) if i >= 3: message.append('```\n[See more]({})'.format(payload["saved_search"]["html_search_url"])) break else: message.append('```') post = '\n'.join(message) except KeyError as e: return json_error(_("Missing key {} in JSON").format(str(e))) # send the message check_send_message(user_profile, request.client, 'stream', [stream], topic, post) # return json result return json_success()
def api_teamcity_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='teamcity')): # type: (HttpRequest, UserProfile, Dict[str, Any], str) -> HttpResponse message = payload['build'] build_name = message['buildFullName'] build_url = message['buildStatusUrl'] changes_url = build_url + '&tab=buildChangesDiv' build_number = message['buildNumber'] build_result = message['buildResult'] build_result_delta = message['buildResultDelta'] build_status = message['buildStatus'] if build_result == 'success': if build_result_delta == 'fixed': status = 'has been fixed! :thumbsup:' else: status = 'was successful! :thumbsup:' elif build_result == 'failure': if build_result_delta == 'broken': status = 'is broken with status %s! :thumbsdown:' % (build_status,) else: status = 'is still broken with status %s! :thumbsdown:' % (build_status,) elif build_result == 'running': status = 'has started.' else: status = '(has no message specified for status %s)' % (build_status,) template = ( u'%s build %s %s\n' u'Details: [changes](%s), [build log](%s)') body = template % (build_name, build_number, status, changes_url, build_url) topic = build_name # Check if this is a personal build, and if so try to private message the user who triggered it. if get_teamcity_property_value(message['teamcityProperties'], 'env.BUILD_IS_PERSONAL') == 'true': # The triggeredBy field gives us the teamcity user full name, and the "teamcity.build.triggeredBy.username" # property gives us the teamcity username. Let's try finding the user email from both. teamcity_fullname = message['triggeredBy'].split(';')[0] teamcity_user = guess_zulip_user_from_teamcity(teamcity_fullname, user_profile.realm) if teamcity_user is None: teamcity_shortname = get_teamcity_property_value(message['teamcityProperties'], 'teamcity.build.triggeredBy.username') if teamcity_shortname is not None: teamcity_user = guess_zulip_user_from_teamcity(teamcity_shortname, user_profile.realm) if teamcity_user is None: # We can't figure out who started this build - there's nothing we can do here. logging.info("Teamcity webhook couldn't find a matching Zulip user for Teamcity user '%s' or '%s'" % ( teamcity_fullname, teamcity_shortname)) return json_success() body = "Your personal build of " + body check_send_message(user_profile, request.client, 'private', [teamcity_user.email], topic, body) return json_success() check_send_message(user_profile, request.client, 'stream', [stream], topic, body) return json_success()
def api_greenhouse_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='greenhouse'), topic=REQ(default=None)): # type: (HttpRequest, UserProfile, Dict[str, Any], str, str) -> HttpResponse try: if payload['action'] == 'update_candidate': candidate = payload['payload']['candidate'] else: candidate = payload['payload']['application']['candidate'] action = payload['action'].replace('_', ' ').title() body = "{}\n>{} {}\nID: {}\n{}".format( action, candidate['first_name'], candidate['last_name'], str(candidate['id']), message_creator(payload['action'], payload['payload']['application'])) if topic is None: topic = "{} - {}".format(action, str(candidate['id'])) except KeyError as e: return json_error(_("Missing key {} in JSON").format(str(e))) check_send_message(user_profile, request.client, 'stream', [stream], topic, body) return json_success()
def api_bitbucket_webhook(request, user_profile, payload=REQ(validator=check_dict([])), stream=REQ(default='commits')): # type: (HttpRequest, UserProfile, Dict[str, Any], str) -> None repository = payload['repository'] commits = [{'id': commit['raw_node'], 'message': commit['message'], 'url': '%s%scommits/%s' % (payload['canon_url'], repository['absolute_url'], commit['raw_node'])} for commit in payload['commits']] subject = repository['name'] if len(commits) == 0: # Bitbucket doesn't give us enough information to really give # a useful message :/ content = ("%s [force pushed](%s)" % (payload['user'], payload['canon_url'] + repository['absolute_url'])) else: branch = payload['commits'][-1]['branch'] content = build_commit_list_content(commits, branch, None, payload['user']) subject += '/%s' % (branch,) check_send_message(user_profile, get_client("ZulipBitBucketWebhook"), "stream", [stream], subject, content) return json_success()
def api_basecamp_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='basecamp')): # type: (HttpRequest, UserProfile, Dict[str, Any], Text) -> HttpResponse event = get_event_type(payload) if event not in SUPPORT_EVENTS: logging.warning("Basecamp {} event is not supported".format(event)) return json_success() subject = get_project_name(payload) if event.startswith('document_'): body = get_document_body(event, payload) elif event.startswith('question_answer_'): body = get_questions_answer_body(event, payload) elif event.startswith('question_'): body = get_questions_body(event, payload) elif event.startswith('message_'): body = get_message_body(event, payload) elif event.startswith('todolist_'): body = get_todo_list_body(event, payload) elif event.startswith('todo_'): body = get_todo_body(event, payload) elif event.startswith('comment_'): body = get_comment_body(event, payload) else: logging.warning("Basecamp handling of {} event is not implemented".format(event)) return json_success() check_send_message(user_profile, request.client, 'stream', [stream], subject, body) return json_success()
def api_jira_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='jira')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], Text) -> HttpResponse event = payload.get('webhookEvent') if event == 'jira:issue_created': subject = get_issue_subject(payload) content = handle_created_issue_event(payload) elif event == 'jira:issue_deleted': subject = get_issue_subject(payload) content = handle_deleted_issue_event(payload) elif event == 'jira:issue_updated': subject = get_issue_subject(payload) content = handle_updated_issue_event(payload, user_profile) elif event in IGNORED_EVENTS: return json_success() else: if event is None: if not settings.TEST_SUITE: message = "Got JIRA event with None event type: {}".format(payload) logging.warning(message) return json_error(_("Event is not given by JIRA")) else: if not settings.TEST_SUITE: logging.warning("Got JIRA event type we don't support: {}".format(event)) return json_error(_("Got JIRA event type we don't support: {}".format(event))) check_send_message(user_profile, client, "stream", [stream], subject, content) return json_success()
def api_heroku_webhook(request, user_profile, client, stream=REQ(default="heroku"), head=REQ(), app=REQ(), user=REQ(), url=REQ(), git_log=REQ()): # type: (HttpRequest, UserProfile, Client, Text, Text, Text, Text, Text, Text) -> HttpResponse template = "{} deployed version {} of [{}]({})\n> {}" content = template.format(user, head, app, url, git_log) check_send_message(user_profile, client, "stream", [stream], app, content) return json_success()
def api_yo_app_webhook(request, user_profile, email=REQ(default=None), username=REQ(default='Yo Bot'), topic=REQ(default=None), user_ip=REQ(default=None)): # type: (HttpRequest, UserProfile, Optional[str], str, Optional[str], Optional[str]) -> HttpResponse body = ('Yo from %s') % (username,) check_send_message(user_profile, request.client, 'private', [email], topic, body) return json_success()
def api_circleci_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='circleci')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], Text) -> HttpResponse payload = payload['payload'] subject = get_subject(payload) body = get_body(payload) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def send_raw_pagerduty_json(user_profile, stream, message, topic): subject = topic or 'pagerduty' body = ( u'Unknown pagerduty message\n' u'``` py\n' u'%s\n' u'```') % (pprint.pformat(message),) check_send_message(user_profile, get_client('ZulipPagerDutyWebhook'), 'stream', [stream], subject, body)
def api_gitlab_webhook(request, user_profile, client, stream=REQ(default='gitlab'), payload=REQ(argument_type='body')): # type: (HttpRequest, UserProfile, Client, text_type, Dict[str, Any]) -> HttpResponse event = get_event(request, payload) body = get_body_based_on_event(event)(payload) subject = get_subject_based_on_event(event, payload) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def send_message_for_event(event, user_profile, client, stream): # type: (Dict[str, Any], UserProfile, Client, str) -> None try: event_type = get_event_type(event) subject = SUBJECT_TEMPLATE.format(service_url=event['check']['url']) body = EVENT_TYPE_BODY_MAPPER[event_type](event) except KeyError as e: return json_error(_("Missing key {} in JSON").format(str(e))) check_send_message(user_profile, client, 'stream', [stream], subject, body)
def send_raw_pagerduty_json(user_profile, client, stream, message, topic): # type: (UserProfile, Client, six.text_type, Dict[str, Any], six.text_type) -> None subject = topic or 'pagerduty' body = ( u'Unknown pagerduty message\n' u'``` py\n' u'%s\n' u'```') % (pprint.pformat(message),) check_send_message(user_profile, client, 'stream', [stream], subject, body)
def send_raw_pagerduty_json(user_profile, client, stream, message, topic): # type: (UserProfile, Client, Text, Dict[str, Any], Text) -> None subject = topic or 'pagerduty' body = ( u'Unknown pagerduty message\n' u'```\n' u'%s\n' u'```') % (ujson.dumps(message, indent=2),) check_send_message(user_profile, client, 'stream', [stream], subject, body)
def api_sentry_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='sentry')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], str) -> HttpResponse subject = "{}".format(payload.get('project_name')) body = "New {} [issue]({}): {}.".format(payload.get('level').upper(), payload.get('url'), payload.get('message')) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def api_github_webhook( request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='github'), branches=REQ(default=None)): # type: (HttpRequest, UserProfile, Dict[str, Any], Text, Text) -> 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_message(user_profile, request.client, 'stream', [stream], subject, body) return json_success()
def api_zapier_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='zapier')): # type: (HttpRequest, UserProfile, Dict[str, Any], str) -> 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_message(user_profile, request.client, "stream", [stream], subject, content) return json_success()
def api_freshdesk_webhook(request, user_profile, stream=REQ(default='')): try: payload = ujson.loads(request.body) ticket_data = payload["freshdesk_webhook"] except ValueError: return json_error("Malformed JSON input") required_keys = [ "triggered_event", "ticket_id", "ticket_url", "ticket_type", "ticket_subject", "ticket_description", "ticket_status", "ticket_priority", "requester_name", "requester_email", ] for key in required_keys: if ticket_data.get(key) is None: logging.warning("Freshdesk webhook error. Payload was:") logging.warning(request.body) return json_error("Missing key %s in JSON" % (key, )) try: stream = request.GET['stream'] except (AttributeError, KeyError): stream = 'freshdesk' ticket = TicketDict(ticket_data) subject = "#%s: %s" % (ticket.id, ticket.subject) try: event_info = parse_freshdesk_event(ticket.triggered_event) except ValueError: return json_error("Malformed event %s" % (ticket.triggered_event, )) if event_info[1] == "created": content = format_freshdesk_ticket_creation_message(ticket) elif event_info[0] == "note_type": content = format_freshdesk_note_message(ticket, event_info) elif event_info[0] in ("status", "priority"): content = format_freshdesk_property_change_message(ticket, event_info) else: # Not an event we know handle; do nothing. return json_success() check_send_message(user_profile, get_client("ZulipFreshdeskWebhook"), "stream", [stream], subject, content) return json_success()
def api_pingdom_webhook(request, user_profile, stream=REQ(default='pingdom')): payload = ujson.loads(request.body) check_type = get_check_type(payload) if check_type in SUPPORTED_CHECK_TYPES: subject = get_subject_for_http_request(payload) body = get_body_for_http_request(payload) else: return json_error('Unsupported check_type: {check_type}'.format(check_type=check_type)) check_send_message(user_profile, get_client('ZulipPingdomWebhook'), 'stream', [stream], subject, body) return json_success()
def api_yo_app_webhook(request, user_profile, client, email=REQ(default=None), username=REQ(default='Yo Bot'), topic=REQ(default=None), user_ip=REQ(default=None)): # type: (HttpRequest, UserProfile, Client, Optional[str], str, Optional[str], Optional[str]) -> HttpResponse body = ('Yo from %s') % (username, ) check_send_message(user_profile, client, 'private', [email], topic, body) return json_success()
def send_response_message( bot_id: int, message_info: Dict[str, Any], response_data: Dict[str, Any] ) -> None: """ bot_id is the user_id of the bot sending the response message_info is used to address the message and should have these fields: type - "stream" or "private" display_recipient - like we have in other message events topic - see get_topic_from_message_info response_data is what the bot wants to send back and has these fields: content - raw Markdown content for Zulip to render WARNING: This function sends messages bypassing the stream access check for the bot - so use with caution to not call this in codepaths that might let someone send arbitrary messages to any stream through this. """ message_type = message_info["type"] display_recipient = message_info["display_recipient"] try: topic_name: Optional[str] = get_topic_from_message_info(message_info) except KeyError: topic_name = None bot_user = get_user_profile_by_id(bot_id) realm = bot_user.realm client = get_client("OutgoingWebhookResponse") content = response_data.get("content") assert content widget_content = response_data.get("widget_content") if message_type == "stream": message_to = [display_recipient] elif message_type == "private": message_to = [recipient["email"] for recipient in display_recipient] else: raise JsonableError(_("Invalid message type")) check_send_message( sender=bot_user, client=client, message_type_name=message_type, message_to=message_to, topic_name=topic_name, message_content=content, widget_content=widget_content, realm=realm, skip_stream_access_check=True, )
def api_sentry_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='sentry')): # type: (HttpRequest, UserProfile, Dict[str, Any], str) -> HttpResponse subject = "{}".format(payload.get('project_name')) body = "New {} [issue]({}): {}.".format(payload['level'].upper(), payload.get('url'), payload.get('message')) check_send_message(user_profile, request.client, 'stream', [stream], subject, body) return json_success()
def api_bitbucket2_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='bitbucket')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], str) -> HttpResponse try: type = get_type(request, payload) subject = get_subject_based_on_type(payload, type) body = get_body_based_on_type(type)(payload) except KeyError as e: return json_error(_("Missing key {} in JSON").format(str(e))) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def api_solano_webhook(request, user_profile, client, stream=REQ(default='solano labs'), topic=REQ(default='build update'), payload=REQ(argument_type='body')): # type: (HttpRequest, UserProfile, Client, str, str, Dict[str, Any]) -> HttpResponse try: try: author = payload['committers'][0] except KeyError: author = 'Unknown' status = payload['status'] build_log = payload['url'] repository = payload['repository']['url'] commit_id = payload['commit_id'] except KeyError as e: return json_error(_('Missing key {} in JSON').format(str(e))) good_status = ['passed'] bad_status = ['failed', 'error'] neutral_status = ['running'] emoji = '' if status in good_status: emoji = ':thumbsup:' elif status in bad_status: emoji = ':thumbsdown:' elif status in neutral_status: emoji = ':arrows_counterclockwise:' else: emoji = "(No emoji specified for status '%s'.)" % (status) template = (u'Author: {}\n' u'Commit: [{}]({})\n' u'Build status: {} {}\n' u'[Build Log]({})') # If the service is not one of the following, the url is of the repository home, not the individual # commit itself. commit_url = repository.split('@')[1] if 'github' in repository: commit_url += '/commit/{}'.format(commit_id) elif 'bitbucket' in repository: commit_url += '/commits/{}'.format(commit_id) elif 'gitlab' in repository: commit_url += '/pipelines/{}'.format(commit_id) body = template.format(author, commit_id, commit_url, status, emoji, build_log) check_send_message(user_profile, client, 'stream', [stream], topic, body) return json_success()
def api_pingdom_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='pingdom')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], Text) -> HttpResponse check_type = get_check_type(payload) if check_type in SUPPORTED_CHECK_TYPES: subject = get_subject_for_http_request(payload) body = get_body_for_http_request(payload) else: return json_error(_('Unsupported check_type: {check_type}').format(check_type=check_type)) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def api_taiga_webhook(request, user_profile, client, message=REQ(argument_type='body'), stream=REQ(default='taiga'), topic=REQ(default='General')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], Text, Text) -> 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)) check_send_message(user_profile, client, 'stream', [stream], topic, content) return json_success()
def api_github_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='github'), branches=REQ(default=None)): # type: (HttpRequest, UserProfile, Dict[str, Any], Text, Text) -> 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_message(user_profile, request.client, 'stream', [stream], subject, body) return json_success()
def api_semaphore_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='builds')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], str) -> HttpResponse # semaphore only gives the last commit, even if there were multiple commits # since the last build try: branch_name = payload["branch_name"] project_name = payload["project_name"] result = payload["result"] event = payload["event"] commit_id = payload["commit"]["id"] commit_url = payload["commit"]["url"] author_email = payload["commit"]["author_email"] message = payload["commit"]["message"] except KeyError as e: return json_error(_("Missing key %s in JSON") % (str(e), )) if event == "build": try: build_url = payload["build_url"] build_number = payload["build_number"] except KeyError as e: return json_error(_("Missing key %s in JSON") % (str(e), )) content = u"[build %s](%s): %s\n" % (build_number, build_url, result) elif event == "deploy": try: build_url = payload["build_html_url"] build_number = payload["build_number"] deploy_url = payload["html_url"] deploy_number = payload["number"] server_name = payload["server_name"] except KeyError as e: return json_error(_("Missing key %s in JSON") % (str(e), )) content = u"[deploy %s](%s) of [build %s](%s) on server %s: %s\n" % \ (deploy_number, deploy_url, build_number, build_url, server_name, result) else: # should never get here content = u"%s: %s\n" % (event, result) content += "!avatar(%s) [`%s`](%s): %s" % (author_email, commit_id[:7], commit_url, message) subject = u"%s/%s" % (project_name, branch_name) check_send_message(user_profile, client, "stream", [stream], subject, content) return json_success()
def api_airbrake_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='airbrake')): # type: (HttpRequest, UserProfile, Client, Dict[str, Any], six.text_type) -> HttpResponse try: subject = get_subject(payload) body = get_body(payload) except KeyError as e: return json_error(_("Missing key {} in JSON").format(e.message)) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def api_codeship_webhook(request, user_profile, client, payload=REQ(argument_type='body'), stream=REQ(default='codeship')): try: payload = payload['build'] subject = get_subject_for_http_request(payload) body = get_body_for_http_request(payload) except KeyError as e: return json_error("Missing key {} in JSON".format(e.message)) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def api_hellosign_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='hellosign'), topic=REQ(default=None)): # type: (HttpRequest, UserProfile, Dict[str, Dict[str, Any]], text_type, text_type) -> 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_message(user_profile, request.client, 'stream', [stream], topic, body) return json_success()
def api_codeship_webhook(request, user_profile, stream=REQ(default='codeship')): try: payload = ujson.loads(request.body)['build'] subject = get_subject_for_http_request(payload) body = get_body_for_http_request(payload) except KeyError as e: return json_error("Missing key {} in JSON".format(e.message)) except ValueError as e: return json_error("Malformed JSON") check_send_message(user_profile, get_client('ZulipCodeshipWebhook'), 'stream', [stream], subject, body) return json_success()
def api_trello_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='trello')): # type: (HttpRequest, UserProfile, Mapping[str, Any], Text) -> HttpResponse payload = ujson.loads(request.body) action_type = payload['action'].get('type') try: message = get_subject_and_body(payload, action_type) if message is None: return json_success() else: subject, body = message except UnsupportedAction: return json_error(_('Unsupported action_type: {action_type}'.format(action_type=action_type))) check_send_message(user_profile, request.client, 'stream', [stream], subject, body) return json_success()
def send_response_message(bot_id: str, message: Dict[str, Any], response_message_content: Text) -> None: recipient_type_name = message['type'] bot_user = get_user_profile_by_id(bot_id) realm = bot_user.realm if recipient_type_name == 'stream': recipients = [message['display_recipient']] check_send_message(bot_user, get_client("OutgoingWebhookResponse"), recipient_type_name, recipients, message['subject'], response_message_content, realm) elif recipient_type_name == 'private': recipients = [recipient['email'] for recipient in message['display_recipient']] check_send_message(bot_user, get_client("OutgoingWebhookResponse"), recipient_type_name, recipients, None, response_message_content, realm) else: raise JsonableError(_("Invalid message type"))
def api_codeship_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='codeship')): # type: (HttpRequest, UserProfile, Dict[str, Any], str) -> HttpResponse try: payload = payload['build'] subject = get_subject_for_http_request(payload) body = get_body_for_http_request(payload) except KeyError as e: return json_error(_("Missing key {} in JSON").format(str(e))) check_send_message(user_profile, request.client, 'stream', [stream], subject, body) return json_success()
def api_heroku_webhook(request, user_profile, stream=REQ(default="heroku"), head=REQ(), app=REQ(), user=REQ(), url=REQ(), git_log=REQ()): # type: (HttpRequest, UserProfile, Text, Text, Text, Text, Text, Text) -> HttpResponse template = "{} deployed version {} of [{}]({})\n> {}" content = template.format(user, head, app, url, git_log) check_send_message(user_profile, request.client, "stream", [stream], app, content) return json_success()
def api_appfollow_webhook(request, user_profile, client, stream=REQ(default="appfollow"), payload=REQ(argument_type="body")): # type: (HttpRequest, UserProfile, Client, Text, Dict[str, Any]) -> HttpResponse try: message = payload["text"] except KeyError: return json_error(_("Missing 'text' argument in JSON")) app_name = re.search('\A(.+)', message).group(0) check_send_message(user_profile, client, "stream", [stream], app_name, convert_markdown(message)) return json_success()
def api_transifex_webhook(request, user_profile, client, project=REQ(), resource=REQ(), language=REQ(), translated=REQ(default=None), reviewed=REQ(default=None), stream=REQ(default='transifex')): # type: (HttpRequest, UserProfile, Client, str, str, str, Optional[int], Optional[int], str) -> HttpResponse subject = "{} in {}".format(project, language) if translated: body = "Resource {} fully translated.".format(resource) elif reviewed: body = "Resource {} fully reviewed.".format(resource) else: return json_error(_("Transifex wrong request")) check_send_message(user_profile, client, 'stream', [stream], subject, body) return json_success()
def api_freshdesk_webhook(request, user_profile, payload=REQ(argument_type='body'), stream=REQ(default='freshdesk')): # type: (HttpRequest, UserProfile, Dict[str, Any], text_type) -> HttpResponse ticket_data = payload["freshdesk_webhook"] required_keys = [ "triggered_event", "ticket_id", "ticket_url", "ticket_type", "ticket_subject", "ticket_description", "ticket_status", "ticket_priority", "requester_name", "requester_email", ] for key in required_keys: if ticket_data.get(key) is None: logging.warning("Freshdesk webhook error. Payload was:") logging.warning(request.body) return json_error(_("Missing key %s in JSON") % (key, )) ticket = TicketDict(ticket_data) subject = "#%s: %s" % (ticket.id, ticket.subject) try: event_info = parse_freshdesk_event(ticket.triggered_event) except ValueError: return json_error(_("Malformed event %s") % (ticket.triggered_event, )) if event_info[1] == "created": content = format_freshdesk_ticket_creation_message(ticket) elif event_info[0] == "note_type": content = format_freshdesk_note_message(ticket, event_info) elif event_info[0] in ("status", "priority"): content = format_freshdesk_property_change_message(ticket, event_info) else: # Not an event we know handle; do nothing. return json_success() check_send_message(user_profile, get_client("ZulipFreshdeskWebhook"), "stream", [stream], subject, content) return json_success()
def send_response_message(bot_id: str, message_info: Dict[str, Any], response_data: Dict[str, Any]) -> None: """ bot_id is the user_id of the bot sending the response message_info is used to address the message and should have these fields: type - "stream" or "private" display_recipient - like we have in other message events topic - see get_topic_from_message_info response_data is what the bot wants to send back and has these fields: content - raw markdown content for Zulip to render """ message_type = message_info['type'] display_recipient = message_info['display_recipient'] try: topic_name = get_topic_from_message_info(message_info) except KeyError: topic_name = None bot_user = get_user_profile_by_id(bot_id) realm = bot_user.realm client = get_client('OutgoingWebhookResponse') content = response_data.get('content') if not content: raise JsonableError(_("Missing content")) widget_content = response_data.get('widget_content') if message_type == 'stream': message_to = [display_recipient] elif message_type == 'private': message_to = [recipient['email'] for recipient in display_recipient] else: raise JsonableError(_("Invalid message type")) check_send_message( sender=bot_user, client=client, message_type_name=message_type, message_to=message_to, topic_name=topic_name, message_content=content, widget_content=widget_content, realm=realm, )
def send_message(self, sender_name, raw_recipients, message_type, content=u"test content", subject=u"test", **kwargs): # type: (Text, Union[Text, List[Text]], int, Text, Text, **Any) -> int sender = get_user_profile_by_email(sender_name) if message_type in [Recipient.PERSONAL, Recipient.HUDDLE]: message_type_name = "private" else: message_type_name = "stream" if isinstance(raw_recipients, six.string_types): recipient_list = [raw_recipients] else: recipient_list = raw_recipients (sending_client, _) = Client.objects.get_or_create(name="test suite") return check_send_message(sender, sending_client, message_type_name, recipient_list, subject, content, forged=False, forged_timestamp=None, forwarder_user_profile=sender, realm=sender.realm, **kwargs)
def fake_message_sender(event): # type: (Dict[str, Any]) -> None log_data = dict() # type: Dict[str, Any] record_request_start_data(log_data) req = event['request'] try: sender = get_user_profile_by_id(event['server_meta']['user_id']) client = get_client(req['client']) msg_id = check_send_message(sender, client, req['type'], extract_recipients(req['to']), req['subject'], req['content'], local_id=req.get('local_id', None), sender_queue_id=req.get('queue_id', None)) resp = {"result": "success", "msg": "", "id": msg_id} except JsonableError as e: resp = {"result": "error", "msg": str(e)} server_meta = event['server_meta'] server_meta.update({ 'worker_log_data': log_data, 'time_request_finished': time.time() }) result = { 'response': resp, 'req_id': event['req_id'], 'server_meta': server_meta } respond_send_message(result)
def api_taiga_webhook(request, user_profile, client, message=REQ(argument_type='body'), stream=REQ(default='taiga'), topic=REQ(default='General')): parsed_events = parse_message(message) content = "" for event in parsed_events: content += generate_content(event) + '\n' check_send_message(user_profile, client, 'stream', [stream], topic, content) return json_success()
def send_response_message(bot_id, message, response_message_content): # type: (str, Dict[str, Any], Text) -> None recipient_type_name = message['type'] bot_user = get_user_profile_by_id(bot_id) realm = get_realm_by_email_domain(message['sender_email']) if recipient_type_name == 'stream': recipients = [message['display_recipient']] check_send_message(bot_user, get_client("OutgoingWebhookResponse"), recipient_type_name, recipients, message['subject'], response_message_content, realm, forwarder_user_profile=bot_user) else: # Private message; only send if the bot is there in the recipients recipients = [recipient['email'] for recipient in message['display_recipient']] if bot_user.email in recipients: check_send_message(bot_user, get_client("OutgoingWebhookResponse"), recipient_type_name, recipients, message['subject'], response_message_content, realm, forwarder_user_profile=bot_user)
def send_message(self, sender_name, recipient_list, message_type, content="test content", subject="test", **kwargs): # type: (str, Iterable[str], int, str, str, **Any) -> int sender = get_user_profile_by_email(sender_name) if message_type == Recipient.PERSONAL: message_type_name = "private" else: message_type_name = "stream" if isinstance(recipient_list, six.string_types): recipient_list = [recipient_list] (sending_client, _) = Client.objects.get_or_create(name="test suite") return check_send_message(sender, sending_client, message_type_name, recipient_list, subject, content, forged=False, forged_timestamp=None, forwarder_user_profile=sender, realm=sender.realm, **kwargs)