From e552307511cdca4a794309f7318353fe9545832d Mon Sep 17 00:00:00 2001 From: Luke Faraone Date: Thu, 17 Oct 2013 16:55:09 -0400 Subject: [PATCH] Send feedback to a queue to be forwarded to staging. (imported from commit 4a9a1bfc6c95763a816263a726cc61b3ca90bf15) --- zerver/lib/actions.py | 7 +++++ zerver/worker/queue_processors.py | 23 +++++++++++++++ zilencer/urls/__init__.py | 0 zilencer/urls/api.py | 6 ++++ zilencer/views.py | 48 +++++++++++++++++++++++++++++++ zproject/local_settings.py | 5 ++++ zproject/urls.py | 6 ++++ 7 files changed, 95 insertions(+) create mode 100644 zilencer/urls/__init__.py create mode 100644 zilencer/urls/api.py create mode 100644 zilencer/views.py diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index 27ae0c69f7..9b2c192c69 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -342,6 +342,13 @@ def do_send_messages(messages): if message['stream'].invite_only: data['invite_only'] = True tornado_callbacks.send_notification(data) + if message['message'].recipient.type == Recipient.PERSONAL and \ + message['recipients'][0].email == "feedback@zulip.com": + queue_json_publish( + 'feedback_messages', + message['message'].to_dict(apply_markdown=False), + lambda x: None + ) # Note that this does not preserve the order of message ids # returned. In practice, this shouldn't matter, as we only diff --git a/zerver/worker/queue_processors.py b/zerver/worker/queue_processors.py index be1cae91cb..cb4dc9e5c0 100644 --- a/zerver/worker/queue_processors.py +++ b/zerver/worker/queue_processors.py @@ -15,12 +15,14 @@ from zerver.decorator import JsonableError from confirmation.models import Confirmation import os +import sys import ujson import traceback from collections import defaultdict import time import datetime import logging +import simplejson def assign_queue(queue_name): def decorate(clazz): @@ -159,6 +161,27 @@ class MissedMessageWorker(QueueProcessingWorker): # of messages time.sleep(2 * 60) +@assign_queue('feedback_messages') +class FeedbackBot(QueueProcessingWorker): + def start(self): + sys.path.append(os.path.join(os.path.dirname(__file__), '../../api')) + import zulip + self.staging_client = zulip.Client( + email=settings.DEPLOYMENT_ROLE_NAME, + api_key=settings.DEPLOYMENT_ROLE_KEY, + verbose=True, + site=settings.FEEDBACK_TARGET) + self.staging_client._register( + 'forward_feedback', + method='POST', + url='deployments/feedback', + make_request=(lambda request: {'message': simplejson.dumps(request)}), + ) + QueueProcessingWorker.start(self) + + def consume(self, ch, method, properties, event): + self.staging_client.forward_feedback(event) + @assign_queue('slow_queries') class SlowQueryWorker(QueueProcessingWorker): def start(self): diff --git a/zilencer/urls/__init__.py b/zilencer/urls/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/zilencer/urls/api.py b/zilencer/urls/api.py new file mode 100644 index 0000000000..f444a1cc4d --- /dev/null +++ b/zilencer/urls/api.py @@ -0,0 +1,6 @@ +from django.conf.urls import patterns, url, include + +urlpatterns = patterns('zilencer.views', + url('^feedback$', 'rest_dispatch', + {'POST': 'submit_feedback'}), +) diff --git a/zilencer/views.py b/zilencer/views.py new file mode 100644 index 0000000000..5152948bd2 --- /dev/null +++ b/zilencer/views.py @@ -0,0 +1,48 @@ +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt, csrf_protect + +from zerver.models import get_realm +from zerver.lib.actions import internal_send_message +from zerver.decorator import has_request_variables, REQ, json_to_dict +from zilencer.models import Deployment + +from zerver.lib.rest import rest_dispatch as _rest_dispatch +rest_dispatch = csrf_exempt((lambda request, *args, **kwargs: _rest_dispatch(request, globals(), *args, **kwargs))) + + +def get_ticket_number(): + fn = '/var/tmp/.feedback-bot-ticket-number' + try: + ticket_number = int(open(fn).read()) + 1 + except: + ticket_number = 1 + open(fn, 'w').write('%d' % ticket_number) + return ticket_number + +@has_request_variables +def submit_feedback(request, deployment, message=REQ(converter=json_to_dict)): + domainish = message["sender_domain"] + if get_realm("zulip.com") not in deployment.realms.all(): + domainish += " via " + deployment.realms.get(0).domain + subject = "feedback: %s (%s)" % (message["sender_email"], domainish) + + if len(subject) > 60: + subject = subject[:57].rstrip() + "..." + + + ticket_number = get_ticket_number() + content = '@support, Please ack this new request.' + content += '\n~~~' + content += '\nticket Z%03d' % (ticket_number,) + content += '\nsender: %s' % (message['sender_full_name'],) + content += '\nemail: %s' % (message['sender_email'],) + if 'sender_domain' in message: + content += '\nrealm: %s' % (message['sender_domain'],) + content += '\n~~~' + + content += '\n\n' + content += message['content'] + + internal_send_message("feedback@zulip.com", "stream", "support", subject, content) + + return HttpResponse(message['sender_email']) diff --git a/zproject/local_settings.py b/zproject/local_settings.py index 9b0c81a213..6f60d1990c 100644 --- a/zproject/local_settings.py +++ b/zproject/local_settings.py @@ -65,6 +65,11 @@ else: EMBEDLY_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +if DEPLOYED: + FEEDBACK_TARGET="https://staging.zulip.com/api" +else: + FEEDBACK_TARGET="http://localhost:9991/api" + # For now, LOCALSERVER is only testing, so write to our test buckets if DEPLOYED and not LOCALSERVER: S3_KEY="xxxxxxxxxxxxxxxxxxxx" diff --git a/zproject/urls.py b/zproject/urls.py index 8abe401763..02d71583a1 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -211,7 +211,13 @@ v1_api_and_json_patterns = patterns('zerver.views', {'GET': 'get_updates_backend'}), url(r'^events$', 'rest_dispatch', {'GET': 'get_events_backend'}), + ) +if not settings.LOCALSERVER: + v1_api_and_json_patterns += patterns('', + # Still scoped to api/v1/, but under a different project + url(r'^deployments/', include('zilencer.urls.api')), + ) urlpatterns += patterns('zerver.tornadoviews',