File size: 4,546 Bytes
d916065
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Natural Language Toolkit: Twitter client
#
# Copyright (C) 2001-2023 NLTK Project
# Author: Ewan Klein <[email protected]>
#         Lorenzo Rubio <[email protected]>
# URL: <https://www.nltk.org/>
# For license information, see LICENSE.TXT

"""

Authentication utilities to accompany `twitterclient`.

"""

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:
    """

    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(f"Cannot find file {self.creds_fullpath}")

        with open(self.creds_fullpath) as infile:
            if verbose:
                print(f"Reading credentials file {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 = f"Missing or incorrect entries in {self.creds_file}\n"
            msg += pprint.pformat(self.oauth)
            raise ValueError(msg)
        elif verbose:
            print(f'Credentials file "{self.creds_file}" looks good')


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 = f"access_token={access_token}\n"
    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))