from urllib.parse import quote
except ImportError:
from urllib2 import quote
+ try:
+ import HTMLParser
+ except ImportError:
+ import html.parser as HTMLParser
+
import webbrowser
-from .api import Twitter, TwitterError
+from .api2 import TwitterAPI, TwitterError, search
from .oauth import OAuth, write_token_file, read_token_file
from .oauth_dance import oauth_dance
from . import ansi
screen_name = options['extra_args'][0]
if not options['extra_args'][1:]:
- lists = twitter.get("lists", screen_name=screen_name)['lists']
- lists = twitter.lists.list(screen_name=screen_name)
++ lists = twitter.get("lists/list", screen_name=screen_name)
if not lists:
printNicely("This user has no lists.")
for list in lists:
class FriendsAction(StatusAction):
def getStatuses(self, twitter, options):
- return reversed(twitter.statuses.home_timeline(count=options["length"]))
+ return reversed(twitter.get("statuses/home_timeline",
+ count=options["length"]))
- class PublicAction(StatusAction):
- def getStatuses(self, twitter, options):
- return reversed(twitter.get("statuses/public_timeline",
- count=options["length"]))
-
class RepliesAction(StatusAction):
def getStatuses(self, twitter, options):
- return reversed(twitter.statuses.mentions_timeline(count=options["length"]))
+ return reversed(twitter.get("statuses/mentions_timeline",
+ count=options["length"]))
class FollowAction(AdminAction):
def getUser(self, twitter, user):
"the Command-Line Tool", CONSUMER_KEY, CONSUMER_SECRET,
options['oauth_filename'])
+ global ansiFormatter
+ ansiFormatter = ansi.AnsiCmd(options["force-ansi"])
+
oauth_token, oauth_token_secret = read_token_file(oauth_filename)
- twitter = Twitter(
+ twitter = TwitterAPI(
+ api_version='1.1',
auth=OAuth(
oauth_token, oauth_token_secret, CONSUMER_KEY, CONSUMER_SECRET),
- secure=options['secure'],
- api_version='1.1',
- domain='api.twitter.com')
+ secure=options['secure'])
try:
Action()(twitter, options)
"""
An OAuth authenticator.
"""
- def __init__(self, token, token_secret, consumer_key, consumer_secret):
- """
- Create the authenticator. If you are in the initial stages of
- the OAuth dance and don't yet have a token or token_secret,
- pass empty strings for these params.
- """
- self.token = token
- self.token_secret = token_secret
- self.consumer_key = consumer_key
- self.consumer_secret = consumer_secret
-
- def encode_params(self, base_url, method, params):
- params = params.copy()
-
- if self.token:
- params['oauth_token'] = self.token
-
- params['oauth_consumer_key'] = self.consumer_key
- params['oauth_signature_method'] = 'HMAC-SHA1'
- params['oauth_version'] = '1.0'
- params['oauth_timestamp'] = str(int(time()))
- params['oauth_nonce'] = str(getrandbits(64))
-
- enc_params = urlencode_noplus(sorted(params.items()))
-
- key = self.consumer_secret + "&" + urllib_parse.quote(self.token_secret, safe='~')
-
- message = '&'.join(
- urllib_parse.quote(i, safe='~') for i in [method.upper(), base_url, enc_params])
-
- signature = (base64.b64encode(hmac.new(
- key.encode('ascii'), message.encode('ascii'), hashlib.sha1)
- .digest()))
- return enc_params + "&" + "oauth_signature=" + urllib_parse.quote(signature, safe='~')
-
- def generate_headers(self):
- return {}
-
-# apparently contrary to the HTTP RFCs, spaces in arguments must be encoded as
-# %20 rather than '+' when constructing an OAuth signature (and therefore
-# also in the request itself.)
-# So here is a specialized version which does exactly that.
-def urlencode_noplus(query):
- if not PY3:
- new_query = []
- for k,v in query:
- if type(k) is unicode: k = k.encode('utf-8')
- if type(v) is unicode: v = v.encode('utf-8')
- new_query.append((k, v))
- query = new_query
- return urlencode(query).replace("+", "%20")
-
- return urlencode(query, safe='~').replace("+", "%20")
+ return OAuth1(unicode(consumer_key), unicode(consumer_secret),
+ unicode(token), unicode(token_secret),
+ signature_type="query")
-
--- /dev/null
-from twitter.auth import Auth
+ """
+ Visit the Twitter developer page and create a new application:
+
+ https://dev.twitter.com/apps/new
+
+ This will get you a CONSUMER_KEY and CONSUMER_SECRET.
+
+ Twitter only supports the application-only flow of OAuth2 for certain
+ API endpoints. This OAuth2 authenticator only supports the application-only
+ flow right now. If twitter supports OAuth2 for other endpoints, this
+ authenticator may be modified as needed.
+
+ Finally, you can use the OAuth2 authenticator to connect to Twitter. In
+ code it all goes like this::
+
+ twitter = Twitter(auth=OAuth2(bearer_token=BEARER_TOKEN))
+
+ # Now work with Twitter
+ twitter.search.tweets(q='keyword')
+
+ """
+
+ from __future__ import print_function
+
+ try:
+ from urllib.parse import quote, urlencode
+ except ImportError:
+ from urllib import quote, urlencode
+
+ from base64 import b64encode
-class OAuth2(Auth):
+
+
++class OAuth2(object):
+ """
+ An OAuth2 application-only authenticator.
+ """
+ def __init__(self, consumer_key=None, consumer_secret=None,
+ bearer_token=None):
+ """
+ Create an authenticator. You can supply consumer_key and
+ consumer_secret if you are requesting a bearer_token. Otherwise
+ you must supply the bearer_token.
+ """
+ self.bearer_token = None
+ self.consumer_key = None
+ self.consumer_secret = None
+
+ if bearer_token:
+ self.bearer_token = bearer_token
+ elif consumer_key and consumer_secret:
+ self.consumer_key = consumer_key
+ self.consumer_secret = consumer_secret
+ else:
+ raise MissingCredentialsError(
+ 'You must supply either a bearer token, or both a '
+ 'consumer_key and a consumer_secret.')
+
+ def encode_params(self, base_url, method, params):
+
+ return urlencode(params)
+
+ def generate_headers(self):
+ if self.bearer_token:
+ headers = {
+ b'Authorization': 'Bearer {0}'.format(
+ self.bearer_token).encode('utf8')
+ }
+
+ elif self.consumer_key and self.consumer_secret:
+
+ headers = {
+ b'Content-Type': (b'application/x-www-form-urlencoded;'
+ b'charset=UTF-8'),
+ b'Authorization': 'Basic {0}'.format(
+ b64encode('{0}:{1}'.format(
+ quote(self.consumer_key),
+ quote(self.consumer_secret)).encode('utf8')
+ ).decode('utf8')
+ ).encode('utf8')
+ }
+
+ else:
+ raise MissingCredentialsError(
+ 'You must supply either a bearer token, or both a '
+ 'consumer_key and a consumer_secret.')
+
+ return headers
+
+
+ class MissingCredentialsError(Exception):
+ pass