"""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