├── .gitignore ├── NonTechnicalREADME.md ├── README.md ├── clone_data.py ├── main.py ├── requirements.txt ├── social.py └── tweet.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .env 3 | env 4 | data 5 | *.pyc -------------------------------------------------------------------------------- /NonTechnicalREADME.md: -------------------------------------------------------------------------------- 1 | 2 | - Download this code 3 | - Run: `git clone http://github.com/alexk307/tweet-a-legislator` 4 | - Download and install [Python 2.7](https://www.python.org/download/releases/2.7/) 5 | - Download and install [Virtualenv](https://virtualenv.pypa.io/en/stable/) 6 | - Run: `virtualenv env`. This will create your virtual environment 7 | - Run: `source env/bin/activate`. This is use your newly created environment 8 | - Run: `pip install -r requirements.txt`. This will install the dependencies needed for this project 9 | 10 | - Create a Twitter [Application](https://apps.twitter.com/) 11 | - Create a new file `.env` in this directory. 12 | - Add the following (fill in your credentials) 13 | ``` 14 | access_token_key= 15 | access_token_secret= 16 | consumer_key= 17 | consumer_secret= 18 | ``` 19 | - Run: `python main.py` 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tweet-a-legislator 2 | Tweets all U.S. Legislators on Twitter. Gets current legislator social media data from [congress-legislators](https://github.com/unitedstates/congress-legislators) and tweets your message to all legislators with a Twitter account. 3 | 4 | ![](http://i.imgur.com/nGePX5i.gif) 5 | 6 | 7 | ### Setup 8 | Create virtualenv, install `requirements.txt` 9 | 10 | ### Run 11 | `python main.py` 12 | 13 | ### Configure 14 | Set environment variables with Twitter App information or put them into a `.env` file. 15 | You'll need: 16 | - `access_token_key` 17 | - `access_token_secret` 18 | - `consumer_key` 19 | - `consumer_secret` 20 | 21 | Don't have these? Set up a Twitter [application](https://apps.twitter.com/) 22 | -------------------------------------------------------------------------------- /clone_data.py: -------------------------------------------------------------------------------- 1 | from git import Repo 2 | from shutil import rmtree 3 | from sys import exit 4 | 5 | 6 | DATA_DIR = './data' 7 | 8 | 9 | def _clear_data(): 10 | rmtree(DATA_DIR, ignore_errors=True) 11 | 12 | 13 | def clone(): 14 | _clear_data() 15 | print 'Cloning congress-legislators...' 16 | try: 17 | Repo.clone_from( 18 | 'git@github.com:unitedstates/congress-legislators.git', DATA_DIR 19 | ) 20 | except: 21 | print 'Unable to clone `congress-legislators`. Exiting...' 22 | exit() 23 | print 'Done' 24 | 25 | 26 | if __name__ == '__main__': 27 | clone() -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from clone_data import clone 2 | from social import get_information 3 | from tweet import Tweeter 4 | 5 | 6 | def get_tweet_body_from_user(): 7 | return raw_input('What would you like to say? [Reminder: Tweet body + ' 8 | '@mention of legislator must be <= 140 chars]\n') 9 | 10 | 11 | def main(): 12 | body = get_tweet_body_from_user() 13 | tweeter = Tweeter() 14 | clone() 15 | data = get_information() 16 | for legislator_id, legislator in data.iteritems(): 17 | name = legislator.get('name') 18 | job = legislator.get('job') 19 | party = legislator.get('party') 20 | title = '%s %s %s' % (party, job, name) 21 | twitter_handle = legislator.get('twitter') 22 | if twitter_handle is None: 23 | print '%s has no twitter account' % title 24 | continue 25 | 26 | handle = legislator.get('twitter') 27 | try: 28 | tweeter.tweet(handle, body) 29 | except Exception as e: 30 | print 'Unable to post tweet: %s' % str(e) 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | appdirs==1.4.0 2 | click==6.7 3 | future==0.16.0 4 | gitdb2==2.0.0 5 | GitPython==2.1.1 6 | oauthlib==2.0.1 7 | packaging==16.8 8 | pyparsing==2.1.10 9 | python-dotenv==0.6.2 10 | python-twitter==3.2.1 11 | PyYAML==3.12 12 | requests==2.13.0 13 | requests-oauthlib==0.7.0 14 | six==1.10.0 15 | smmap2==2.0.1 16 | -------------------------------------------------------------------------------- /social.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | from clone_data import DATA_DIR 3 | 4 | 5 | CURRENT_LEGISLATORS = 'legislators-current.yaml' 6 | LEGISLATORS_SOCIAL = 'legislators-social-media.yaml' 7 | 8 | 9 | def _get_path_to_file(filename): 10 | if not DATA_DIR.endswith('/'): 11 | path = DATA_DIR + '/' 12 | else: 13 | path = DATA_DIR 14 | return '%s%s' % (path, filename) 15 | 16 | 17 | def get_information(): 18 | officials = {} 19 | with file(_get_path_to_file(CURRENT_LEGISLATORS), 'r') as f: 20 | for official in yaml.load(f.read()): 21 | current_term = official.get('terms', [])[-1] 22 | officials[official.get('id', {}).get('govtrack')] = { 23 | 'name': official.get('name', {}).get('official_full'), 24 | 'party': current_term.get('party'), 25 | 'job': current_term.get('type') 26 | } 27 | 28 | with file(_get_path_to_file(LEGISLATORS_SOCIAL), 'r') as f: 29 | for official in yaml.load(f.read()): 30 | govtrack_id = official.get('id', {}).get('govtrack') 31 | if govtrack_id in officials: 32 | officials[govtrack_id]['twitter'] = \ 33 | official.get('social', {}).get('twitter') 34 | 35 | return officials 36 | 37 | -------------------------------------------------------------------------------- /tweet.py: -------------------------------------------------------------------------------- 1 | from twitter import Api, TwitterError 2 | from dotenv import load_dotenv, find_dotenv 3 | 4 | import os 5 | 6 | 7 | load_dotenv(find_dotenv()) 8 | 9 | 10 | class Tweeter(object): 11 | 12 | def __init__(self): 13 | creds = { 14 | 'consumer_key': os.environ.get('consumer_key'), 15 | 'consumer_secret': os.environ.get('consumer_secret'), 16 | 'access_token_key': os.environ.get('access_token_key'), 17 | 'access_token_secret': os.environ.get('access_token_secret') 18 | } 19 | 20 | for name, cred in creds.iteritems(): 21 | if cred is None: 22 | raise Exception( 23 | 'Misconfiguration error, Twitter creds missing %s' % name) 24 | self.api = Api(**creds) 25 | 26 | def tweet(self, to, message): 27 | try: 28 | tweet_body = '@%s %s' % (to, message) 29 | self.api.PostUpdate(tweet_body) 30 | print 'Posted: %s' % tweet_body 31 | except TwitterError as e: 32 | print 'Unable to post: %s' % str(e) 33 | --------------------------------------------------------------------------------