Skip to content
This repository was archived by the owner on Aug 7, 2024. It is now read-only.

Commit f2dd2d3

Browse files
author
Jonathan Schultz
committed
Reworked @bryanlandia extension to allow application-only authentication.
1 parent 62bb5c6 commit f2dd2d3

1 file changed

Lines changed: 46 additions & 16 deletions

File tree

twitter/api.py

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import base64
2828
import re
2929
import requests
30-
from requests_oauthlib import OAuth1
30+
from requests_oauthlib import OAuth1, OAuth2
3131
import io
3232
import warnings
3333
from uuid import uuid4
@@ -146,6 +146,7 @@ def __init__(self,
146146
consumer_secret=None,
147147
access_token_key=None,
148148
access_token_secret=None,
149+
application_only_auth=False,
149150
input_encoding=None,
150151
request_headers=None,
151152
cache=DEFAULT_CACHE,
@@ -171,6 +172,9 @@ def __init__(self,
171172
access_token_secret (str):
172173
The oAuth access token's secret, also retrieved
173174
from the get_access_token.py run.
175+
application_only_auth:
176+
Use Application-Only Auth instead of User Auth.
177+
Defaults to False [Optional]
174178
input_encoding (str, optional):
175179
The encoding used to encode input strings.
176180
request_header (dict, optional):
@@ -256,16 +260,13 @@ def __init__(self,
256260
"strongly advised to increase it above 16384"
257261
))
258262

259-
if consumer_key is not None and (access_token_key is None or
260-
access_token_secret is None):
261-
print('Twitter now requires an oAuth Access Token for API calls. '
262-
'If you\'re using this library from a command line utility, '
263-
'please run the included get_access_token.py tool to '
264-
'generate one.', file=sys.stderr)
263+
if consumer_key is None or consumer_secret is None or (
264+
not application_only_auth
265+
and (access_token_key is None or access_token_secret is None)):
266+
raise TwitterError({'message': "Missing oAuth Consumer Key or Access Token"})
265267

266-
raise TwitterError({'message': "Twitter requires oAuth Access Token for all API access"})
267-
268-
self.SetCredentials(consumer_key, consumer_secret, access_token_key, access_token_secret)
268+
self.SetCredentials(consumer_key, consumer_secret, access_token_key, access_token_secret,
269+
application_only_auth)
269270

270271
if debugHTTP:
271272
import logging
@@ -279,11 +280,33 @@ def __init__(self,
279280
requests_log.setLevel(logging.DEBUG)
280281
requests_log.propagate = True
281282

283+
def GetAppOnlyAuthToken(self, consumer_key, consumer_secret):
284+
"""
285+
Generate a Bearer Token from consumer_key and consumer_secret
286+
"""
287+
from urllib import quote_plus
288+
import base64
289+
290+
key = quote_plus(consumer_key)
291+
secret = quote_plus(consumer_secret)
292+
bearer_token = base64.b64encode('{}:{}'.format(key, secret) )
293+
294+
post_headers = {
295+
'Authorization': 'Basic '+bearer_token,
296+
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
297+
}
298+
res = requests.post(url='https://api.twitter.com/oauth2/token',
299+
data={'grant_type':'client_credentials'},
300+
headers=post_headers)
301+
bearer_creds = res.json()
302+
return bearer_creds
303+
282304
def SetCredentials(self,
283305
consumer_key,
284306
consumer_secret,
285307
access_token_key=None,
286-
access_token_secret=None):
308+
access_token_secret=None,
309+
application_only_auth=False):
287310
"""Set the consumer_key and consumer_secret for this instance
288311
289312
Args:
@@ -297,17 +320,23 @@ def SetCredentials(self,
297320
access_token_secret:
298321
The oAuth access token's secret, also retrieved
299322
from the get_access_token.py run.
323+
application_only_auth:
324+
Whether to generate a bearer token and use Application-Only Auth
300325
"""
301326
self._consumer_key = consumer_key
302327
self._consumer_secret = consumer_secret
303328
self._access_token_key = access_token_key
304329
self._access_token_secret = access_token_secret
305-
auth_list = [consumer_key, consumer_secret,
306-
access_token_key, access_token_secret]
307330

308-
if all(auth_list):
309-
self.__auth = OAuth1(consumer_key, consumer_secret,
310-
access_token_key, access_token_secret)
331+
if application_only_auth:
332+
self._bearer_token = self.GetAppOnlyAuthToken(consumer_key, consumer_secret)
333+
self.__auth = OAuth2(token=self._bearer_token)
334+
else:
335+
auth_list = [consumer_key, consumer_secret,
336+
access_token_key, access_token_secret]
337+
if all(auth_list):
338+
self.__auth = OAuth1(consumer_key, consumer_secret,
339+
access_token_key, access_token_secret)
311340

312341
self._config = None
313342

@@ -350,6 +379,7 @@ def ClearCredentials(self):
350379
self._consumer_secret = None
351380
self._access_token_key = None
352381
self._access_token_secret = None
382+
self._bearer_token = None
353383
self.__auth = None # for request upgrade
354384

355385
def GetSearch(self,

0 commit comments

Comments
 (0)