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 dispatch.models import Dispatcher
from dispatch.models import Dispatcher, DispatcherAction
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):
"""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'
FILE_TYPE = 'file'
@ -20,11 +32,11 @@ class Dispatcher(models.Model):
(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)
destination = models.CharField(max_length=200)
def __unicode__(self):
"""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 dispatch.models import Dispatcher
from dispatch.models import Dispatcher, DispatcherAction
class DispatcherSerializer(serializers.ModelSerializer):
class Meta:
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):

View File

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