Skip to content

Commit

Permalink
Merge pull request #3 from webscopeio/feature/events-api-and-home
Browse files Browse the repository at this point in the history
Events API support fixes #2
  • Loading branch information
jvorcak authored Feb 18, 2020
2 parents 1714dba + 0c8e8ce commit fc9df35
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 2 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup

setup(
version="1.0.34",
version="1.0.35",
install_requires=["slackclient"]
)
57 changes: 57 additions & 0 deletions slack_app/decorators.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from functools import wraps

import slack
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponseBadRequest

from .signals import slack_event_received, refresh_home
from .models import SlackUserMapping, SlackWorkspace

from .helpers import is_verified_slack_request, slack_interactivity_callbacks, slack_commands


Expand Down Expand Up @@ -37,3 +41,56 @@ def wrapped_view(request, *args, **kwargs):
view_func.csrf_exempt = True

return wraps(view_func)(wrapped_view)


def on_slack_signal(*event_types, inject_slack_models=False):
def decorator_receiver(receiver_func):
@wraps(receiver_func)
def signal_receiver(sender, event_type, event_data, signal, **kwargs):
if event_type in event_types:
slack_models = {
"slack_user_mapping": SlackUserMapping.objects.get(pk=event_data.get('user')),
"slack_workspace": SlackWorkspace.objects.get(pk=kwargs.get('team_id')),
} if inject_slack_models else {}
return receiver_func(sender, event_data=event_data, event_type=event_type, **slack_models, **kwargs)

slack_event_received.connect(signal_receiver, weak=False)

return decorator_receiver


def slack_app_home(receiver_func):
@wraps(receiver_func)
def signal_receiver(
sender,
event_type=None,
event_data=None,

slack_user_mapping=None,
slack_workspace=None,
**kwargs
):
if event_type == 'app_home_opened':
slack_user_mapping = SlackUserMapping.objects.get(pk=event_data.get('user'))
slack_workspace = SlackWorkspace.objects.get(pk=kwargs.get('team_id'))

blocks, title = receiver_func(
sender,
event_data=event_data,
event_type=event_type,
slack_user_mapping=slack_user_mapping,
slack_workspace=slack_workspace,
**kwargs,
)

client = slack.WebClient(token=slack_workspace.bot_access_token)
client.views_publish(user_id=slack_user_mapping.slack_user_id, view={
"type": 'home',
"title": title,
"blocks": blocks
})

slack_event_received.connect(signal_receiver, weak=False)
refresh_home.connect(signal_receiver, weak=False)

return signal_receiver
10 changes: 10 additions & 0 deletions slack_app/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import django.dispatch

"""
Slack want us to implement a queue to react to events.
https://api.slack.com/events-api#responding_to_events
That's why, we've chosen to implement this using Django's signals.
"""
slack_event_received = django.dispatch.Signal(providing_args=["event_type", "event_data"])
refresh_home = django.dispatch.Signal(providing_args=["slack_user_mapping", "slack_workspace"])
4 changes: 3 additions & 1 deletion slack_app/urls.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from django.urls import path

from .views import slack_oauthcallback, slack_login_callback, slack_interactivity, slack_command, connect_account
from .views import slack_oauthcallback, slack_login_callback, slack_interactivity, slack_command, connect_account, \
slack_events

app_name = "slack_app"

urlpatterns = [
path('install/', slack_oauthcallback, name='install'),
path('login/', slack_login_callback, name='login'),
path('interactivity/', slack_interactivity, name='interactivity'),
path('events/', slack_events, name='events'),
path('commands/<str:name>/', slack_command, name='command'),
path('connect/<str:nonce>/', connect_account, name='connect_account'),
]
23 changes: 23 additions & 0 deletions slack_app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.urls import reverse
from django.views.decorators.http import require_http_methods

from .signals import slack_event_received
from .exceptions import SlackAppNotInstalledProperlyException, SlackAccountNotLinkedException, SlackCommandDoesNotExist, \
SlackInteractivityTypeDoesNotExist
from .models import SlackWorkspace, SlackUserMapping
Expand Down Expand Up @@ -160,3 +161,25 @@ def connect_account(request, nonce: str):
# TODO - allow to specify a function that accepts request, mapping & user and return whatever it wants
# (Redirect/Render, etc)
return render(request, "verified_nonce.html")


@slack_verify_request
def slack_events(request):
data = json.loads(request.body)

if data.get("type") == "url_verification":
return JsonResponse({
"challenge": data.get("challenge"),
})

if data.get("type") == "event_callback":
event_data = data.pop('event')
event_type = event_data.pop('type')

slack_event_received.send(sender=request, event_type=event_type, event_data=event_data, **data)
return JsonResponse({})

if data.get("type") == 'app_rate_limited':
return JsonResponse({})

return NotImplementedError(f"Unknown type {type}")

0 comments on commit fc9df35

Please sign in to comment.