|
@@ -25,6 +25,12 @@ from desktop.conf import ENABLE_GIST_PREVIEW
|
|
|
from desktop.lib.django_util import login_notrequired, JsonResponse
|
|
from desktop.lib.django_util import login_notrequired, JsonResponse
|
|
|
from desktop.lib.exceptions_renderable import PopupException
|
|
from desktop.lib.exceptions_renderable import PopupException
|
|
|
from desktop.models import Document2, _get_gist_document
|
|
from desktop.models import Document2, _get_gist_document
|
|
|
|
|
+from desktop.auth.backend import rewrite_user
|
|
|
|
|
+
|
|
|
|
|
+from notebook.api import _fetch_result_data, _check_status, _execute_notebook
|
|
|
|
|
+from notebook.models import MockRequest
|
|
|
|
|
+
|
|
|
|
|
+from useradmin.models import User
|
|
|
|
|
|
|
|
from django.http import HttpResponse
|
|
from django.http import HttpResponse
|
|
|
from django.utils.translation import ugettext as _
|
|
from django.utils.translation import ugettext as _
|
|
@@ -32,6 +38,11 @@ from django.views.decorators.csrf import csrf_exempt
|
|
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
+try:
|
|
|
|
|
+ from prettytable import PrettyTable
|
|
|
|
|
+except ImportError:
|
|
|
|
|
+ raise ImportError("prettytable module not found")
|
|
|
|
|
+
|
|
|
SLACK_VERIFICATION_TOKEN = conf.SLACK.SLACK_VERIFICATION_TOKEN.get()
|
|
SLACK_VERIFICATION_TOKEN = conf.SLACK.SLACK_VERIFICATION_TOKEN.get()
|
|
|
SLACK_BOT_USER_TOKEN = conf.SLACK.SLACK_BOT_USER_TOKEN.get()
|
|
SLACK_BOT_USER_TOKEN = conf.SLACK.SLACK_BOT_USER_TOKEN.get()
|
|
|
|
|
|
|
@@ -89,6 +100,7 @@ def handle_on_message(channel_id, bot_id, text, user_id):
|
|
|
if not response['ok']:
|
|
if not response['ok']:
|
|
|
raise PopupException(_("Error posting message"), detail=response["error"])
|
|
raise PopupException(_("Error posting message"), detail=response["error"])
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def handle_on_link_shared(channel_id, message_ts, links):
|
|
def handle_on_link_shared(channel_id, message_ts, links):
|
|
|
for item in links:
|
|
for item in links:
|
|
|
path = urlsplit(item['url'])[2]
|
|
path = urlsplit(item['url'])[2]
|
|
@@ -97,25 +109,67 @@ def handle_on_link_shared(channel_id, message_ts, links):
|
|
|
try:
|
|
try:
|
|
|
if path == '/hue/editor' and id_type == 'editor':
|
|
if path == '/hue/editor' and id_type == 'editor':
|
|
|
doc = Document2.objects.get(id=qid)
|
|
doc = Document2.objects.get(id=qid)
|
|
|
|
|
+ doc_type = 'Editor'
|
|
|
elif path == '/hue/gist' and id_type == 'uuid' and ENABLE_GIST_PREVIEW.get():
|
|
elif path == '/hue/gist' and id_type == 'uuid' and ENABLE_GIST_PREVIEW.get():
|
|
|
doc = _get_gist_document(uuid=qid)
|
|
doc = _get_gist_document(uuid=qid)
|
|
|
|
|
+ doc_type = 'Gist'
|
|
|
else:
|
|
else:
|
|
|
raise PopupException(_("Cannot unfurl link"))
|
|
raise PopupException(_("Cannot unfurl link"))
|
|
|
except Document2.DoesNotExist:
|
|
except Document2.DoesNotExist:
|
|
|
msg = "Document with {key}={value} does not exist".format(key='uuid' if id_type == 'uuid' else 'id', value=qid)
|
|
msg = "Document with {key}={value} does not exist".format(key='uuid' if id_type == 'uuid' else 'id', value=qid)
|
|
|
raise PopupException(_(msg))
|
|
raise PopupException(_(msg))
|
|
|
|
|
|
|
|
- doc_data = json.loads(doc.data)
|
|
|
|
|
- statement = doc_data['snippets'][0]['statement_raw'] if id_type == 'editor' else doc_data['statement_raw']
|
|
|
|
|
- dialect = doc_data['dialect'].capitalize() if id_type == 'editor' else doc.extra.capitalize()
|
|
|
|
|
- created_by = doc.owner.get_full_name() or doc.owner.username
|
|
|
|
|
-
|
|
|
|
|
- payload = _make_unfurl_payload(item['url'], statement, dialect, created_by)
|
|
|
|
|
|
|
+ payload = _make_unfurl_payload(item['url'], id_type, doc, doc_type)
|
|
|
response = slack_client.chat_unfurl(channel=channel_id, ts=message_ts, unfurls=payload)
|
|
response = slack_client.chat_unfurl(channel=channel_id, ts=message_ts, unfurls=payload)
|
|
|
if not response['ok']:
|
|
if not response['ok']:
|
|
|
raise PopupException(_("Cannot unfurl link"), detail=response["error"])
|
|
raise PopupException(_("Cannot unfurl link"), detail=response["error"])
|
|
|
|
|
|
|
|
-def _make_unfurl_payload(url, statement, dialect, created_by):
|
|
|
|
|
|
|
+
|
|
|
|
|
+def query_result(request, notebook):
|
|
|
|
|
+ snippet = notebook['snippets'][0]
|
|
|
|
|
+ snippet['statement'] = notebook['snippets'][0]['statement_raw']
|
|
|
|
|
+
|
|
|
|
|
+ query_execute = _execute_notebook(request, notebook, snippet)
|
|
|
|
|
+
|
|
|
|
|
+ history_uuid = query_execute['history_uuid']
|
|
|
|
|
+ status = _check_status(request, operation_id=history_uuid)
|
|
|
|
|
+ if status['query_status']['status'] == 'available':
|
|
|
|
|
+ response = _fetch_result_data(request, operation_id=history_uuid)
|
|
|
|
|
+
|
|
|
|
|
+ return response['result']
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _make_result_table(result):
|
|
|
|
|
+ meta = []
|
|
|
|
|
+ for field in result['meta']:
|
|
|
|
|
+ meta.append(field['name'])
|
|
|
|
|
+
|
|
|
|
|
+ table = PrettyTable()
|
|
|
|
|
+ table.field_names = meta
|
|
|
|
|
+ table.add_rows(result['data'])
|
|
|
|
|
+ return table
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _make_unfurl_payload(url, id_type, doc, doc_type):
|
|
|
|
|
+ doc_data = json.loads(doc.data)
|
|
|
|
|
+ statement = doc_data['snippets'][0]['statement_raw'] if id_type == 'editor' else doc_data['statement_raw']
|
|
|
|
|
+ dialect = doc_data['dialect'] if id_type == 'editor' else doc.extra
|
|
|
|
|
+ created_by = doc.owner.get_full_name() or doc.owner.username
|
|
|
|
|
+
|
|
|
|
|
+ # Mock request for query execution and fetch result
|
|
|
|
|
+ user = rewrite_user(User.objects.get(username=doc.owner.username))
|
|
|
|
|
+ request = MockRequest(user=user)
|
|
|
|
|
+
|
|
|
|
|
+ if id_type == 'editor':
|
|
|
|
|
+ try:
|
|
|
|
|
+ status = _check_status(request, operation_id=doc_data['uuid'])
|
|
|
|
|
+ if status['query_status']['status'] == 'available':
|
|
|
|
|
+ result = _make_result_table(query_result(request, json.loads(doc.data)))
|
|
|
|
|
+ except:
|
|
|
|
|
+ result = 'Query result has expired or could not be found.'
|
|
|
|
|
+ else:
|
|
|
|
|
+ result = 'Result is not available for Gist.'
|
|
|
|
|
+
|
|
|
payload = {
|
|
payload = {
|
|
|
url: {
|
|
url: {
|
|
|
"color": "#025BA6",
|
|
"color": "#025BA6",
|
|
@@ -124,14 +178,17 @@ def _make_unfurl_payload(url, statement, dialect, created_by):
|
|
|
"type": "section",
|
|
"type": "section",
|
|
|
"text": {
|
|
"text": {
|
|
|
"type": "mrkdwn",
|
|
"type": "mrkdwn",
|
|
|
- "text": "\n*<{}|Hue - SQL Editor>*".format(url)
|
|
|
|
|
|
|
+ "text": "\n*<{}|Hue - SQL {}>*".format(url, doc_type)
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ {
|
|
|
|
|
+ "type": "divider"
|
|
|
|
|
+ },
|
|
|
{
|
|
{
|
|
|
"type": "section",
|
|
"type": "section",
|
|
|
"text": {
|
|
"text": {
|
|
|
"type": "mrkdwn",
|
|
"type": "mrkdwn",
|
|
|
- "text": statement if len(statement) < 150 else (statement[:150] + '...')
|
|
|
|
|
|
|
+ "text": "*Statement:*\n```{}```".format(statement if len(statement) < 150 else (statement[:150] + '...'))
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
@@ -143,15 +200,24 @@ def _make_unfurl_payload(url, statement, dialect, created_by):
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
"type": "mrkdwn",
|
|
"type": "mrkdwn",
|
|
|
- "text": "*Created By:*\n{}".format(created_by)
|
|
|
|
|
|
|
+ "text": "*Created by:*\n{}".format(created_by)
|
|
|
}
|
|
}
|
|
|
]
|
|
]
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "type": "section",
|
|
|
|
|
+ "text": {
|
|
|
|
|
+ "type": "mrkdwn",
|
|
|
|
|
+ "text": "*Query result:*\n```{}```".format(result),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
]
|
|
]
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return payload
|
|
return payload
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def say_hi_user(channel_id, user_id):
|
|
def say_hi_user(channel_id, user_id):
|
|
|
"""
|
|
"""
|
|
|
Sends Hi<user_id> message in a specific channel.
|
|
Sends Hi<user_id> message in a specific channel.
|