diff --git a/static/images/integrations/flock/001.png b/static/images/integrations/flock/001.png new file mode 100644 index 0000000000..496f52f1a0 Binary files /dev/null and b/static/images/integrations/flock/001.png differ diff --git a/static/images/integrations/logos/flock.png b/static/images/integrations/logos/flock.png new file mode 100644 index 0000000000..b96bd2803b Binary files /dev/null and b/static/images/integrations/logos/flock.png differ diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py index f7266d201f..1ba2b0cd99 100644 --- a/zerver/lib/integrations.py +++ b/zerver/lib/integrations.py @@ -293,6 +293,7 @@ WEBHOOK_INTEGRATIONS = [ stream_name='desk' ), WebhookIntegration('dropbox', ['productivity'], display_name='Dropbox'), + WebhookIntegration('flock', ['customer-support'], display_name='Flock'), WebhookIntegration('freshdesk', ['customer-support']), WebhookIntegration('front', ['customer-support'], display_name='Front'), GithubIntegration( diff --git a/zerver/webhooks/flock/__init__.py b/zerver/webhooks/flock/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/zerver/webhooks/flock/doc.md b/zerver/webhooks/flock/doc.md new file mode 100644 index 0000000000..7277c099f0 --- /dev/null +++ b/zerver/webhooks/flock/doc.md @@ -0,0 +1,17 @@ +Get Zulip notifications from your Flock channels. + +1. {!create-stream.md!} + +1. {!create-bot-construct-url-indented.md!} + +1. Click on **Apps** in the bottom-right corner. + Click on **Admin Panel**, and click on **Webhooks**. + Next to **Outgoing Webhook**, click on **Add**. + +1. Set **Send messages from a channel** to the channel you'd like to be notified about. + Set **Name that the webhook will post as** to a name of your choice, such as `Zulip`. + Set **Callback URL** to the URL created above, and click **Save Settings**. + +{!congrats.md!} + +![](/static/images/integrations/flock/001.png) diff --git a/zerver/webhooks/flock/fixtures/messages.json b/zerver/webhooks/flock/fixtures/messages.json new file mode 100644 index 0000000000..acea1faa87 --- /dev/null +++ b/zerver/webhooks/flock/fixtures/messages.json @@ -0,0 +1,11 @@ +{ + "id": "1519889547187_0", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "text": "This is the welcome message!", + "timestamp": "2018-03-01T07:32:25.238Z", + "timestampInMillis": 1519889545238, + "uid": "1519889545238-gg8-m203", + "onBehalfOf": "", + "visibleTo": [] +} diff --git a/zerver/webhooks/flock/fixtures/note.json b/zerver/webhooks/flock/fixtures/note.json new file mode 100644 index 0000000000..2d7e8f22a6 --- /dev/null +++ b/zerver/webhooks/flock/fixtures/note.json @@ -0,0 +1,26 @@ +{ + "attachments": [ + { + "appId": "bd05fb5b1e39e29b396e03c2efe053196e3b9458", + "title": "NoteTitle", + "forward": true, + "views": { + "widget": { + "src": "https://apps.flock.co:443/flock-notes/notes/8a0fc0c2-e567-4685-a7a7-883898da47c3/preview", + "width": 0, + "height": 65 + } + } + } + ], + "id": "Amreh", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "notification": "Shared a note", + "text": "", + "appId": "bd05fb5b1e39e29b396e03c2efe053196e3b9458", + "timestamp": "2018-03-01T08:16:08.335Z", + "timestampInMillis": 1519892168335, + "uid": "1519892168335-y7J-m203", + "onBehalfOf": "" +} diff --git a/zerver/webhooks/flock/fixtures/pinned.json b/zerver/webhooks/flock/fixtures/pinned.json new file mode 100644 index 0000000000..64788bb27d --- /dev/null +++ b/zerver/webhooks/flock/fixtures/pinned.json @@ -0,0 +1,17 @@ +{ + "id": "SMzzJ", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "notification": "Rishabh rawat pinned an item to the conversation", + "flockml": "Rishabh rawat pinned an item to this conversation. You can access it via the Files App.", + "text": "", + "sendAs": { + "name": "Pinner Bot", + "profileImage": "https://apps-static.flock.co/smartbar/bot-icon.png" + }, + "appId": "6937451c-edbf-4ecb-b715-1e26574b5168", + "timestamp": "2018-03-01T07:49:06.284Z", + "timestampInMillis": 1519890546284, + "uid": "1519890546284-f3t-m203", + "onBehalfOf": "" +} diff --git a/zerver/webhooks/flock/fixtures/reminder.json b/zerver/webhooks/flock/fixtures/reminder.json new file mode 100644 index 0000000000..5b92648540 --- /dev/null +++ b/zerver/webhooks/flock/fixtures/reminder.json @@ -0,0 +1,40 @@ +{ + "attachments": [ + { + "id": "3d5774d9-ec8e-4664-9286-c54d0034e401", + "appId": "905f9943396442448b5d259d72c6d5fe", + "title": "FlockBot undefined in mychannel: Hey ", + "color": "#efb80b", + "forward": false, + "buttons": [ + { + "name": "Snooze for me", + "icon": "https://apps-static.flock.co/reminder/snooze.svg", + "action": { + "mobileType": "modal", + "type": "openWidget", + "desktopType": "modal", + "url": "https://apps-static.flock.co/reminder3/production/html/snooze.html", + "width": 570, + "height": 270, + "sendContext": false + }, + "id": "22841" + } + ] + } + ], + "id": "wzXJN", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:Bu4v779hlh4uuug5", + "text": "Rishabh rawat wanted me to remind All", + "sendAs": { + "name": "Reminder Bot", + "profileImage": "https://apps-static.flock.co/reminder/reminder-bot.png" + }, + "appId": "905f9943396442448b5d259d72c6d5fe", + "timestamp": "2018-03-01T08:00:03.587Z", + "timestampInMillis": 1519891203587, + "uid": "1519891203587-Nhj-m201", + "onBehalfOf": "u:9qehqo3ixo3t93e3" +} diff --git a/zerver/webhooks/flock/fixtures/reply.json b/zerver/webhooks/flock/fixtures/reply.json new file mode 100644 index 0000000000..a21e26da58 --- /dev/null +++ b/zerver/webhooks/flock/fixtures/reply.json @@ -0,0 +1,20 @@ +{ + "attachments": [ + { + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "title": "in reply to Rishabh R", + "description": "This is the welcome message!", + "color": "#0BBE51", + "forward": false + } + ], + "id": "BPsjQ", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "text": "It's interesting how high productivity will go...", + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "timestamp": "2018-03-01T07:44:45.493Z", + "timestampInMillis": 1519890285493, + "uid": "1519890285493-eed-m203", + "onBehalfOf": "" +} diff --git a/zerver/webhooks/flock/fixtures/reply_note.json b/zerver/webhooks/flock/fixtures/reply_note.json new file mode 100644 index 0000000000..37c6664a75 --- /dev/null +++ b/zerver/webhooks/flock/fixtures/reply_note.json @@ -0,0 +1,20 @@ +{ + "attachments": [ + { + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "title": "in reply to Rishabh R", + "description": "NoteTitle", + "color": "#0BBE51", + "forward": false + } + ], + "id": "WPDlW", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "text": "This is reply to Note.", + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "timestamp": "2018-03-01T08:16:57.793Z", + "timestampInMillis": 1519892217793, + "uid": "1519892217793-lt2-m203", + "onBehalfOf": "" +} diff --git a/zerver/webhooks/flock/fixtures/reply_pinned.json b/zerver/webhooks/flock/fixtures/reply_pinned.json new file mode 100644 index 0000000000..33db7482ec --- /dev/null +++ b/zerver/webhooks/flock/fixtures/reply_pinned.json @@ -0,0 +1,20 @@ +{ + "attachments": [ + { + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "title": "in reply to Rishabh R", + "description": "Rishabh rawat pinned an item to this conversation. You can access it via the Files", + "color": "#0BBE51", + "forward": false + } + ], + "id": "QPJia", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "text": "This is reply to pinned message.", + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "timestamp": "2018-03-01T08:11:46.549Z", + "timestampInMillis": 1519891906549, + "uid": "1519891906549-rzZ-m203", + "onBehalfOf": "" +} diff --git a/zerver/webhooks/flock/fixtures/reply_reminder.json b/zerver/webhooks/flock/fixtures/reply_reminder.json new file mode 100644 index 0000000000..0dc4f36002 --- /dev/null +++ b/zerver/webhooks/flock/fixtures/reply_reminder.json @@ -0,0 +1,20 @@ +{ + "attachments": [ + { + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "title": "in reply to Reminders B", + "description": "Rishabh rawat wanted me to remind All", + "color": "#0BBE51", + "forward": false + } + ], + "id": "Oprnr", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "text": "This is a reply to Reminder.", + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "timestamp": "2018-03-01T08:14:17.985Z", + "timestampInMillis": 1519892057985, + "uid": "1519892057985-B1f-m203", + "onBehalfOf": "" +} diff --git a/zerver/webhooks/flock/fixtures/reply_todo.json b/zerver/webhooks/flock/fixtures/reply_todo.json new file mode 100644 index 0000000000..597582e5be --- /dev/null +++ b/zerver/webhooks/flock/fixtures/reply_todo.json @@ -0,0 +1,20 @@ +{ + "attachments": [ + { + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "title": "in reply to To-do bot", + "description": "Study for end term exams.", + "color": "#0BBE51", + "forward": false + } + ], + "id": "WoBGB", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:9qehqo3ixo3t93e3", + "text": "This is a reply to Todo notification.", + "appId": "7d7d0856-f0a1-45bc-a66e-8c9ed504e620", + "timestamp": "2018-03-01T08:13:24.950Z", + "timestampInMillis": 1519892004950, + "uid": "1519892004950-1re-m203", + "onBehalfOf": "" +} diff --git a/zerver/webhooks/flock/fixtures/todo.json b/zerver/webhooks/flock/fixtures/todo.json new file mode 100644 index 0000000000..9bea25f4e3 --- /dev/null +++ b/zerver/webhooks/flock/fixtures/todo.json @@ -0,0 +1,49 @@ +{ + "attachments": [ + { + "id": "todo_attachment", + "appId": "6d0aa37b00944ec0a7426d34ca2df048", + "color": "#2A83Fc", + "views": { + "flockml": "Study for end term exams." + }, + "buttons": [ + { + "name": "View", + "action": { + "mobileType": "modal", + "type": "openWidget", + "desktopType": "sidebar", + "url": "https://apps-static.flock.co/todo/index.html?type=chat&chat&chatName=mychannel&listId=li%3Ac5f13a8a-e90a-4396-b810-1cfe85ef7c31&todoId=to%3Ab4273700-ac8c-44d0-91a3-d13d3d11e500", + "sendContext": false + }, + "id": "view" + }, + { + "name": "Mark as done", + "icon": "https://apps-static.flock.com/todo/markasdone.svg", + "action": { + "type": "sendEvent", + "sendContext": false + }, + "id": "complete;g:183ff1e90d79465793273a31d7d1e537;li:c5f13a8a-e90a-4396-b810-1cfe85ef7c31;to:b4273700-ac8c-44d0-91a3-d13d3d11e500" + } + ] + } + ], + "id": "LrAbZ", + "to": "g:183ff1e90d79465793273a31d7d1e537", + "from": "u:Bgcq3pt33pqpllbt", + "notification": "Rishabh rawat added a to-do in New List 1 list", + "flockml": "Rishabh rawat added a to-do in New List 1 list", + "text": "", + "sendAs": { + "name": "To-do bot", + "profileImage": "https://apps-static.flock.com/todo/todoboticon.png" + }, + "appId": "6d0aa37b00944ec0a7426d34ca2df048", + "timestamp": "2018-03-01T07:56:41.413Z", + "timestampInMillis": 1519891001413, + "uid": "1519891001413-vNe-m201", + "onBehalfOf": "u:9qehqo3ixo3t93e3" +} diff --git a/zerver/webhooks/flock/tests.py b/zerver/webhooks/flock/tests.py new file mode 100644 index 0000000000..ae6f9ba8ff --- /dev/null +++ b/zerver/webhooks/flock/tests.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +from typing import Text +from zerver.lib.test_classes import WebhookTestCase + +class FlockHookTests(WebhookTestCase): + STREAM_NAME = 'test' + URL_TEMPLATE = u"/api/v1/external/flock?api_key={api_key}" + + def test_flock_message(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"This is the welcome message!" + self.send_and_test_stream_message('messages', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_reply(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"It's interesting how high productivity will go..." + self.send_and_test_stream_message('reply', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_note(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"Shared a note" + self.send_and_test_stream_message('note', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_reply_note(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"This is reply to Note." + self.send_and_test_stream_message('reply_note', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_reply_pinned(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"This is reply to pinned message." + self.send_and_test_stream_message('reply_pinned', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_reply_reminder(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"This is a reply to Reminder." + self.send_and_test_stream_message('reply_reminder', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_reply_todo(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"This is a reply to Todo notification." + self.send_and_test_stream_message('reply_todo', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_pinned(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"Rishabh rawat pinned an item to the conversation" + self.send_and_test_stream_message('pinned', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_reminder(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"Rishabh rawat wanted me to remind All" + self.send_and_test_stream_message('reminder', + expected_subject, + expected_message, + content_type="application/json") + + def test_flock_todo(self) -> None: + expected_subject = u"Flock notifications" + expected_message = u"Rishabh rawat added a to-do in New List 1 list" + self.send_and_test_stream_message('todo', + expected_subject, + expected_message, + content_type="application/json") + + def get_body(self, fixture_name: Text) -> Text: + return self.fixture_data("flock", fixture_name, file_type="json") diff --git a/zerver/webhooks/flock/view.py b/zerver/webhooks/flock/view.py new file mode 100644 index 0000000000..c7ce376a68 --- /dev/null +++ b/zerver/webhooks/flock/view.py @@ -0,0 +1,26 @@ +# Webhooks for external integrations. +from zerver.lib.actions import check_send_stream_message +from zerver.lib.response import json_success +from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view +from zerver.models import UserProfile +from django.http import HttpRequest, HttpResponse +from typing import Dict, Any, Text + +CHECK_IS_REPLY = "in reply to" + +@api_key_only_webhook_view('Flock') +@has_request_variables +def api_flock_webhook(request: HttpRequest, user_profile: UserProfile, + payload: Dict[str, Any]=REQ(argument_type='body'), + stream: str=REQ(default='test'), + topic: str=REQ(default='Flock notifications')) -> HttpResponse: + + if len(payload["text"]) != 0: + message_body = payload["text"] + else: + message_body = payload["notification"] + body = u"{}".format(message_body) + + check_send_stream_message(user_profile, request.client, stream, topic, body) + + return json_success()