dr.botzo/dispatch/views.py

119 lines
4.1 KiB
Python

"""Handle dispatcher API requests."""
import copy
import logging
import os
import xmlrpc.client
from rest_framework import generics, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from dispatch.models import Dispatcher, DispatcherAction
from dispatch.serializers import DispatcherActionSerializer, DispatcherSerializer, DispatchMessageSerializer
log = logging.getLogger('dispatch.views')
class HasSendMessagePermission(IsAuthenticated):
"""Class to check if the authenticated user can send messages via dispatch."""
def has_permission(self, request, view):
"""Check user permission for dispatch.send_message."""
if request.user.has_perm('dispatch.send_message'):
return True
return False
class DispatcherList(generics.ListAPIView):
"""List all dispatchers."""
queryset = Dispatcher.objects.all()
serializer_class = DispatcherSerializer
class DispatcherDetail(generics.RetrieveAPIView):
"""Detail the given dispatcher."""
queryset = Dispatcher.objects.all()
serializer_class = DispatcherSerializer
class DispatcherDetailByKey(DispatcherDetail):
"""Detail a specific dispatcher."""
lookup_field = 'key'
class DispatchMessage(generics.GenericAPIView):
"""Send a message to the given dispatcher."""
permission_classes = (HasSendMessagePermission,)
queryset = Dispatcher.objects.all()
serializer_class = DispatchMessageSerializer
def get(self, request, *args, **kwargs):
"""Return a default message, since this needs POST."""
data = {'message': "", 'status': "READY"}
message = self.serializer_class(data=data)
return Response(message.initial_data)
def post(self, request, *args, **kwargs):
"""Accept and dispatch a provided message."""
dispatcher = self.get_object()
message = self.serializer_class(data=request.data)
if message.is_valid():
for action in dispatcher.actions.all():
# manipulate the message if desired
if action.include_key:
text = "[{0:s}] {1:s}".format(action.dispatcher.key, message.data['message'])
else:
text = message.data['message']
if action.type == DispatcherAction.PRIVMSG_TYPE:
# connect over XML-RPC and send
try:
bot_url = 'http://{0:s}:{1:d}/'.format(dispatcher.bot_xmlrpc_host, dispatcher.bot_xmlrpc_port)
bot = xmlrpc.client.ServerProxy(bot_url, allow_none=True)
log.debug("sending '%s' to channel %s", text, action.destination)
bot.reply(None, text, False, action.destination)
except Exception as e:
new_data = copy.deepcopy(message.data)
new_data['status'] = "FAILED - {0:s}".format(str(e))
new_message = self.serializer_class(data=new_data)
return Response(new_message.initial_data)
elif action.type == DispatcherAction.FILE_TYPE:
# write to file
filename = os.path.abspath(action.destination)
log.debug("sending '%s' to file %s", text, filename)
with open(filename, 'w') as f:
f.write(text + '\n')
new_data = copy.deepcopy(message.data)
new_data['status'] = "OK"
new_message = self.serializer_class(data=new_data)
return Response(new_message.initial_data)
return Response(message.errors, status=status.HTTP_400_BAD_REQUEST)
class DispatchMessageByKey(DispatchMessage):
"""Dispatch a message for a specific key."""
lookup_field = 'key'
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