util.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. # -*- coding: utf-8 -*-
  2. # Natural Language Toolkit: Twitter client
  3. #
  4. # Copyright (C) 2001-2020 NLTK Project
  5. # Author: Ewan Klein <ewan@inf.ed.ac.uk>
  6. # Lorenzo Rubio <lrnzcig@gmail.com>
  7. # URL: <http://nltk.org/>
  8. # For license information, see LICENSE.TXT
  9. """
  10. Authentication utilities to accompany :module:`twitterclient`.
  11. """
  12. import os
  13. import pprint
  14. from twython import Twython
  15. def credsfromfile(creds_file=None, subdir=None, verbose=False):
  16. """
  17. Convenience function for authentication
  18. """
  19. return Authenticate().load_creds(
  20. creds_file=creds_file, subdir=subdir, verbose=verbose
  21. )
  22. class Authenticate(object):
  23. """
  24. Methods for authenticating with Twitter.
  25. """
  26. def __init__(self):
  27. self.creds_file = "credentials.txt"
  28. self.creds_fullpath = None
  29. self.oauth = {}
  30. try:
  31. self.twitter_dir = os.environ["TWITTER"]
  32. self.creds_subdir = self.twitter_dir
  33. except KeyError:
  34. self.twitter_dir = None
  35. self.creds_subdir = None
  36. def load_creds(self, creds_file=None, subdir=None, verbose=False):
  37. """
  38. Read OAuth credentials from a text file.
  39. ::
  40. File format for OAuth 1
  41. =======================
  42. app_key=YOUR_APP_KEY
  43. app_secret=YOUR_APP_SECRET
  44. oauth_token=OAUTH_TOKEN
  45. oauth_token_secret=OAUTH_TOKEN_SECRET
  46. ::
  47. File format for OAuth 2
  48. =======================
  49. app_key=YOUR_APP_KEY
  50. app_secret=YOUR_APP_SECRET
  51. access_token=ACCESS_TOKEN
  52. :param str file_name: File containing credentials. ``None`` (default) reads\
  53. data from `TWITTER/'credentials.txt'`
  54. """
  55. if creds_file is not None:
  56. self.creds_file = creds_file
  57. if subdir is None:
  58. if self.creds_subdir is None:
  59. msg = (
  60. "Supply a value to the 'subdir' parameter or"
  61. + " set the TWITTER environment variable."
  62. )
  63. raise ValueError(msg)
  64. else:
  65. self.creds_subdir = subdir
  66. self.creds_fullpath = os.path.normpath(
  67. os.path.join(self.creds_subdir, self.creds_file)
  68. )
  69. if not os.path.isfile(self.creds_fullpath):
  70. raise OSError("Cannot find file {}".format(self.creds_fullpath))
  71. with open(self.creds_fullpath) as infile:
  72. if verbose:
  73. print("Reading credentials file {}".format(self.creds_fullpath))
  74. for line in infile:
  75. if "=" in line:
  76. name, value = line.split("=", 1)
  77. self.oauth[name.strip()] = value.strip()
  78. self._validate_creds_file(verbose=verbose)
  79. return self.oauth
  80. def _validate_creds_file(self, verbose=False):
  81. """Check validity of a credentials file."""
  82. oauth1 = False
  83. oauth1_keys = ["app_key", "app_secret", "oauth_token", "oauth_token_secret"]
  84. oauth2 = False
  85. oauth2_keys = ["app_key", "app_secret", "access_token"]
  86. if all(k in self.oauth for k in oauth1_keys):
  87. oauth1 = True
  88. elif all(k in self.oauth for k in oauth2_keys):
  89. oauth2 = True
  90. if not (oauth1 or oauth2):
  91. msg = "Missing or incorrect entries in {}\n".format(self.creds_file)
  92. msg += pprint.pformat(self.oauth)
  93. raise ValueError(msg)
  94. elif verbose:
  95. print('Credentials file "{}" looks good'.format(self.creds_file))
  96. def add_access_token(creds_file=None):
  97. """
  98. For OAuth 2, retrieve an access token for an app and append it to a
  99. credentials file.
  100. """
  101. if creds_file is None:
  102. path = os.path.dirname(__file__)
  103. creds_file = os.path.join(path, "credentials2.txt")
  104. oauth2 = credsfromfile(creds_file=creds_file)
  105. app_key = oauth2["app_key"]
  106. app_secret = oauth2["app_secret"]
  107. twitter = Twython(app_key, app_secret, oauth_version=2)
  108. access_token = twitter.obtain_access_token()
  109. tok = "access_token={}\n".format(access_token)
  110. with open(creds_file, "a") as infile:
  111. print(tok, file=infile)
  112. def guess_path(pth):
  113. """
  114. If the path is not absolute, guess that it is a subdirectory of the
  115. user's home directory.
  116. :param str pth: The pathname of the directory where files of tweets should be written
  117. """
  118. if os.path.isabs(pth):
  119. return pth
  120. else:
  121. return os.path.expanduser(os.path.join("~", pth))