dispatch: break Dispatcher actions into 2nd model

decouple the dispatcher (a key, basically) with the actions to take upon
receiving such a message. allows us to have multiple actions for one key
without weird hacks
This commit is contained in:
Brian S. Stephan 2015-06-19 11:29:00 -05:00
parent dac7999c0f
commit 4f717cb1c2
6 changed files with 96 additions and 22 deletions

View File

@ -2,7 +2,8 @@
from django.contrib import admin from django.contrib import admin
from dispatch.models import Dispatcher from dispatch.models import Dispatcher, DispatcherAction
admin.site.register(Dispatcher) admin.site.register(Dispatcher)
admin.site.register(DispatcherAction)

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('dispatch', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='DispatcherAction',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('type', models.CharField(max_length=16, choices=[(b'privmsg', b'IRC privmsg'), (b'file', b'Write to file')])),
('destination', models.CharField(max_length=200)),
],
),
migrations.RemoveField(
model_name='dispatcher',
name='destination',
),
migrations.RemoveField(
model_name='dispatcher',
name='type',
),
migrations.AddField(
model_name='dispatcheraction',
name='dispatcher',
field=models.ForeignKey(to='dispatch.Dispatcher'),
),
]

View File

@ -10,7 +10,19 @@ log = logging.getLogger('dispatch.models')
class Dispatcher(models.Model): class Dispatcher(models.Model):
"""Handle incoming API requests and do something with them.""" """Organize dispatchers by key."""
key = models.CharField(max_length=16, unique=True)
def __unicode__(self):
"""String representation."""
return u"{0:s}".format(self.key)
class DispatcherAction(models.Model):
"""Handle requests to dispatchers and do something with them."""
PRIVMSG_TYPE = 'privmsg' PRIVMSG_TYPE = 'privmsg'
FILE_TYPE = 'file' FILE_TYPE = 'file'
@ -20,11 +32,11 @@ class Dispatcher(models.Model):
(FILE_TYPE, "Write to file"), (FILE_TYPE, "Write to file"),
) )
key = models.CharField(max_length=16, unique=True) dispatcher = models.ForeignKey('Dispatcher')
type = models.CharField(max_length=16, choices=TYPE_CHOICES) type = models.CharField(max_length=16, choices=TYPE_CHOICES)
destination = models.CharField(max_length=200) destination = models.CharField(max_length=200)
def __unicode__(self): def __unicode__(self):
"""String representation.""" """String representation."""
return u"{0:s} -> {1:s}".format(self.key, self.destination) return u"{0:s} -> {1:s} {2:s}".format(self.dispatcher.key, self.type, self.destination)

View File

@ -2,14 +2,21 @@
from rest_framework import serializers from rest_framework import serializers
from dispatch.models import Dispatcher from dispatch.models import Dispatcher, DispatcherAction
class DispatcherSerializer(serializers.ModelSerializer): class DispatcherSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Dispatcher model = Dispatcher
fields = ('id', 'key', 'type', 'destination') fields = ('id', 'key')
class DispatcherActionSerializer(serializers.ModelSerializer):
class Meta:
model = DispatcherAction
fields = ('id', 'dispatcher', 'type', 'destination')
class DispatchMessageSerializer(serializers.Serializer): class DispatchMessageSerializer(serializers.Serializer):

View File

@ -2,11 +2,15 @@
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from dispatch.views import DispatchMessage, DispatcherList, DispatcherDetail from dispatch.views import (DispatchMessage, DispatcherList, DispatcherDetail, DispatcherActionList,
DispatcherActionDetail)
urlpatterns = patterns('dispatch.views', urlpatterns = patterns('dispatch.views',
url(r'^api/dispatchers/$', DispatcherList.as_view(), name='dispatch_api_dispatchers'), url(r'^api/dispatchers/$', DispatcherList.as_view(), name='dispatch_api_dispatchers'),
url(r'^api/dispatchers/(?P<pk>[0-9]+)/$', DispatcherDetail.as_view(), name='dispatch_api_dispatcher_detail'), url(r'^api/dispatchers/(?P<pk>[0-9]+)/$', DispatcherDetail.as_view(), name='dispatch_api_dispatcher_detail'),
url(r'^api/dispatchers/(?P<pk>[0-9]+)/message$', DispatchMessage.as_view(), name='dispatch_api_dispatch_message'), url(r'^api/dispatchers/(?P<pk>[0-9]+)/message$', DispatchMessage.as_view(), name='dispatch_api_dispatch_message'),
url(r'^api/actions/$', DispatcherActionList.as_view(), name='dispatch_api_actions'),
url(r'^api/actions/(?P<pk>[0-9]+)/$', DispatcherActionDetail.as_view(), name='dispatch_api_action_detail'),
) )

View File

@ -8,14 +8,12 @@ import os
import xmlrpclib import xmlrpclib
from django.conf import settings from django.conf import settings
from django.http import Http404
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import generics, status from rest_framework import generics, status
from dispatch.models import Dispatcher from dispatch.models import Dispatcher, DispatcherAction
from dispatch.serializers import DispatchMessageSerializer, DispatcherSerializer from dispatch.serializers import DispatchMessageSerializer, DispatcherSerializer, DispatcherActionSerializer
log = logging.getLogger('dispatch.views') log = logging.getLogger('dispatch.views')
@ -59,17 +57,18 @@ class DispatchMessage(generics.GenericAPIView):
dispatcher = self.get_object() dispatcher = self.get_object()
message = self.serializer_class(data=request.data) message = self.serializer_class(data=request.data)
if message.is_valid(): if message.is_valid():
if dispatcher.type == Dispatcher.PRIVMSG_TYPE: for action in dispatcher.dispatcheraction_set.all():
bot_url = 'http://{0:s}:{1:d}/'.format(settings.IRCBOT_XMLRPC_HOST, settings.IRCBOT_XMLRPC_PORT) if action.type == DispatcherAction.PRIVMSG_TYPE:
bot = xmlrpclib.ServerProxy(bot_url) bot_url = 'http://{0:s}:{1:d}/'.format(settings.IRCBOT_XMLRPC_HOST, settings.IRCBOT_XMLRPC_PORT)
log.debug("sending '%s' to channel %s", message.data['message'], dispatcher.destination) bot = xmlrpclib.ServerProxy(bot_url)
bot.privmsg(dispatcher.destination, message.data['message']) log.debug("sending '%s' to channel %s", message.data['message'], action.destination)
elif dispatcher.type == Dispatcher.FILE_TYPE: bot.privmsg(action.destination, message.data['message'])
filename = os.path.abspath(dispatcher.destination) elif action.type == DispatcherAction.FILE_TYPE:
log.debug("sending '%s' to file %s", message.data['message'], filename) filename = os.path.abspath(action.destination)
with open(filename, 'w') as f: log.debug("sending '%s' to file %s", message.data['message'], filename)
f.write(message.data['message']) with open(filename, 'w') as f:
f.write('\n') f.write(message.data['message'])
f.write('\n')
new_data = copy.deepcopy(message.data) new_data = copy.deepcopy(message.data)
new_data['status'] = "OK" new_data['status'] = "OK"
@ -77,3 +76,19 @@ class DispatchMessage(generics.GenericAPIView):
return Response(new_message.initial_data) return Response(new_message.initial_data)
return Response(message.errors, status=status.HTTP_400_BAD_REQUEST) return Response(message.errors, status=status.HTTP_400_BAD_REQUEST)
class DispatcherActionList(generics.ListAPIView):
"""List all dispatchers."""
queryset = DispatcherAction.objects.all()
serializer_class = DispatcherActionSerializer
class DispatcherActionDetail(generics.RetrieveAPIView):
"""Detail the given dispatcher."""
queryset = DispatcherAction.objects.all()
serializer_class = DispatcherActionSerializer