def buildVotesForBill(self, billId): rawVotes = congress.votes(bill_id=billId, roll_type="On Passage", fields="voter_ids") if rawVotes is None: return ids = rawVotes[0]["voter_ids"] for key, value in ids.iteritems(): self.lastVoteId += 1 legislator = None # Create vote obj for each individual vote = {"vote": value, "bill": self.bills[billId]} # if we have a legislator for that id if self.legislators.get(key) != None: legislator = self.legislators[key] # Add it to the vote vote["legislator"] = legislator vote["chamber"] = legislator["chamber"] legislator.keys() # Add vote to the legislator legislator["votes"].append(vote) self.bills[billId]["votes"].append(vote) self.votes[self.lastVoteId] = vote
def load_data(self, since=None): if not since: res = self.db.votes.aggregate( {'$group': { '_id': '', 'last': { '$max': '$voted_at' } }}) since = res['result'][0]['last'] if res['result'] else day_before( yesterday()) votes = congress.votes(voted_at__gte=since.isoformat() + 'Z', fields='roll_id,vote_type,bill,voted_at,result', per_page=200) for vote in votes: if self.db.votes.find_one({'roll_id': vote['roll_id']}) is None: obj = self.db.Vote() obj.roll_id = vote['roll_id'] obj.type = vote['vote_type'] obj.voted_at = parse_date(vote['voted_at']) obj.result = vote['result'] if 'bill' in vote: obj.bill_id = vote['bill']['bill_id'] obj.sponsor_id = vote['bill']['sponsor_id'] obj.save()
def buildVotesForBill(self, billId): rawVotes = congress.votes(bill_id=billId, roll_type='On Passage', fields='voter_ids') if rawVotes is None: return ids = rawVotes[0]['voter_ids'] for key, value in ids.iteritems(): self.lastVoteId += 1 legislator = None # Create vote obj for each individual vote = {'vote': value, 'bill': self.bills[billId]} # if we have a legislator for that id if self.legislators.get(key) != None: legislator = self.legislators[key] # Add it to the vote vote['legislator'] = legislator vote['chamber'] = legislator['chamber'] legislator.keys() # Add vote to the legislator legislator['votes'].append(vote) self.bills[billId]['votes'].append(vote) self.votes[self.lastVoteId] = vote
def get(self): if self.current_user not in settings.get('staff'): self.redirect('/') # Sunlight API pukes on null args, so sanitize kwargs = {'per_page': 50} # Max 50 results form = self.get_votes_form() for k, v in form.iteritems(): if v: kwargs[k] = v # Query Sunlight API print kwargs #congress2 = PagingService(congress) #votes = list(congress2.votes(**kwargs)) votes = congress.votes(**kwargs) # Post-query logic if not votes: err = 'No search results, try again' return self.render('admin/votes.html', form=form, err=err) if len(votes) > 1: msg = 'Showing %s results:' % len(votes) # TODO: returns max 50 results on first page. Give option to search further pages else: msg = 'Please confirm that this is the correct vote' return self.render('admin/votes.html', msg=msg, votes=votes, form=form)
def tweet(request): vote = request.GET # assumes request comes from votes(request) reps_account_placeholder = "@[representative's account]" choice_placeholder = '[yes/no]' tweet_beginning = "%s voted %s on " % (reps_account_placeholder, choice_placeholder) if request.method == 'POST': # If the form has been submitted... form = TweetForm(request.POST) if not form.is_valid(): error = 'Submitted invalid tweet!' return render_to_response('tweet.html', {'error': error, 'tweet_beginning': tweet_beginning, 'vote': vote, 'form':form}, context_instance=RequestContext(request)) else: # Create base tweet tweet_text = form.cleaned_data['text'] tweet_template = tweet_beginning + tweet_text # Get votes for each politician from Sunlight kwargs = {'fields': 'voter_ids'} for k, v in request.GET.iteritems(): if v: kwargs[k] = v individual_votes = congress.votes(**kwargs) if len(individual_votes) != 1: print 'Error finding votes' return #TODO figure out error handling or better transfer method individual_votes = individual_votes[0]['voter_ids'] # returns a dict with bioguide_ids for keys # Tweet for every applicable politician for twitter_ftv in Twitter_FTV.objects.all().exclude(handle="FollowTheVote"): p = twitter_ftv.politician # Hierarchy of name choosing if len(p.brief_name()) <= 16: name = p.brief_name() elif p.twitter: name = twitter elif len(p.last_name) <= 16: name = p.last_name elif p.title == 'sen': name = "Senator" else: name = "Representative" # Find corresponding vote if p.portrait_id in individual_votes: choice = individual_votes[p.portrait_id] if choice == 'Yea': choice = 'YES' elif choice == 'Nay': choice == 'NO' tweet = tweet_template.replace(reps_account_placeholder, name).replace(choice_placeholder, choice) twitter_ftv.tweet(tweet) return render_to_response('admin.html', {'msg': 'All accounts tweeted successfully!'}, context_instance=RequestContext(request)) else: form = TweetForm() return render_to_response('tweet.html', {'tweet_beginning': tweet_beginning, 'vote': vote, 'form':form}, context_instance=RequestContext(request))
def votes(request): if request.method == 'POST': # If the form has been submitted... form = VotesForm(request.POST) # A form bound to the POST data if form.is_valid(): # Sunlight API pukes on null args, so sanitize kwargs = {'per_page': 50} for k, v in form.cleaned_data.items(): if v: kwargs[k] = v # Query Sunlight API votes = congress.votes(**kwargs) # Post-query logic if not votes: error = 'No search results, try again' return render_to_response('votes.html', {'error': error, 'form': form}, context_instance=RequestContext(request)) if len(votes) > 1: message = 'Found %s results, please choose the correct one:' % len(votes) # TODO: returns max 50 results on first page. Give option to search further pages else: message = 'Please confirm that this is the correct vote' return render_to_response('votes.html', {'message': message, 'votes': votes}, context_instance=RequestContext(request)) else: form = VotesForm() # An unbound form message = 'What shall we tweet about? Search the Congressional Archives' return render_to_response('votes.html', {'form': form, 'message': message}, context_instance=RequestContext(request))
def buildVotesForBill(self, billId): rawVotes = congress.votes(bill_id=billId, roll_type='On Passage', fields='voter_ids') if rawVotes is None: return ids = rawVotes[0]['voter_ids'] for key, value in ids.iteritems(): self.lastVoteId += 1 legislator = None # Create vote obj for each individual vote = { 'vote': value, 'bill': self.bills[billId] } # if we have a legislator for that id if self.legislators.get(key) != None: legislator = self.legislators[key] # Add it to the vote vote['legislator'] = legislator vote['chamber'] = legislator['chamber'] legislator.keys() # Add vote to the legislator legislator['votes'].append(vote) self.bills[billId]['votes'].append(vote) self.votes[self.lastVoteId] = vote
def voted_for(self, score_adjustment, roll_ids): """ Checks for aye votes on one or more roll call votes """ (adjustment_desc, adjustment) = self._get_adjustment_desc(score_adjustment) for roll_id in roll_ids: votes = congress.votes(roll_id=roll_id, fields='voters') for legislator in self.scores: score = 0 if votes[0]['voters'].get(legislator, {'vote': 'not present in data'})['vote'].lower().strip() == 'yea': score = adjustment self.scores[legislator]['%s (%s%s)' % (adjustment_desc, (adjustment > 0) and '+' or '', adjustment)] = score
def voted_for(self, score_adjustment, roll_ids): """ Checks for aye votes on one or more roll call votes """ (adjustment_desc, adjustment) = self._get_adjustment_desc(score_adjustment) for roll_id in roll_ids: votes = congress.votes(roll_id=roll_id, fields="voters") for legislator in self.scores: score = 0 if votes[0]["voters"].get(legislator, {"vote": "not present in data"})["vote"].lower().strip() == "yea": score = adjustment self.scores[legislator][ "%s (%s%s)" % (adjustment_desc, (adjustment > 0) and "+" or "", adjustment) ] = score
def load_data(self, since=None): if not since: res = self.db.votes.aggregate({'$group': {'_id': '', 'last': {'$max': '$voted_at'}}}) since = res['result'][0]['last'] if res['result'] else day_before(yesterday()) votes = congress.votes(voted_at__gte=since.isoformat() + 'Z', fields='roll_id,vote_type,bill,voted_at,result', per_page=200) for vote in votes: if self.db.votes.find_one({'roll_id': vote['roll_id']}) is None: obj = self.db.Vote() obj.roll_id = vote['roll_id'] obj.type = vote['vote_type'] obj.voted_at = parse_date(vote['voted_at']) obj.result = vote['result'] if 'bill' in vote: obj.bill_id = vote['bill']['bill_id'] obj.sponsor_id = vote['bill']['sponsor_id'] obj.save()
def post(self): if self.current_user not in settings.get('staff'): return self.redirect('/') vote = self.get_vote() tweet_beginning = self.get_tweet_beginning() tweet_text = self.get_argument('tweet_text', '') # Check if rePOSTing. I did this once and it doesn't break anything # but fails when trying to tweet, so sets tweet document to 0 accounts tweeted existing_tweet = tweetdb.find_one({'vote': vote}) if existing_tweet: return self.redirect('admin/?err=tweet_exists') if len( tweet_text ) > 110: # poorly hardcoded. calculated from get_tweet_beginning() err = 'Some tweets will exceed 140 characters in length!' return self.render('admin/tweet.html', err=err, tweet_beginning=tweet_beginning, vote=vote, form=self.get_tweet_form()) else: vote['fields'] = 'voter_ids' individual_votes = congress.votes(**vote) if len(individual_votes) != 1: print 'Error finding votes' raise Exception individual_votes = individual_votes[0][ 'voter_ids'] # returns a dict with bioguide_ids for keys # Tweet for every applicable politician. Yes, this is suboptimal tweeted = {} # Track successfully tweeted accounts... failed = {} # and those that failed for p in Politician.objects(): # Hierarchy of name choosing if p.twitter: name = "@" + p.twitter elif len(p.brief_name()) <= 16: name = p.brief_name() elif len(p.last_name) <= 16: name = p.last_name elif p.title == 'Sen': name = "Senator" else: name = "Representative" # Find corresponding vote if p.bioguide_id in individual_votes: choice = individual_votes[p.bioguide_id] if choice == 'Yea': choice = 'YES' elif choice == 'Nay': choice = 'NO' elif choice == 'Not Voting': choice = 'abstained' # Turn template into actual tweet and tweet! tweet_template = tweet_beginning + tweet_text # Further down replace tweet = tweet_template.replace(REPS_ACCOUNT_PLACEHOLDER, name).replace( CHOICE_PLACEHOLDER, choice) if choice == 'abstained': tweet = tweet.replace( 'voted ', '') # get rid of voting verb if abstained success = p.tweet(tweet) # If successfull tweeted, save for entry to database if success: tweeted[p.bioguide_id] = choice else: failed[p.bioguide_id] = choice logging.info(len(tweeted)) logging.info(len(failed)) # endfor p in Politician.objects(): # Save to database save_tweet = { 'datetime': datetime.datetime.now(), 'vote': vote, 'tweeted': tweeted, # Who actually had FTV accounts, i.e. actually tweeted 'tweet_template': tweet_template, 'placeholders': { 'reps_account_placeholder': REPS_ACCOUNT_PLACEHOLDER, 'choice_placeholder': CHOICE_PLACEHOLDER }, 'tweet': tweet, # A sample tweet (always from last rep in database to tweet) 'individual_votes': individual_votes, 'admin': self.current_user } tweetdb.save(save_tweet) logging.info('saved tweet') # Email admins subject = '%s tweeted!' % self.current_user text_body = tweet_template for sn in settings.get('staff'): admin = userdb.get_user_by_screen_name(sn) try: self.send_email(admin['email_address'], subject, text_body) except: print 'Failed to send email to admin %s' % admin['user'][ 'username'] pass if len(failed) is 0: return self.redirect('/admin?msg=tweet_success') else: return self.redirect( '/admin?msg=tweet_success&num_accounts_failed=%s' % len(failed))