def create(self, request=None, **kwargs):
        """POST method of DialCallback API"""
        logger.debug('DialCallback API authentication called!')
        auth_result = self._meta.authentication.is_authenticated(request)
        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        logger.debug('DialCallback API authorization called!')
        auth_result = self._meta.authorization.is_authorized(request, object)

        logger.debug('DialCallback API validation called!')
        errors = self._meta.validation.is_valid(request)

        if not errors:
            logger.debug('DialCallback API get called!')
            opt_aleg_uuid = request.POST.get('DialALegUUID')
            opt_dial_bleg_uuid = request.POST.get('DialBLegUUID')
            opt_dial_bleg_status = request.POST.get('DialBLegStatus')
            #We are just analyzing the hangup
            if opt_dial_bleg_status != 'hangup':
                object_list = [{'result': 'OK - Bleg status is not Hangup'}]
                logger.debug('DialCallback API : Result 200!')
                obj = CustomXmlEmitter()
                return self.create_response(request,
                                            obj.render(request, object_list))
            callrequest = Callrequest.objects.get(aleg_uuid=opt_aleg_uuid)
            data = {}
            for element in CDR_VARIABLES:
                if not request.POST.get('variable_%s' % element):
                    data[element] = None
                else:
                    data[element] = request.POST.get('variable_%s' % element)

            from_plivo = request.POST.get('From')
            to_plivo = request.POST.get('To')

            create_voipcall(obj_callrequest=callrequest,
                            plivo_request_uuid=callrequest.request_uuid,
                            data=data,
                            data_prefix='',
                            leg='b',
                            from_plivo=from_plivo,
                            to_plivo=to_plivo)
            object_list = [{'result': 'OK'}]
            logger.debug('DialCallback API : Result 200!')
            obj = CustomXmlEmitter()

            return self.create_response(request,
                                        obj.render(request, object_list))
        else:
            if len(errors):
                if request:
                    desired_format = self.determine_format(request)
                else:
                    desired_format = self._meta.default_format

                serialized = self.serialize(request, errors, desired_format)
                response = http.HttpBadRequest(content=serialized,
                                               content_type=desired_format)
                raise ImmediateHttpResponse(response=response)
    def create(self, request=None, **kwargs):
        """POST method of Hangupcall API"""
        logger.debug('Hangupcall API authentication called!')
        auth_result = self._meta.authentication.is_authenticated(request)
        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())
        auth_result = self._meta.authorization.is_authorized(request, object)
        errors = self._meta.validation.is_valid(request)
        if not errors:
            opt_request_uuid = request.POST.get('RequestUUID')
            opt_hangup_cause = request.POST.get('HangupCause')
            try:
                callrequest = Callrequest.objects.get(
                    request_uuid=opt_request_uuid)
            except:
                logger.debug('Hangupcall Error cannot find the Callrequest!')
            try:
                obj_subscriber = CampaignSubscriber.objects.get(
                    id=callrequest.campaign_subscriber.id)
                if opt_hangup_cause == 'NORMAL_CLEARING':
                    obj_subscriber.status = 5  # Complete
                else:
                    obj_subscriber.status = 4  # Fail
                obj_subscriber.save()
            except:
                logger.debug('Hangupcall Error cannot find the '
                             'Campaignsubscriber!')

            # 2 / FAILURE ; 3 / RETRY ; 4 / SUCCESS
            if opt_hangup_cause == 'NORMAL_CLEARING':
                callrequest.status = 4  # Success
            else:
                callrequest.status = 2  # Failure
            callrequest.hangup_cause = opt_hangup_cause
            #save callrequest & campaignsubscriber
            callrequest.save()
            data = {}
            for element in CDR_VARIABLES:
                if not request.POST.get('variable_%s' % element):
                    data[element] = None
                else:
                    data[element] = request.POST.get('variable_%s' % element)
            from_plivo = request.POST.get('From')
            to_plivo = request.POST.get('To')

            create_voipcall(obj_callrequest=callrequest,
                            plivo_request_uuid=opt_request_uuid,
                            data=data,
                            data_prefix='',
                            leg='a',
                            hangup_cause=opt_hangup_cause,
                            from_plivo=from_plivo,
                            to_plivo=to_plivo)
            object_list = [{'result': 'OK'}]
            logger.debug('Hangupcall API : Result 200!')
            obj = CustomXmlEmitter()

            #We will manage the retry directly from the API
            if opt_hangup_cause != 'NORMAL_CLEARING'\
            and callrequest.call_type == 1:  # Allow retry
                #Update to Retry Done
                callrequest.call_type = 3
                callrequest.save()

                dialer_set = user_dialer_setting(callrequest.user)
                if callrequest.num_attempt >= callrequest.campaign.maxretry\
                or callrequest.num_attempt >= dialer_set.maxretry:
                    logger.error("Not allowed retry - Maxretry (%d)" %\
                                 callrequest.campaign.maxretry)
                else:
                    #Allowed Retry

                    # TODO : Review Logic
                    # Create new callrequest, Assign parent_callrequest,
                    # Change callrequest_type & num_attempt
                    new_callrequest = Callrequest(
                        request_uuid=uuid1(),
                        parent_callrequest_id=callrequest.id,
                        call_type=1,
                        num_attempt=callrequest.num_attempt + 1,
                        user=callrequest.user,
                        campaign_id=callrequest.campaign_id,
                        aleg_gateway_id=callrequest.aleg_gateway_id,
                        content_type=callrequest.content_type,
                        object_id=callrequest.object_id,
                        phone_number=callrequest.phone_number)
                    new_callrequest.save()
                    #Todo Check if it's a good practice
                    #implement a PID algorithm
                    second_towait = callrequest.campaign.intervalretry
                    launch_date = datetime.now() + \
                                  timedelta(seconds=second_towait)
                    logger.info("Init Retry CallRequest at %s" %\
                                (launch_date.strftime("%b %d %Y %I:%M:%S")))
                    init_callrequest.apply_async(
                        args=[new_callrequest.id, callrequest.campaign.id],
                        eta=launch_date)

            return self.create_response(request,
                                        obj.render(request, object_list))
        else:
            if len(errors):
                if request:
                    desired_format = self.determine_format(request)
                else:
                    desired_format = self._meta.default_format

                serialized = self.serialize(request, errors, desired_format)
                response = http.HttpBadRequest(content=serialized,
                                               content_type=desired_format)
                raise ImmediateHttpResponse(response=response)
    def create(self, request=None, **kwargs):
        """POST method of Answercall API"""
        logger.debug('Answercall API authentication called!')
        auth_result = self._meta.authentication.is_authenticated(request)
        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        logger.debug('Answercall API authorization called!')
        auth_result = self._meta.authorization.is_authorized(request, object)

        logger.debug('Answercall API validation called!')
        errors = self._meta.validation.is_valid(request)

        if not errors:
            logger.debug('Answercall API get called!')

            opt_ALegRequestUUID = request.POST.get('ALegRequestUUID')
            opt_CallUUID = request.POST.get('CallUUID')

            #TODO: If we update the Call to success here we should
            # not do it in hangup url
            obj_callrequest = Callrequest.objects\
                .get(request_uuid=opt_ALegRequestUUID)

            #TODO : use constant
            obj_callrequest.status = 8  # IN-PROGRESS
            obj_callrequest.aleg_uuid = opt_CallUUID
            obj_callrequest.save()

            # check if Voice App
            if obj_callrequest.content_object.__class__.__name__ != 'VoiceApp':
                object_list = []
                logger.error('Error with App type, not a VoiceApp!')
            else:
                data = obj_callrequest.content_object.data
                tts_language = obj_callrequest.content_object.tts_language

                extra_data = obj_callrequest.campaign.extra_data
                if extra_data and len(extra_data) > 1:
                    #check if we have a voice_app_data tag to replace
                    voice_app_data = search_tag_string(extra_data,
                                    'voice_app_data')
                    if voice_app_data:
                        data = voice_app_data

                if obj_callrequest.content_object.type == 1:
                    #Dial
                    timelimit = obj_callrequest.timelimit
                    callerid = obj_callrequest.callerid
                    gatewaytimeouts = obj_callrequest.timeout
                    gateways = obj_callrequest.content_object.gateway.gateways
                    dial_command = 'Dial timeLimit="%s" ' \
                                   'callerId="%s" ' \
                                   'callbackUrl="%s"' % \
                                   (timelimit,
                                    callerid,
                                    PLIVO_DEFAULT_DIALCALLBACK_URL)
                    number_command = 'Number gateways="%s" ' \
                                     'gatewayTimeouts="%s"' % \
                                     (gateways, gatewaytimeouts)

                    object_list = [{dial_command: {number_command: data}}]
                    logger.debug('Dial command')

                elif obj_callrequest.content_object.type == 2:
                    #PlayAudio
                    object_list = [{'Play': data}]
                    logger.debug('PlayAudio')

                elif obj_callrequest.content_object.type == 3:
                    #Conference
                    object_list = [{'Conference': data}]
                    logger.debug('Conference')

                elif obj_callrequest.content_object.type == 4:
                    #Speak
                    if settings.TTS_ENGINE != 'ACAPELA':
                        object_list = [{'Speak': data}]
                        logger.debug('Speak')
                    else:
                        import acapela
                        DIRECTORY = settings.MEDIA_ROOT + '/tts/'
                        domain = Site.objects.get_current().domain
                        tts_acapela = acapela.Acapela(
                            settings.TTS_ENGINE,
                            settings.ACCOUNT_LOGIN,
                            settings.APPLICATION_LOGIN,
                            settings.APPLICATION_PASSWORD,
                            settings.SERVICE_URL,
                            settings.QUALITY,
                            DIRECTORY)
                        tts_acapela.prepare(
                            data,
                            tts_language,
                            settings.ACAPELA_GENDER,
                            settings.ACAPELA_INTONATION)
                        output_filename = tts_acapela.run()

                        audiofile_url = domain + settings.MEDIA_URL +\
                                        'tts/' + output_filename
                        object_list = [{'Play': audiofile_url}]
                        logger.debug('PlayAudio-TTS')
                else:
                    logger.error('Error with Voice App type!')

            obj = CustomXmlEmitter()
            return self.create_response(request,
                obj.render(request, object_list))

        else:
            logger.debug('ERROR : ' + str(errors))
            if len(errors):
                if request:
                    desired_format = self.determine_format(request)
                else:
                    desired_format = self._meta.default_format

                serialized = self.serialize(request, errors, desired_format)
                response = http.HttpBadRequest(content=serialized,
                    content_type=desired_format)
                raise ImmediateHttpResponse(response=response)
    def create(self, request, **kwargs):
        """POST method of CDR_Store API"""
        logger.debug("CDR API authentication called!")
        auth_result = self._meta.authentication.is_authenticated(request)
        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        logger.debug("CDR API authorization called!")
        auth_result = self._meta.authorization.is_authorized(request, object)

        errors = self._meta.validation.is_valid(request)
        logger.debug("CDR API get called from IP %s" % request.META.get("REMOTE_ADDR"))

        if not errors:

            opt_cdr = request.POST.get("cdr")
            # XML parsing doesn't work if you urldecode first
            # decoded_cdr = urllib.unquote(opt_cdr.decode("utf8"))
            decoded_cdr = opt_cdr
            data = {}
            try:
                import xml.etree.ElementTree as ET

                tree = ET.fromstring(decoded_cdr)
                lst = tree.find("variables")
            except:
                logger.debug("Error parse XML")
                raise

            for j in lst:
                if j.tag in CDR_VARIABLES:
                    data[j.tag] = urllib.unquote(j.text.decode("utf8"))
            for element in CDR_VARIABLES:
                if element in data:
                    data[element] = None
                else:
                    logger.debug("%s not found!")

            # TODO: Add tag for newfies in outbound call
            if not "request_uuid" in data or not data["request_uuid"]:
                # CDR not related to plivo
                error_msg = "CDR not related to Newfies/Plivo!"
                logger.error(error_msg)
                raise BadRequest(error_msg)

            # TODO : delay if not find callrequest
            try:
                # plivo add "a_" in front of the uuid
                # for the aleg so we remove the "a_"
                if data["request_uuid"][1:2] == "a_":
                    request_uuid = data["request_uuid"][2:]
                else:
                    request_uuid = data["request_uuid"]
                obj_callrequest = Callrequest.objects.get(request_uuid=request_uuid)
            except:
                # Send notification to admin
                from dialer_campaign.views import common_send_notification
                from django.contrib.auth.models import User

                recipient_list = User.objects.filter(is_superuser=1, is_active=1)
                # send to all admin user
                for recipient in recipient_list:
                    # callrequest_not_found - notification id 8
                    common_send_notification(request, 8, recipient)

                error_msg = "Error, there is no callrequest for " "this uuid %s " % data["request_uuid"]
                logger.error(error_msg, extra={"stack": True})

                raise BadRequest(error_msg)

            # CREATE CDR - VOIP CALL
            create_voipcall(obj_callrequest, request_uuid, data, data_prefix="", leg="a")

            # List of HttpResponse :
            # https://github.com/toastdriven/django-tastypie/blob/master/tastypie/http.py
            logger.debug("CDR API : Result 200")

            object_list = [{"result": "OK"}]
            obj = CustomXmlEmitter()
            return self.create_response(request, obj.render(request, object_list))

        else:
            if len(errors):
                if request:
                    desired_format = self.determine_format(request)
                else:
                    desired_format = self._meta.default_format

                serialized = self.serialize(request, errors, desired_format)
                response = http.HttpBadRequest(content=serialized, content_type=desired_format)
                raise ImmediateHttpResponse(response=response)
    def create(self, request, **kwargs):
        """POST method of CDR_Store API"""
        logger.debug('CDR API authentication called!')
        auth_result = self._meta.authentication.is_authenticated(request)
        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        logger.debug('CDR API authorization called!')
        auth_result = self._meta.authorization.is_authorized(request, object)

        errors = self._meta.validation.is_valid(request)
        logger.debug('CDR API get called from IP %s' % request.META.get('REMOTE_ADDR'))

        if not errors:

            opt_cdr = request.POST.get('cdr')
            #XML parsing doesn't work if you urldecode first
            #decoded_cdr = urllib.unquote(opt_cdr.decode("utf8"))
            decoded_cdr = opt_cdr
            data = {}
            try:
                import xml.etree.ElementTree as ET
                tree = ET.fromstring(decoded_cdr)
                lst = tree.find("variables")
            except:
                logger.debug('Error parse XML')
                raise

            for j in lst:
                if j.tag in CDR_VARIABLES:
                    data[j.tag] = urllib.unquote(j.text.decode("utf8"))
            for element in CDR_VARIABLES:
                if element in data:
                    data[element] = None
                else:
                    logger.debug("%s not found!")

            #TODO: Add tag for newfies in outbound call
            if not 'request_uuid' in data or not data['request_uuid']:
                # CDR not related to plivo
                error_msg = 'CDR not related to Newfies/Plivo!'
                logger.error(error_msg)
                raise BadRequest(error_msg)

            #TODO : delay if not find callrequest
            try:
                # plivo add "a_" in front of the uuid
                # for the aleg so we remove the "a_"
                if data['request_uuid'][1:2] == 'a_':
                    request_uuid = data['request_uuid'][2:]
                else:
                    request_uuid = data['request_uuid']
                obj_callrequest = Callrequest.objects.get(
                    request_uuid=request_uuid)
            except:
                # Send notification to admin
                from dialer_campaign.views import common_send_notification
                from django.contrib.auth.models import User
                recipient_list = User.objects.filter(
                    is_superuser=1,
                    is_active=1)
                # send to all admin user
                for recipient in recipient_list:
                    # callrequest_not_found - notification id 8
                    common_send_notification(request, 8, recipient)

                error_msg = "Error, there is no callrequest for "\
                            "this uuid %s " % data['request_uuid']
                logger.error(error_msg, extra={'stack': True})

                raise BadRequest(error_msg)

            # CREATE CDR - VOIP CALL
            create_voipcall(
                obj_callrequest,
                request_uuid,
                data,
                data_prefix='',
                leg='a')

            # List of HttpResponse :
            # https://github.com/toastdriven/django-tastypie/blob/master/tastypie/http.py
            logger.debug('CDR API : Result 200')

            object_list = [{'result': 'OK'}]
            obj = CustomXmlEmitter()
            return self.create_response(request, obj.render(request, object_list))

        else:
            if len(errors):
                if request:
                    desired_format = self.determine_format(request)
                else:
                    desired_format = self._meta.default_format

                serialized = self.serialize(request, errors, desired_format)
                response = http.HttpBadRequest(
                    content=serialized,
                    content_type=desired_format)
                raise ImmediateHttpResponse(response=response)
Example #6
0
    def create(self, request=None, **kwargs):
        """POST method of Answercall API"""
        logger.debug('Answercall API authentication called!')
        auth_result = self._meta.authentication.is_authenticated(request)
        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        logger.debug('Answercall API authorization called!')
        auth_result = self._meta.authorization.is_authorized(request, object)

        logger.debug('Answercall API validation called!')
        errors = self._meta.validation.is_valid(request)

        if not errors:
            logger.debug('Answercall API get called!')

            opt_ALegRequestUUID = request.POST.get('ALegRequestUUID')
            opt_CallUUID = request.POST.get('CallUUID')

            #TODO: If we update the Call to success here we should
            # not do it in hangup url
            obj_callrequest = Callrequest.objects\
                .get(request_uuid=opt_ALegRequestUUID)

            #TODO : use constant
            obj_callrequest.status = 8  # IN-PROGRESS
            obj_callrequest.aleg_uuid = opt_CallUUID
            obj_callrequest.save()

            # check if Voice App
            if obj_callrequest.content_object.__class__.__name__ != 'VoiceApp':
                object_list = []
                logger.error('Error with App type, not a VoiceApp!')
            else:
                data = obj_callrequest.content_object.data
                tts_language = obj_callrequest.content_object.tts_language

                extra_data = obj_callrequest.campaign.extra_data
                if extra_data and len(extra_data) > 1:
                    #check if we have a voice_app_data tag to replace
                    voice_app_data = search_tag_string(extra_data,
                                                       'voice_app_data')
                    if voice_app_data:
                        data = voice_app_data

                if obj_callrequest.content_object.type == 1:
                    #Dial
                    timelimit = obj_callrequest.timelimit
                    callerid = obj_callrequest.callerid
                    gatewaytimeouts = obj_callrequest.timeout
                    gateways = obj_callrequest.content_object.gateway.gateways
                    dial_command = 'Dial timeLimit="%s" ' \
                                   'callerId="%s" ' \
                                   'callbackUrl="%s"' % \
                                   (timelimit,
                                    callerid,
                                    PLIVO_DEFAULT_DIALCALLBACK_URL)
                    number_command = 'Number gateways="%s" ' \
                                     'gatewayTimeouts="%s"' % \
                                     (gateways, gatewaytimeouts)

                    object_list = [{dial_command: {number_command: data}}]
                    logger.debug('Dial command')

                elif obj_callrequest.content_object.type == 2:
                    #PlayAudio
                    object_list = [{'Play': data}]
                    logger.debug('PlayAudio')

                elif obj_callrequest.content_object.type == 3:
                    #Conference
                    object_list = [{'Conference': data}]
                    logger.debug('Conference')

                elif obj_callrequest.content_object.type == 4:
                    #Speak
                    if settings.TTS_ENGINE != 'ACAPELA':
                        object_list = [{'Speak': data}]
                        logger.debug('Speak')
                    else:
                        import acapela
                        DIRECTORY = settings.MEDIA_ROOT + '/tts/'
                        domain = Site.objects.get_current().domain
                        tts_acapela = acapela.Acapela(
                            settings.TTS_ENGINE, settings.ACCOUNT_LOGIN,
                            settings.APPLICATION_LOGIN,
                            settings.APPLICATION_PASSWORD,
                            settings.SERVICE_URL, settings.QUALITY, DIRECTORY)
                        tts_acapela.prepare(data, tts_language,
                                            settings.ACAPELA_GENDER,
                                            settings.ACAPELA_INTONATION)
                        output_filename = tts_acapela.run()

                        audiofile_url = domain + settings.MEDIA_URL +\
                                        'tts/' + output_filename
                        object_list = [{'Play': audiofile_url}]
                        logger.debug('PlayAudio-TTS')
                else:
                    logger.error('Error with Voice App type!')

            obj = CustomXmlEmitter()
            return self.create_response(request,
                                        obj.render(request, object_list))

        else:
            logger.debug('ERROR : ' + str(errors))
            if len(errors):
                if request:
                    desired_format = self.determine_format(request)
                else:
                    desired_format = self._meta.default_format

                serialized = self.serialize(request, errors, desired_format)
                response = http.HttpBadRequest(content=serialized,
                                               content_type=desired_format)
                raise ImmediateHttpResponse(response=response)
    def create(self, request=None, **kwargs):
        """POST method of Hangupcall API"""
        logger.debug('Hangupcall API authentication called!')
        auth_result = self._meta.authentication.is_authenticated(request)
        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())
        auth_result = self._meta.authorization.is_authorized(request, object)
        errors = self._meta.validation.is_valid(request)
        if not errors:
            opt_request_uuid = request.POST.get('RequestUUID')
            opt_hangup_cause = request.POST.get('HangupCause')
            try:
                callrequest = Callrequest.objects.get(
                    request_uuid=opt_request_uuid)
            except:
                logger.debug('Hangupcall Error cannot find the Callrequest!')
            try:
                obj_subscriber = CampaignSubscriber.objects.get(
                    id=callrequest.campaign_subscriber.id)
                if opt_hangup_cause == 'NORMAL_CLEARING':
                    obj_subscriber.status = 5  # Complete
                else:
                    obj_subscriber.status = 4  # Fail
                obj_subscriber.save()
            except:
                logger.debug('Hangupcall Error cannot find the '
                             'Campaignsubscriber!')

            # 2 / FAILURE ; 3 / RETRY ; 4 / SUCCESS
            if opt_hangup_cause == 'NORMAL_CLEARING':
                callrequest.status = 4  # Success
            else:
                callrequest.status = 2  # Failure
            callrequest.hangup_cause = opt_hangup_cause
            #save callrequest & campaignsubscriber
            callrequest.save()
            data = {}
            for element in CDR_VARIABLES:
                if not request.POST.get('variable_%s' % element):
                    data[element] = None
                else:
                    data[element] = request.POST.get('variable_%s' % element)
            from_plivo = request.POST.get('From')
            to_plivo = request.POST.get('To')

            create_voipcall(obj_callrequest=callrequest,
                plivo_request_uuid=opt_request_uuid,
                data=data,
                data_prefix='',
                leg='a',
                hangup_cause=opt_hangup_cause,
                from_plivo=from_plivo,
                to_plivo=to_plivo)
            object_list = [{'result': 'OK'}]
            logger.debug('Hangupcall API : Result 200!')
            obj = CustomXmlEmitter()

            #We will manage the retry directly from the API
            if opt_hangup_cause != 'NORMAL_CLEARING'\
            and callrequest.call_type == 1:  # Allow retry
                #Update to Retry Done
                callrequest.call_type = 3
                callrequest.save()

                dialer_set = user_dialer_setting(callrequest.user)
                if callrequest.num_attempt >= callrequest.campaign.maxretry\
                or callrequest.num_attempt >= dialer_set.maxretry:
                    logger.error("Not allowed retry - Maxretry (%d)" %\
                                 callrequest.campaign.maxretry)
                else:
                    #Allowed Retry

                    # TODO : Review Logic
                    # Create new callrequest, Assign parent_callrequest,
                    # Change callrequest_type & num_attempt
                    new_callrequest = Callrequest(
                        request_uuid=uuid1(),
                        parent_callrequest_id=callrequest.id,
                        call_type=1,
                        num_attempt=callrequest.num_attempt + 1,
                        user=callrequest.user,
                        campaign_id=callrequest.campaign_id,
                        aleg_gateway_id=callrequest.aleg_gateway_id,
                        content_type=callrequest.content_type,
                        object_id=callrequest.object_id,
                        phone_number=callrequest.phone_number)
                    new_callrequest.save()
                    #Todo Check if it's a good practice
                    #implement a PID algorithm
                    second_towait = callrequest.campaign.intervalretry
                    launch_date = datetime.now() + \
                                  timedelta(seconds=second_towait)
                    logger.info("Init Retry CallRequest at %s" %\
                                (launch_date.strftime("%b %d %Y %I:%M:%S")))
                    init_callrequest.apply_async(
                        args=[new_callrequest.id, callrequest.campaign.id],
                        eta=launch_date)

            return self.create_response(request,
                obj.render(request, object_list))
        else:
            if len(errors):
                if request:
                    desired_format = self.determine_format(request)
                else:
                    desired_format = self._meta.default_format

                serialized = self.serialize(request, errors, desired_format)
                response = http.HttpBadRequest(
                    content=serialized,
                    content_type=desired_format)
                raise ImmediateHttpResponse(response=response)