def decorated(*args, **kwargs): print request.values if 'CallSid' not in request.values: return abort(401, 'Request must be a signed Twilio request.') if validate and False: validator = RequestValidator(settings.TWILIO_AUTH_TOKEN) sig_header = request.headers.get('X-Twilio-Signature', '') if request.method == 'POST': vparams = request.form vurl = request.url else: vparams = {} vurl = request.url # validator params are called URL, POST vars, and signature if not validator.validate(vurl, vparams, sig_header): return abort(401, 'Request signature could not be validated') # load the call from Mongo or create if one does not exist g.call = load_call(request.values['CallSid'], request.values) g.zipcode = read_context('zipcode', None) g.legislator = read_context('legislator', None) twilio_response = func(*args, **kwargs) return Response(str(twilio_response), mimetype='application/xml')
def subscribe_to_bill_updates(): r = twiml.Response() bill_id = read_context('bill_id') if not bill_id: r.redirect(url_for('.bills')) return r bill = data.get_bill_by_id(bill_id) if not bill: r.say("No bill was found matching %s" % bill_id) r.redirect(url_for('.bills')) return r if 'from' in g.call: params = { 'phone': g.call['from'], 'interest_type': 'item', 'item_type': 'bill', 'item_id': bill_id, 'source': 'call_on_congress', } if data.subscribe_to_bill_updates(**params): r.say('You have been subscribed. A confirmation message has been sent to %s.' % " ".join(g.call['from'][1:])) else: r.say('Sorry, there was an error subscribing you.') else: r.say('Sorry, we were unable to identify your phone number.') r.redirect(url_for('.bills')) return str(r)
def load_member_for(bioguide): for legislator in read_context('legislators', []): if legislator['bioguide_id'] == bioguide: write_context('legislator', legislator) return legislator legislator = data.legislator_by_bioguide(bioguide) write_context('legislator', legislator) return legislator
def member_bio(): """Biography for a specific member of congress""" r = twiml.Response() bioguide = g.request_params['bioguide_id'] legislator = read_context('legislator', load_member_for(bioguide)) with r.gather(numDigits=1, timeout=1, action=url_for('.member_bio', bioguide_id=bioguide)) as rg: rg.say(data.legislator_bio(legislator) or 'There is no biography available for this legislator.') return next_action(r, default=url_for('.member', bioguide_id=bioguide))
def call_member(): """Calls the DC office of a member of congress""" r = twiml.Response() bioguide = g.request_params['bioguide_id'] legislator = read_context('legislator', load_member_for(bioguide)) r.say("Connecting you to %s at %s" % (legislator['fullname'], legislator['phone'])) with r.dial() as rd: rd.number(legislator['phone']) return r
def member_donors(): """Top campaign donors for a member of congress""" r = twiml.Response() bioguide = g.request_params['bioguide_id'] legislator = read_context('legislator', load_member_for(bioguide)) contribs = data.top_contributors(legislator) script = " ".join("%(name)s contributed $%(total_amount)s.\n" % c for c in contribs) with r.gather(numDigits=1, timeout=1, action=url_for('.member_donors', bioguide_id=bioguide)) as rg: rg.say(script) return next_action(r, default=url_for('.member'))
def member_votes(): """Recent votes by a member of congress""" r = twiml.Response() bioguide = g.request_params['bioguide_id'] legislator = read_context('legislator', load_member_for(bioguide)) votes = data.recent_votes(legislator) script = " ".join("On %(question)s. Voted %(voted)s. . The vote %(result)s.\t" % v for v in votes) with r.gather(numDigits=1, timeout=1, action=url_for('.member_votes', bioguide_id=bioguide)) as rg: rg.say("Recent votes for %s. %s" % (legislator['fullname'], script)) return next_action(r, default=url_for('.member', bioguide_id=bioguide))
def member(): """Menu for a specific member of congress""" r = twiml.Response() bioguide = g.request_params['bioguide_id'] legislator = read_context('legislator', load_member_for(bioguide)) if 'Digits' in g.request_params.keys(): return handle_selection(r, menu='member', selection=g.request_params['Digits'], params={'bioguide_id': bioguide}) r.say(MENU['member']['name'] % legislator['fullname']) with r.gather(numDigits=1, timeout=settings.INPUT_TIMEOUT, action=url_for('.member', bioguide_id=bioguide)) as rg: rg.say("""Press 1 to hear a short biography. Press 2 for a list of top campaign donors. Press 3 for recent votes in congress. Press 4 to call this representative's Capitol Hill office.""") rg.say("""To return to the previous menu, press 9.""") r.redirect(url_for('.member', bioguide_id=bioguide)) return r
def select_bill(): """Meta-route for handling multiple bills returned from search""" r = twiml.Response() query = {} bills = read_context('bills') if 'Digits' in g.request_params.keys() and bills: if g.request_params['Digits'] == '0': flush_context('bills') r.redirect(url_for('.search_bills')) try: sel = int(g.request_params['Digits']) bill = bills[sel - 1] query.update(bill_id=bill['bill_id']) r.redirect(url_for('.bill', **query)) return r except: r.say("No bill matched your selection.") r.redirect(url_for('.search_bills', **query)) return r
def bioguide_selection(): """Ensures a Bioguide ID is present in request params before proceeding with call flow. This is not stored in the context, only passed in params. Logic as follows: - If a get param is sent, return. - If a list of possible legislators is stored in context, and a choice was passed, append the choice's Bioguide ID to params and return. - If no list of legislators is present in context, prompt for zipcode and load legislators, then prompt for a selection. """ r = twiml.Response() # Handle twimlet-style params if 'bioguide_id' in g.request_params.keys(): digits = g.request_params.get('Digits') if digits == '9': if re.search(r'member\/[\w\d\/]+', request.path): r.redirect(url_for('.member', bioguide_id=g.request_params['bioguide_id'])) else: del g.request_params['bioguide_id'] r.redirect(url_for('.member')) return r elif digits == '0': r.redirect(url_for('.index')) return r return True # If Digits = 0, we're entering a new zip or going back if g.request_params.get('Digits') == '0': if len(read_context('legislators', [])): flush_context('zipcode') flush_context('legislators') r.redirect(url_for('.member')) return r else: r.redirect(url_for('.index')) return r # Make sure there's a legislators list in the call context. # If not, short-circuit to zip collection and repost to get legislator list # before prompting for a selection. legislators = read_context('legislators', []) if 'Digits' in g.request_params.keys() and len(legislators): if len(legislators) < 8 and g.request_params['Digits'] == '9': r.redirect(url_for('.index')) return r sel = int(g.request_params['Digits']) del g.request_params['Digits'] try: legislator = read_context('legislators')[sel - 1] g.request_params['bioguide_id'] = legislator['bioguide_id'] return True except: del g.request_params['Digits'] r.say('%d is not a valid selection, please try again.' % sel) # If we don't have a bioguide, or legislators, or a zip selection, # skip this and get a zip code first. if not len(legislators) and not get_zip() and not 'Digits' in g.request_params.keys(): return zipcode_selection() # If we do have a zip code selection, store it before trying to get legislators. if not len(legislators) and not get_zip(): zipcode_selection() # If we have a zip and no legislators, load them. if not len(legislators): load_members_for(get_zip()) legislators = read_context('legislators', []) # If there are legislators, prompt for a choice. If still nothing, fail and get a new zip. if len(legislators): with r.gather(numDigits=1, timeout=settings.INPUT_TIMEOUT) as rg: if len(legislators) > 3: rg.say("""Since your zip code covers more than one congressional district, you will be provided with a list of all possible legislators that may represent you. Please select from the following names:""") else: rg.say("""We identified your representatives in Congress.""") rg.say("""Please select from the following:""") options = [(l['fullname'], l['bioguide_id']) for l in legislators] script = " ".join("Press %i for %s." % (index + 1, o[0]) for index, o in enumerate(options)) script += " Press 0 to enter a new zip code." if len(legislators) < 8: script += " Press 9 to return to the previous menu." rg.say(script) else: r.say("We were unable to locate any representatives for") r.say("%s." % get_zip()) flush_context('zipcode') try: del g.request_params['Digits'] except: pass r.redirect(request.path) return r