<commit_before># -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals

import json
import pytz
import requests
import xml.etree.ElementTree as ET

from datetime import datetime
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.files import File
from django.core.files.temp import NamedTemporaryFile
from django.db.models import Q
from django.http import HttpResponse, JsonResponse
from django.utils import timezone
from django.utils.dateparse import parse_datetime
from django.views.generic import View
from temba.api.models import WebHookEvent, SMS_RECEIVED
from temba.channels.models import Channel, PLIVO, SHAQODOON, YO, TWILIO_MESSAGING_SERVICE, AUTH_TOKEN, TELEGRAM, TWIML_API
from temba.contacts.models import Contact, URN, TEL_SCHEME
from temba.flows.models import Flow, FlowRun
from temba.orgs.models import NEXMO_UUID
from temba.msgs.models import Msg, HANDLE_EVENT_TASK, HANDLER_QUEUE, MSG_EVENT
from temba.triggers.models import Trigger
from temba.utils import json_date_to_datetime
from temba.utils.middleware import disable_middleware
from temba.utils.queues import push_task
from .tasks import fb_channel_subscribe
from twilio import twiml


class TwilioHandler(View):

    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(TwilioHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        return HttpResponse("ILLEGAL METHOD")

    def post(self, request, *args, **kwargs):
        from twilio.util import RequestValidator
        from temba.msgs.models import Msg

        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
        url = "https://" + settings.TEMBA_HOST + "%s" % request.get_full_path()

        call_sid = request.REQUEST.get('CallSid', None)
        direction = request.REQUEST.get('Direction', None)
        status = request.REQUEST.get('CallStatus', None)
        to_number = request.REQUEST.get('To', None)
        to_country = request.REQUEST.get('ToCountry', None)
        from_number = request.REQUEST.get('From', None)

        # Twilio sometimes sends un-normalized numbers
        if not to_number.startswith('+') and to_country:
            to_number, valid = URN.normalize_number(to_number, to_country)

        # see if it's a twilio call being initiated
        if to_number and call_sid and direction == 'inbound' and status == 'ringing':

            # find a channel that knows how to answer twilio calls
            channel = Channel.objects.filter(address=to_number, channel_type='T', role__contains='A', is_active=True).exclude(org=None).first()
            if not channel:
                raise Exception("No active answering channel found for number: %s" % to_number)

            client = channel.org.get_twilio_client()
            validator = RequestValidator(client.auth[1])
            signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')

            base_url = settings.TEMBA_HOST
            url = "https://%s%s" % (base_url, request.get_full_path())

            if validator.validate(url, request.POST, signature):
                from temba.ivr.models import IVRCall

                # find a contact for the one initiating us
                urn = URN.from_tel(from_number)
                contact = Contact.get_or_create(channel.org, channel.created_by, urns=[urn], channel=channel)
                urn_obj = contact.urn_objects[urn]

                flow = Trigger.find_flow_for_inbound_call(contact)

                call = IVRCall.create_incoming(channel, contact, urn_obj, flow, channel.created_by)
                call.update_status(request.POST.get('CallStatus', None),
                                   request.POST.get('CallDuration', None))
                call.save()

                if flow:
                    FlowRun.create(flow, contact.pk, call=call)
                    response = Flow.handle_call(call, {})
                    return HttpResponse(unicode(response))
                else:

                    # we don't have an inbound trigger to deal with this call.
                    response = twiml.Response()

                    # say nothing and hangup, this is a little rude, but if we reject the call, then
                    # they'll get a non-working number error. We send 'busy' when our server is down
                    # so we don't want to use that here either.
                    response.say('')
                    response.hangup()

                    # if they have a missed call trigger, fire that off
                    Trigger.catch_triggers(contact, Trigger.TYPE_MISSED_CALL, channel)

                    # either way, we need to hangup now
                    return HttpResponse(unicode(response))

        action = request.GET.get('action', 'received')
        # this is a callback for a message we sent
        if action == 'callback':
            smsId = request.GET.get('id', None)
            status = request.POST.get('SmsStatus', None)

            # get the SMS
            sms = Msg.all_messages.select_related('channel').get(id=smsId)

            # validate this request is coming from twilio
            org = sms.org
            client = org.get_twilio_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            # queued, sending, sent, failed, or received.
            if status == 'sent':
                sms.status_sent()
            elif status == 'delivered':
                sms.status_delivered()
            elif status == 'failed':
                sms.fail()

            return HttpResponse("", status=200)

        # this is an incoming message that is being received by Twilio
        elif action == 'received':
            channel = Channel.objects.filter(address=to_number, is_active=True).exclude(org=None).first()
            if not channel:
                raise Exception("No active channel found for number: %s" % to_number)

            # validate this request is coming from twilio
            org = channel.org
            client = org.get_twilio_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            body = request.POST['Body']
            urn = URN.from_tel(request.POST['From'])

            # process any attached media
            for i in range(int(request.POST.get('NumMedia', 0))):
                media_url = client.download_media(request.POST['MediaUrl%d' % i])
                path = media_url.partition(':')[2]
                Msg.create_incoming(channel, urn, path, media=media_url)

            if body:
                Msg.create_incoming(channel, urn, body)

            return HttpResponse("", status=201)

        return HttpResponse("Not Handled, unknown action", status=400)


class TwilioMessagingServiceHandler(View):
    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(TwilioMessagingServiceHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        return self.post(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        from twilio.util import RequestValidator
        from temba.msgs.models import Msg

        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
        url = "https://" + settings.HOSTNAME + "%s" % request.get_full_path()

        action = kwargs['action']
        channel_uuid = kwargs['uuid']

        channel = Channel.objects.filter(uuid=channel_uuid, is_active=True, channel_type=TWILIO_MESSAGING_SERVICE).exclude(org=None).first()
        if not channel:
            return HttpResponse("Channel with uuid: %s not found." % channel_uuid, status=404)

        if action == 'receive':

            org = channel.org
            client = org.get_twilio_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            Msg.create_incoming(channel, URN.from_tel(request.POST['From']), request.POST['Body'])

            return HttpResponse("", status=201)

        return HttpResponse("Not Handled, unknown action", status=400)


class TwimlAPIHandler(View):
    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(TwimlAPIHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        return self.post(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        from twilio.util import RequestValidator
        from temba.msgs.models import Msg

        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
        url = "https://" + settings.HOSTNAME + "%s" % request.get_full_path()

        action = kwargs['action']
        channel_uuid = kwargs['uuid']

        channel = Channel.objects.filter(uuid=channel_uuid, is_active=True, channel_type=TWIML_API).exclude(org=None).first()
        if not channel:
            return HttpResponse("Channel with uuid: %s not found." % channel_uuid, status=404)

        if action == 'receive':

            org = channel.org
            client = org.get_twiml_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            sms = Msg.create_incoming(channel, URN.from_tel(request.POST['From']), request.POST['Body'])

            return HttpResponse("SMS Accepted: %d" % sms.id)

        return HttpResponse("Not Handled, unknown action", status=400)


class AfricasTalkingHandler(View):

    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(AfricasTalkingHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):<commit_msg>Add handler incoming call<commit_after># -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals

import json
import pytz
import requests
import xml.etree.ElementTree as ET

from datetime import datetime
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.files import File
from django.core.files.temp import NamedTemporaryFile
from django.db.models import Q
from django.http import HttpResponse, JsonResponse
from django.utils import timezone
from django.utils.dateparse import parse_datetime
from django.views.generic import View
from temba.api.models import WebHookEvent, SMS_RECEIVED
from temba.channels.models import Channel, PLIVO, SHAQODOON, YO, TWILIO_MESSAGING_SERVICE, AUTH_TOKEN, TELEGRAM, TWIML_API
from temba.contacts.models import Contact, URN, TEL_SCHEME
from temba.flows.models import Flow, FlowRun
from temba.orgs.models import NEXMO_UUID
from temba.msgs.models import Msg, HANDLE_EVENT_TASK, HANDLER_QUEUE, MSG_EVENT
from temba.triggers.models import Trigger
from temba.utils import json_date_to_datetime
from temba.utils.middleware import disable_middleware
from temba.utils.queues import push_task
from .tasks import fb_channel_subscribe
from twilio import twiml


class TwilioHandler(View):

    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(TwilioHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        return HttpResponse("ILLEGAL METHOD")

    def post(self, request, *args, **kwargs):
        from twilio.util import RequestValidator
        from temba.msgs.models import Msg

        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
        url = "https://" + settings.TEMBA_HOST + "%s" % request.get_full_path()

        call_sid = request.REQUEST.get('CallSid', None)
        direction = request.REQUEST.get('Direction', None)
        status = request.REQUEST.get('CallStatus', None)
        to_number = request.REQUEST.get('To', None)
        to_country = request.REQUEST.get('ToCountry', None)
        from_number = request.REQUEST.get('From', None)

        # Twilio sometimes sends un-normalized numbers
        if not to_number.startswith('+') and to_country:
            to_number, valid = URN.normalize_number(to_number, to_country)

        # see if it's a twilio call being initiated
        if to_number and call_sid and direction == 'inbound' and status == 'ringing':

            # find a channel that knows how to answer twilio calls
            channel = Channel.objects.filter(address=to_number, channel_type='T', role__contains='A', is_active=True).exclude(org=None).first()
            if not channel:
                raise Exception("No active answering channel found for number: %s" % to_number)

            client = channel.org.get_twilio_client()
            validator = RequestValidator(client.auth[1])
            signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')

            base_url = settings.TEMBA_HOST
            url = "https://%s%s" % (base_url, request.get_full_path())

            if validator.validate(url, request.POST, signature):
                from temba.ivr.models import IVRCall

                # find a contact for the one initiating us
                urn = URN.from_tel(from_number)
                contact = Contact.get_or_create(channel.org, channel.created_by, urns=[urn], channel=channel)
                urn_obj = contact.urn_objects[urn]

                flow = Trigger.find_flow_for_inbound_call(contact)

                call = IVRCall.create_incoming(channel, contact, urn_obj, flow, channel.created_by)
                call.update_status(request.POST.get('CallStatus', None),
                                   request.POST.get('CallDuration', None))
                call.save()

                if flow:
                    FlowRun.create(flow, contact.pk, call=call)
                    response = Flow.handle_call(call, {})
                    return HttpResponse(unicode(response))
                else:

                    # we don't have an inbound trigger to deal with this call.
                    response = twiml.Response()

                    # say nothing and hangup, this is a little rude, but if we reject the call, then
                    # they'll get a non-working number error. We send 'busy' when our server is down
                    # so we don't want to use that here either.
                    response.say('')
                    response.hangup()

                    # if they have a missed call trigger, fire that off
                    Trigger.catch_triggers(contact, Trigger.TYPE_MISSED_CALL, channel)

                    # either way, we need to hangup now
                    return HttpResponse(unicode(response))

        action = request.GET.get('action', 'received')
        # this is a callback for a message we sent
        if action == 'callback':
            smsId = request.GET.get('id', None)
            status = request.POST.get('SmsStatus', None)

            # get the SMS
            sms = Msg.all_messages.select_related('channel').get(id=smsId)

            # validate this request is coming from twilio
            org = sms.org
            client = org.get_twilio_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            # queued, sending, sent, failed, or received.
            if status == 'sent':
                sms.status_sent()
            elif status == 'delivered':
                sms.status_delivered()
            elif status == 'failed':
                sms.fail()

            return HttpResponse("", status=200)

        # this is an incoming message that is being received by Twilio
        elif action == 'received':
            channel = Channel.objects.filter(address=to_number, is_active=True).exclude(org=None).first()
            if not channel:
                raise Exception("No active channel found for number: %s" % to_number)

            # validate this request is coming from twilio
            org = channel.org
            client = org.get_twilio_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            body = request.POST['Body']
            urn = URN.from_tel(request.POST['From'])

            # process any attached media
            for i in range(int(request.POST.get('NumMedia', 0))):
                media_url = client.download_media(request.POST['MediaUrl%d' % i])
                path = media_url.partition(':')[2]
                Msg.create_incoming(channel, urn, path, media=media_url)

            if body:
                Msg.create_incoming(channel, urn, body)

            return HttpResponse("", status=201)

        return HttpResponse("Not Handled, unknown action", status=400)


class TwilioMessagingServiceHandler(View):
    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(TwilioMessagingServiceHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        return self.post(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        from twilio.util import RequestValidator
        from temba.msgs.models import Msg

        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
        url = "https://" + settings.HOSTNAME + "%s" % request.get_full_path()

        action = kwargs['action']
        channel_uuid = kwargs['uuid']

        channel = Channel.objects.filter(uuid=channel_uuid, is_active=True, channel_type=TWILIO_MESSAGING_SERVICE).exclude(org=None).first()
        if not channel:
            return HttpResponse("Channel with uuid: %s not found." % channel_uuid, status=404)

        if action == 'receive':

            org = channel.org
            client = org.get_twilio_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            Msg.create_incoming(channel, URN.from_tel(request.POST['From']), request.POST['Body'])

            return HttpResponse("", status=201)

        return HttpResponse("Not Handled, unknown action", status=400)


class TwimlAPIHandler(View):
    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(TwimlAPIHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        return self.post(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        from twilio.util import RequestValidator
        from temba.msgs.models import Msg

        signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')
        url = "https://" + settings.HOSTNAME + "%s" % request.get_full_path()

        call_sid = request.REQUEST.get('CallSid', None)
        direction = request.REQUEST.get('Direction', None)
        status = request.REQUEST.get('CallStatus', None)
        to_number = request.REQUEST.get('To', None)
        to_country = request.REQUEST.get('ToCountry', None)
        from_number = request.REQUEST.get('From', None)

        # Twilio sometimes sends un-normalized numbers
        if not to_number.startswith('+') and to_country:
            to_number, valid = URN.normalize_number(to_number, to_country)

        # see if it's a twilio call being initiated
        if to_number and call_sid and direction == 'inbound' and status == 'ringing':

            # find a channel that knows how to answer twilio calls
            channel = Channel.objects.filter(address=to_number, channel_type=TWIML_API, role__contains='A', is_active=True).exclude(org=None).first()
            if not channel:
                raise Exception("No active answering channel found for number: %s" % to_number)

            client = channel.org.get_twiml_client()
            validator = RequestValidator(client.auth[1])
            signature = request.META.get('HTTP_X_TWILIO_SIGNATURE', '')

            base_url = settings.TEMBA_HOST
            url = "https://%s%s" % (base_url, request.get_full_path())

            if validator.validate(url, request.POST, signature):
                from temba.ivr.models import IVRCall

                # find a contact for the one initiating us
                urn = URN.from_tel(from_number)
                contact = Contact.get_or_create(channel.org, channel.created_by, urns=[urn], channel=channel)
                urn_obj = contact.urn_objects[urn]

                flow = Trigger.find_flow_for_inbound_call(contact)

                call = IVRCall.create_incoming(channel, contact, urn_obj, flow, channel.created_by)
                call.update_status(request.POST.get('CallStatus', None),
                                   request.POST.get('CallDuration', None))
                call.save()

                if flow:
                    FlowRun.create(flow, contact.pk, call=call)
                    response = Flow.handle_call(call, {})
                    return HttpResponse(unicode(response))
                else:

                    # we don't have an inbound trigger to deal with this call.
                    response = twiml.Response()

                    # say nothing and hangup, this is a little rude, but if we reject the call, then
                    # they'll get a non-working number error. We send 'busy' when our server is down
                    # so we don't want to use that here either.
                    response.say('')
                    response.hangup()

                    # if they have a missed call trigger, fire that off
                    Trigger.catch_triggers(contact, Trigger.TYPE_MISSED_CALL, channel)

                    # either way, we need to hangup now
                    return HttpResponse(unicode(response))

        action = kwargs['action']
        channel_uuid = kwargs['uuid']

        if action == 'receive':

            channel = Channel.objects.filter(uuid=channel_uuid, is_active=True, channel_type=TWIML_API).exclude(org=None).first()
            if not channel:
                return HttpResponse("Channel with uuid: %s not found." % channel_uuid, status=404)

            client = channel.org.get_twiml_client()
            validator = RequestValidator(client.auth[1])

            if not validator.validate(url, request.POST, signature):
                # raise an exception that things weren't properly signed
                raise ValidationError("Invalid request signature")

            sms = Msg.create_incoming(channel, URN.from_tel(request.POST['From']), request.POST['Body'])

            return HttpResponse("SMS Accepted: %d" % sms.id)

        return HttpResponse("Not Handled, unknown action", status=400)


class AfricasTalkingHandler(View):

    @disable_middleware
    def dispatch(self, *args, **kwargs):
        return super(AfricasTalkingHandler, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
{'fraction_non_alphanumeric': 0.09778822344399211, 'fraction_numerical': 0.0027279976497251016, 'mean_word_length': 2.442855078745846, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 9, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '211471', 'n_tokens_mistral': 6704, 'n_tokens_neox': 6316, 'n_words': 1736}