# -*- coding: utf-8 -*- # Natural Language Toolkit: Twitter client # # Copyright (C) 2001-2018 NLTK Project # Author: Ewan Klein # Lorenzo Rubio # URL: # For license information, see LICENSE.TXT """ Authentication utilities to accompany :module:`twitterclient`. """ from __future__ import print_function import os import pprint from twython import Twython def credsfromfile(creds_file=None, subdir=None, verbose=False): """ Convenience function for authentication """ return Authenticate().load_creds(creds_file=creds_file, subdir=subdir, verbose=verbose) class Authenticate(object): """ Methods for authenticating with Twitter. """ def __init__(self): self.creds_file = 'credentials.txt' self.creds_fullpath = None self.oauth = {} try: self.twitter_dir = os.environ['TWITTER'] self.creds_subdir = self.twitter_dir except KeyError: self.twitter_dir = None self.creds_subdir = None def load_creds(self, creds_file=None, subdir=None, verbose=False): """ Read OAuth credentials from a text file. :: File format for OAuth 1 ======================= app_key=YOUR_APP_KEY app_secret=YOUR_APP_SECRET oauth_token=OAUTH_TOKEN oauth_token_secret=OAUTH_TOKEN_SECRET :: File format for OAuth 2 ======================= app_key=YOUR_APP_KEY app_secret=YOUR_APP_SECRET access_token=ACCESS_TOKEN :param str file_name: File containing credentials. ``None`` (default) reads\ data from `TWITTER/'credentials.txt'` """ if creds_file is not None: self.creds_file = creds_file if subdir is None: if self.creds_subdir is None: msg = "Supply a value to the 'subdir' parameter or" + \ " set the TWITTER environment variable." raise ValueError(msg) else: self.creds_subdir = subdir self.creds_fullpath = \ os.path.normpath(os.path.join(self.creds_subdir, self.creds_file)) if not os.path.isfile(self.creds_fullpath): raise OSError('Cannot find file {}'.format(self.creds_fullpath)) with open(self.creds_fullpath) as infile: if verbose: print('Reading credentials file {}'.format(self.creds_fullpath)) for line in infile: if '=' in line: name, value = line.split('=', 1) self.oauth[name.strip()] = value.strip() self._validate_creds_file(verbose=verbose) return self.oauth def _validate_creds_file(self, verbose=False): """Check validity of a credentials file.""" oauth1 = False oauth1_keys = ['app_key', 'app_secret', 'oauth_token', 'oauth_token_secret'] oauth2 = False oauth2_keys = ['app_key', 'app_secret', 'access_token'] if all(k in self.oauth for k in oauth1_keys): oauth1 = True elif all(k in self.oauth for k in oauth2_keys): oauth2 = True if not (oauth1 or oauth2): msg = 'Missing or incorrect entries in {}\n'.format(self.creds_file) msg += pprint.pformat(self.oauth) raise ValueError(msg) elif verbose: print('Credentials file "{}" looks good'.format(self.creds_file)) def add_access_token(creds_file=None): """ For OAuth 2, retrieve an access token for an app and append it to a credentials file. """ if creds_file is None: path = os.path.dirname(__file__) creds_file = os.path.join(path, 'credentials2.txt') oauth2 = credsfromfile(creds_file=creds_file) app_key = oauth2['app_key'] app_secret = oauth2['app_secret'] twitter = Twython(app_key, app_secret, oauth_version=2) access_token = twitter.obtain_access_token() tok = 'access_token={}\n'.format(access_token) with open(creds_file, 'a') as infile: print(tok, file=infile) def guess_path(pth): """ If the path is not absolute, guess that it is a subdirectory of the user's home directory. :param str pth: The pathname of the directory where files of tweets should be written """ if os.path.isabs(pth): return pth else: return os.path.expanduser(os.path.join("~", pth))