Exemple #1
0
def make_single():
    params, campaign = parse_params(request)

    if not params or not campaign:
        abort(400)

    i = int(request.values.get('call_index', 0))
    params['call_index'] = i

    (uid, prefix) = parse_target(params['targetIds'][i])
    (current_target, cached) = Target.get_uid_or_cache(uid, prefix)
    if cached:
        # save Target to database
        db.session.add(current_target)
        db.session.commit()

    resp = twilio.twiml.Response()

    if not current_target.number:
        play_or_say(resp, campaign.audio('msg_invalid_location'))
        return str(resp)

    target_phone = current_target.number.e164  # use full E164 syntax here
    play_or_say(resp,
                campaign.audio('msg_target_intro'),
                title=current_target.title,
                name=current_target.name)

    if current_app.debug:
        current_app.logger.debug(
            'Call #{}, {} ({}) from {} in call.make_single()'.format(
                i, current_target.name, target_phone, params['userPhone']))

    userPhone = PhoneNumber(params['userPhone'], params['userCountry'])

    resp.dial(target_phone,
              callerId=userPhone.e164,
              timeLimit=current_app.config['TWILIO_TIME_LIMIT'],
              timeout=current_app.config['TWILIO_TIMEOUT'],
              hangupOnStar=True,
              action=url_for('call.complete', **params))

    return str(resp)
Exemple #2
0
def make_single():
    params, campaign = parse_params(request)

    if not params or not campaign:
        abort(400)

    i = int(request.values.get('call_index', 0))
    params['call_index'] = i

    (uid, prefix) = parse_target(params['targetIds'][i])
    (current_target, cached) = Target.get_or_cache_key(uid, prefix)
    if cached:
        # save Target to database
        db.session.add(current_target)
        db.session.commit()

    resp = VoiceResponse()

    if not current_target.number:
        play_or_say(resp, campaign.audio('msg_invalid_location'),
            lang=campaign.language_code)
        return str(resp)

    if current_target.offices:
        if campaign.target_offices == TARGET_OFFICE_DISTRICT:
            office = random.choice(current_target.offices)
            target_phone = office.number
        elif campaign.target_offices == TARGET_OFFICE_BUSY:
            # TODO keep track of which ones we have tried
            undialed_offices = current_target.offices
            # then pick a random one
            office = random.choice(undialed_offices)
            target_phone = office.number
        #elif campaign.target_offices == TARGET_OFFICE_CLOSEST:
        #   office = find_closest(current_target.offices, params['userLocation'])
        #   target_phone = office.phone
        else:
            office = None
            target_phone = current_target.number
    else:
        office = None
        target_phone = current_target.number
        
    play_or_say(resp, campaign.audio('msg_target_intro'),
        title=current_target.title,
        name=current_target.name,
        office_type = office.name if office else '',
        lang=campaign.language_code)

    if current_app.debug:
        current_app.logger.debug(u'Call #{}, {} ({}) from {} in call.make_single()'.format(
            i, current_target.name, target_phone.e164, params['userPhone']))

    try:
        parsed = PhoneNumber(params['userPhone'], params['userCountry'])
        userPhone = parsed.e164
    except phonenumbers.NumberParseException:
        current_app.logger.error('Unable to parse %(userPhone)s for %(userCountry)s' % params)
        # press onward, but we may not be able to actually dial
        userPhone = params['userPhone']

    # sending a twiml.Number to dial init will not nest properly
    # have to add it after creation
    d = Dial(None, caller_id=userPhone,
              time_limit=current_app.config['TWILIO_TIME_LIMIT'],
              timeout=current_app.config['TWILIO_TIMEOUT'], hangup_on_star=True,
              action=url_for('call.complete', **params)) \
        .number(target_phone.e164, sendDigits=target_phone.extension)
    resp.append(d)

    return str(resp)
Exemple #3
0
def create():
    """
    Places a phone call to a user, given a country, phone number, and campaign.

    Required Params:
        userPhone
        campaignId
    Optional Params:
        userCountry (defaults to US)
        userLocation (zipcode)
        targetIds
        record (boolean)
        ref (string)
    """
    # parse the info needed to make the call
    params, campaign = parse_params(request)

    # find outgoing phone number in same country as user
    phone_numbers = campaign.phone_numbers(params['userCountry'])

    if not phone_numbers:
        msg = "no numbers available for campaign %(campaignId)s in %(userCountry)s" % params
        return abort(400, msg)

    # validate phonenumber for country
    try:
        parsed = PhoneNumber(params['userPhone'], params['userCountry'])
        userPhone = parsed.e164
    except phonenumbers.NumberParseException:
        current_app.logger.error('Unable to parse %(userPhone)s for %(userCountry)s' % params)
        # press onward, but we may not be able to actually dial
        userPhone = params['userPhone']

    if Blocklist.user_blocked(params['userPhone'], params['userIPAddress'], user_country=params['userCountry']):
        abort(429, {'kthx': 'bai'}) # submission tripped blocklist

    if campaign.status == 'archived':
        result = jsonify(campaign=campaign.status)
        return result

    # compute campaign targeting now, to return to calling page
    if campaign.segment_by == SEGMENT_BY_CUSTOM:
        targets_list = [t for t in campaign.target_set]
        if campaign.target_ordering == 'shuffle':
            # do randomization now
            random.shuffle(targets_list)
            # limit to maximum
            if campaign.call_maximum:
                targets_list = targets_list[:campaign.call_maximum]
            # save to params so order persists for this caller
            params['targetIds'] = [t.uid for t in targets_list]
        target_response = {
            'segment': 'custom',
            'objects': [{'name': t.name, 'title': t.title, 'phone': t.number.e164} for t in targets_list]
        }
    else:
        target_response = {
            'segment': campaign.segment_by,
            'display': campaign.targets_display()
        }

    # start call session for user
    try:
        from_number = random.choice(phone_numbers)

        call_session_data = {
            'campaign_id': campaign.id,
            'location': params['userLocation'],
            'from_number': from_number,
            'direction': 'outbound'
        }
        if current_app.config['LOG_PHONE_NUMBERS']:
            call_session_data['phone_number'] = params['userPhone']
            # user phone numbers are hashed by the init method
            # but some installations may not want to log at all

        call_session = Session(**call_session_data)
        if 'ref' in request.values:
            call_session.referral_code = request.values.get('ref')[:64]
        db.session.add(call_session)
        db.session.commit()

        params['sessionId'] = call_session.id

        # initiate outbound call
        call = current_app.config['TWILIO_CLIENT'].calls.create(
            to=userPhone,
            from_=from_number,
            url=url_for('call.connection', _external=True, **params),
            timeout=current_app.config['TWILIO_TIMEOUT'],
            status_callback=url_for("call.status_callback", _external=True, **params),
            status_callback_event=['ringing','completed'],
            record=request.values.get('record', False))

        if campaign.embed:
            script = campaign.embed.get('script')
            redirect = campaign.embed.get('redirect')
        else:
            script = ''
            redirect = ''
        result = jsonify(campaign=campaign.status, call=call.status, script=script, redirect=redirect,
            fromNumber=from_number, targets=target_response)
        result.status_code = 200 if call.status != 'failed' else 500
    except TwilioRestException, err:
        twilio_error = stripANSI(err.msg)
        abort(400, twilio_error)
Exemple #4
0
def create():
    """
    Places a phone call to a user, given a country, phone number, and campaign.

    Required Params:
        userPhone
        campaignId
    Optional Params:
        userCountry (defaults to US)
        userLocation (zipcode)
        targetIds
    """
    # parse the info needed to make the call
    params, campaign = parse_params(request)

    # find outgoing phone number in same country as user
    phone_numbers = campaign.phone_numbers(params['userCountry'])

    if not phone_numbers:
        msg = "no numbers available for campaign %(campaignId)s in %(userCountry)s" % params
        return abort(400, msg)

    # validate phonenumber for country
    try:
        parsed = PhoneNumber(params['userPhone'], params['userCountry'])
        userPhone = parsed.e164
    except phonenumbers.NumberParseException:
        current_app.logger.error(
            'Unable to parse %(userPhone)s for %(userCountry)s' % params)
        # press onward, but we may not be able to actually dial
        userPhone = params['userPhone']

    # start call session for user
    try:
        from_number = random.choice(phone_numbers)

        call_session_data = {
            'campaign_id': campaign.id,
            'location': params['userLocation'],
            'from_number': from_number,
        }
        if current_app.config['LOG_PHONE_NUMBERS']:
            call_session_data['phone_number'] = params['userPhone']
            # user phone numbers are hashed by the init method
            # but some installations may not want to log at all

        call_session = Session(**call_session_data)
        db.session.add(call_session)
        db.session.commit()

        params['sessionId'] = call_session.id

        # initiate outbound call
        call = current_app.config['TWILIO_CLIENT'].calls.create(
            to=userPhone,
            from_=from_number,
            url=url_for('call.connection', _external=True, **params),
            timeLimit=current_app.config['TWILIO_TIME_LIMIT'],
            timeout=current_app.config['TWILIO_TIMEOUT'],
            status_callback=url_for("call.complete_status",
                                    _external=True,
                                    **params))

        if campaign.embed:
            script = campaign.embed.get('script')
        else:
            script = ''
        result = jsonify(campaign=campaign.status,
                         call=call.status,
                         script=script)
        result.status_code = 200 if call.status != 'failed' else 500
    except TwilioRestException, err:
        twilio_error = stripANSI(err.msg)
        abort(400, twilio_error)