From 9ca737b986dd8056ce1c159b9eadafc9597e4c19 Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Mon, 23 Nov 2009 22:03:21 -0500 Subject: [PATCH] Twython 0.9 - enough has changed with the Twitter API as of late that this merits a new release. 0.8 was beginning to show age as the API moved forward, and is now deprecated as a result - 0.9 is the way to go (or trunk, if you're adventurous. ;D) --- README.markdown | 8 +- build/lib/twython.py | 1764 ++++++++++++++++++---- dist/twython-0.9.macosx-10.5-i386.tar.gz | Bin 0 -> 58118 bytes dist/twython-0.9.tar.gz | Bin 0 -> 16158 bytes dist/twython-0.9.win32.exe | Bin 0 -> 90830 bytes setup.py | 16 +- twython.egg-info/PKG-INFO | 27 +- twython.egg-info/SOURCES.txt | 1 - twython.py | 2 +- twython3k.py | 2 +- 10 files changed, 1478 insertions(+), 342 deletions(-) create mode 100644 dist/twython-0.9.macosx-10.5-i386.tar.gz create mode 100644 dist/twython-0.9.tar.gz create mode 100644 dist/twython-0.9.win32.exe diff --git a/README.markdown b/README.markdown index 336b5d1..8501a38 100644 --- a/README.markdown +++ b/README.markdown @@ -8,9 +8,9 @@ This is my first library I've ever written in Python, so there could be some stu make a seasoned Python vet scratch his head, or possibly call me insane. It's open source, though, and I'm open to anything that'll improve the library as a whole. -OAuth support is in the works, but every other part of the Twitter API should be covered. Twython -handles both Basic (HTTP) Authentication and OAuth. Older versions of Twython need Basic Auth specified - -to override this, specify 'authtype="Basic"' in your twython.setup() call. +OAuth and Streaming API support is in the works, but every other part of the Twitter API should be covered. Twython +handles both Basic (HTTP) Authentication and OAuth (Older versions (pre 0.9) of Twython need Basic Auth specified - +to override this, specify 'authtype="Basic"' in your twython.setup() call). Twython has Docstrings if you want function-by-function plays; otherwise, check the Twython Wiki or Twitter's API Wiki (Twython calls mirror most of the methods listed there). @@ -27,7 +27,7 @@ Example Use ----------------------------------------------------------------------------------------------------- > import twython > -> twitter = twython.setup(authtype="Basic", username="example", password="example") +> twitter = twython.setup(username="example", password="example") > twitter.updateStatus("See how easy this was?") diff --git a/build/lib/twython.py b/build/lib/twython.py index 456b6c8..ffe31e5 100644 --- a/build/lib/twython.py +++ b/build/lib/twython.py @@ -1,8 +1,6 @@ #!/usr/bin/python """ - NOTE: Tango is being renamed to Twython; all basic strings have been changed below, but there's still work ongoing in this department. - Twython is an up-to-date library for Python that wraps the Twitter API. Other Python Twitter libraries seem to have fallen a bit behind, and Twitter's API has evolved a bit. Here's hoping this helps. @@ -18,7 +16,7 @@ from urlparse import urlparse from urllib2 import HTTPError __author__ = "Ryan McGrath " -__version__ = "0.6" +__version__ = "0.9" """Twython - Easy Twitter utilities in Python""" @@ -27,15 +25,13 @@ try: except ImportError: try: import json as simplejson - except: - raise Exception("Twython requires the simplejson library (or Python 2.6) to work. http://www.undefined.org/python/") + except ImportError: + try: + from django.utils import simplejson + except: + raise Exception("Twython requires the simplejson library (or Python 2.6) to work. http://www.undefined.org/python/") -try: - import oauth -except ImportError: - pass - -class TangoError(Exception): +class TwythonError(Exception): def __init__(self, msg, error_code=None): self.msg = msg if error_code == 400: @@ -43,114 +39,185 @@ class TangoError(Exception): def __str__(self): return repr(self.msg) -class APILimit(TangoError): +class APILimit(TwythonError): + def __init__(self, msg): + self.msg = msg + def __str__(self): + return repr(self.msg) + +class AuthError(TwythonError): def __init__(self, msg): self.msg = msg def __str__(self): return repr(self.msg) class setup: - def __init__(self, authtype = "OAuth", username = None, password = None, consumer_secret = None, consumer_key = None, headers = None): - self.authtype = authtype + def __init__(self, username = None, password = None, headers = None, version = 1): + """setup(authtype = "OAuth", username = None, password = None, consumer_secret = None, consumer_key = None, headers = None) + + Instantiates an instance of Twython. Takes optional parameters for authentication and such (see below). + + Parameters: + username - Your Twitter username, if you want Basic (HTTP) Authentication. + password - Password for your twitter account, if you want Basic (HTTP) Authentication. + headers - User agent header. + version (number) - Twitter supports a "versioned" API as of Oct. 16th, 2009 - this defaults to 1, but can be overridden on a class and function-based basis. + + ** Note: versioning is not currently used by search.twitter functions; when Twitter moves their junk, it'll be supported. + """ self.authenticated = False self.username = username - self.password = password - # OAuth specific variables below - self.request_token_url = 'https://twitter.com/oauth/request_token' - self.access_token_url = 'https://twitter.com/oauth/access_token' - self.authorization_url = 'http://twitter.com/oauth/authorize' - self.signin_url = 'http://twitter.com/oauth/authenticate' - self.consumer_key = consumer_key - self.consumer_secret = consumer_secret - self.request_token = None - self.access_token = None + self.apiVersion = version # Check and set up authentication - if self.username is not None and self.password is not None: - if self.authtype == "Basic": - # Basic authentication ritual - self.auth_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() - self.auth_manager.add_password(None, "http://twitter.com", self.username, self.password) - self.handler = urllib2.HTTPBasicAuthHandler(self.auth_manager) - self.opener = urllib2.build_opener(self.handler) - if headers is not None: - self.opener.addheaders = [('User-agent', headers)] - try: - simplejson.load(self.opener.open("http://twitter.com/account/verify_credentials.json")) - self.authenticated = True - except HTTPError, e: - raise TangoError("Authentication failed with your provided credentials. Try again? (%s failure)" % `e.code`, e.code) - else: - self.signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1() - # Awesome OAuth authentication ritual - if consumer_secret is not None and consumer_key is not None: - #req = oauth.OAuthRequest.from_consumer_and_token - #req.sign_request(self.signature_method, self.consumer_key, self.token) - #self.opener = urllib2.build_opener() - pass - else: - raise TwythonError("Woah there, buddy. We've defaulted to OAuth authentication, but you didn't provide API keys. Try again.") - - def getRequestToken(self): - response = self.oauth_request(self.request_token_url) - token = self.parseOAuthResponse(response) - self.request_token = oauth.OAuthConsumer(token['oauth_token'],token['oauth_token_secret']) - return self.request_token - - def parseOAuthResponse(self, response_string): - # Partial credit goes to Harper Reed for this gem. - lol = {} - for param in response_string.split("&"): - pair = param.split("=") - if(len(pair) != 2): - break - lol[pair[0]] = pair[1] - return lol + if self.username is not None and password is not None: + # Assume Basic authentication ritual + self.auth_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() + self.auth_manager.add_password(None, "http://api.twitter.com", self.username, password) + self.handler = urllib2.HTTPBasicAuthHandler(self.auth_manager) + self.opener = urllib2.build_opener(self.handler) + if headers is not None: + self.opener.addheaders = [('User-agent', headers)] + try: + simplejson.load(self.opener.open("http://api.twitter.com/%d/account/verify_credentials.json" % self.apiVersion)) + self.authenticated = True + except HTTPError, e: + raise AuthError("Authentication failed with your provided credentials. Try again? (%s failure)" % `e.code`) + else: + pass # URL Shortening function huzzah def shortenURL(self, url_to_shorten, shortener = "http://is.gd/api.php", query = "longurl"): + """shortenURL(url_to_shorten, shortener = "http://is.gd/api.php", query = "longurl") + + Shortens url specified by url_to_shorten. + + Parameters: + url_to_shorten - URL to shorten. + shortener - In case you want to use url shorterning service other that is.gd. + """ try: - return urllib2.urlopen(shortener + "?" + urllib.urlencode({query: url_to_shorten})).read() + return urllib2.urlopen(shortener + "?" + urllib.urlencode({query: self.unicode2utf8(url_to_shorten)})).read() except HTTPError, e: - raise TangoError("shortenURL() failed with a %s error code." % `e.code`) - + raise TwythonError("shortenURL() failed with a %s error code." % `e.code`) + def constructApiURL(self, base_url, params): return base_url + "?" + "&".join(["%s=%s" %(key, value) for (key, value) in params.iteritems()]) - - def getRateLimitStatus(self, rate_for = "requestingIP"): + + def getRateLimitStatus(self, rate_for = "requestingIP", version = None): + """getRateLimitStatus() + + Returns the remaining number of API requests available to the requesting user before the + API limit is reached for the current hour. Calls to rate_limit_status do not count against + the rate limit. If authentication credentials are provided, the rate limit status for the + authenticating user is returned. Otherwise, the rate limit status for the requesting + IP address is returned. + + Params: + rate_for - Defaults to "requestingIP", but can be changed to check on whatever account is currently authenticated. (Pass a blank string or something) + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion try: if rate_for == "requestingIP": - return simplejson.load(urllib2.urlopen("http://twitter.com/account/rate_limit_status.json")) + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/account/rate_limit_status.json" % version)) else: if self.authenticated is True: - return simplejson.load(self.opener.open("http://twitter.com/account/rate_limit_status.json")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/account/rate_limit_status.json" % version)) else: - raise TangoError("You need to be authenticated to check a rate limit status on an account.") + raise TwythonError("You need to be authenticated to check a rate limit status on an account.") except HTTPError, e: - raise TangoError("It seems that there's something wrong. Twitter gave you a %s error code; are you doing something you shouldn't be?" % `e.code`, e.code) - - def getPublicTimeline(self): + raise TwythonError("It seems that there's something wrong. Twitter gave you a %s error code; are you doing something you shouldn't be?" % `e.code`, e.code) + + def getPublicTimeline(self, version = None): + """getPublicTimeline() + + Returns the 20 most recent statuses from non-protected users who have set a custom user icon. + The public timeline is cached for 60 seconds, so requesting it more often than that is a waste of resources. + + Params: + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion try: - return simplejson.load(urllib2.urlopen("http://twitter.com/statuses/public_timeline.json")) + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/statuses/public_timeline.json" % version)) except HTTPError, e: - raise TangoError("getPublicTimeline() failed with a %s error code." % `e.code`) - - def getFriendsTimeline(self, **kwargs): + raise TwythonError("getPublicTimeline() failed with a %s error code." % `e.code`) + + def getHomeTimeline(self, version = None, **kwargs): + """getHomeTimeline(**kwargs) + + Returns the 20 most recent statuses, including retweets, posted by the authenticating user + and that user's friends. This is the equivalent of /timeline/home on the Web. + + Usage note: This home_timeline is identical to statuses/friends_timeline, except it also + contains retweets, which statuses/friends_timeline does not (for backwards compatibility + reasons). In a future version of the API, statuses/friends_timeline will go away and + be replaced by home_timeline. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - friendsTimelineURL = self.constructApiURL("http://twitter.com/statuses/friends_timeline.json", kwargs) + homeTimelineURL = self.constructApiURL("http://api.twitter.com/%d/statuses/home_timeline.json" % version, kwargs) + return simplejson.load(self.opener.open(homeTimelineURL)) + except HTTPError, e: + raise TwythonError("getHomeTimeline() failed with a %s error code. (This is an upcoming feature in the Twitter API, and may not be implemented yet)" % `e.code`) + else: + raise AuthError("getHomeTimeline() requires you to be authenticated.") + + def getFriendsTimeline(self, version = None, **kwargs): + """getFriendsTimeline(**kwargs) + + Returns the 20 most recent statuses posted by the authenticating user, as well as that users friends. + This is the equivalent of /timeline/home on the Web. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + friendsTimelineURL = self.constructApiURL("http://api.twitter.com/%d/statuses/friends_timeline.json" % version, kwargs) return simplejson.load(self.opener.open(friendsTimelineURL)) except HTTPError, e: - raise TangoError("getFriendsTimeline() failed with a %s error code." % `e.code`) + raise TwythonError("getFriendsTimeline() failed with a %s error code." % `e.code`) else: - raise TangoError("getFriendsTimeline() requires you to be authenticated.") - - def getUserTimeline(self, id = None, **kwargs): + raise AuthError("getFriendsTimeline() requires you to be authenticated.") + + def getUserTimeline(self, id = None, version = None, **kwargs): + """getUserTimeline(id = None, **kwargs) + + Returns the 20 most recent statuses posted from the authenticating user. It's also + possible to request another user's timeline via the id parameter. This is the + equivalent of the Web / page for your own user, or the profile page for a third party. + + Parameters: + id - Optional. Specifies the ID or screen name of the user for whom to return the user_timeline. + user_id - Optional. Specfies the ID of the user for whom to return the user_timeline. Helpful for disambiguating. + screen_name - Optional. Specfies the screen name of the user for whom to return the user_timeline. (Helpful for disambiguating when a valid screen name is also a user ID) + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if id is not None and kwargs.has_key("user_id") is False and kwargs.has_key("screen_name") is False: - userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline/" + id + ".json", kwargs) + userTimelineURL = self.constructApiURL("http://api.twitter.com/%d/statuses/user_timeline/%s.json" % (version, `id`), kwargs) elif id is None and kwargs.has_key("user_id") is False and kwargs.has_key("screen_name") is False and self.authenticated is True: - userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline/" + self.username + ".json", kwargs) + userTimelineURL = self.constructApiURL("http://api.twitter.com/%d/statuses/user_timeline/%s.json" % (version, self.username), kwargs) else: - userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline.json", kwargs) + userTimelineURL = self.constructApiURL("http://api.twitter.com/%d/statuses/user_timeline.json" % version, kwargs) try: # We do our custom opener if we're authenticated, as it helps avoid cases where it's a protected user if self.authenticated is True: @@ -158,177 +225,682 @@ class setup: else: return simplejson.load(urllib2.urlopen(userTimelineURL)) except HTTPError, e: - raise TangoError("Failed with a %s error code. Does this user hide/protect their updates? If so, you'll need to authenticate and be their friend to get their timeline." + raise TwythonError("Failed with a %s error code. Does this user hide/protect their updates? If so, you'll need to authenticate and be their friend to get their timeline." % `e.code`, e.code) - - def getUserMentions(self, **kwargs): + + def getUserMentions(self, version = None, **kwargs): + """getUserMentions(**kwargs) + + Returns the 20 most recent mentions (status containing @username) for the authenticating user. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - mentionsFeedURL = self.constructApiURL("http://twitter.com/statuses/mentions.json", kwargs) + mentionsFeedURL = self.constructApiURL("http://api.twitter.com/%d/statuses/mentions.json" % version, kwargs) return simplejson.load(self.opener.open(mentionsFeedURL)) except HTTPError, e: - raise TangoError("getUserMentions() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("getUserMentions() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("getUserMentions() requires you to be authenticated.") + raise AuthError("getUserMentions() requires you to be authenticated.") - def showStatus(self, id): + def reportSpam(self, id = None, user_id = None, screen_name = None, version = None): + """reportSpam(self, id), user_id, screen_name): + + Report a user account to Twitter as a spam account. *One* of the following parameters is required, and + this requires that you be authenticated with a user account. + + Parameters: + id - Optional. The ID or screen_name of the user you want to report as a spammer. + user_id - Optional. The ID of the user you want to report as a spammer. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Optional. The ID or screen_name of the user you want to report as a spammer. Helpful for disambiguating when a valid screen name is also a user ID. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + # This entire block of code is stupid, but I'm far too tired to think through it at the moment. Refactor it if you care. + if id is not None or user_id is not None or screen_name is not None: + try: + apiExtension = "" + if id is not None: + apiExtension = "id=%s" % id + if user_id is not None: + apiExtension = "user_id=%s" % `user_id` + if screen_name is not None: + apiExtension = "screen_name=%s" % screen_name + return simplejson.load(self.opener.open("http://api.twitter.com/%d/report_spam.json" % version, apiExtension)) + except HTTPError, e: + raise TwythonError("reportSpam() failed with a %s error code." % `e.code`, e.code) + else: + raise TwythonError("reportSpam requires you to specify an id, user_id, or screen_name. Try again!") + else: + raise AuthError("reportSpam() requires you to be authenticated.") + + def reTweet(self, id, version = None): + """reTweet(id) + + Retweets a tweet. Requires the id parameter of the tweet you are retweeting. + + Parameters: + id - Required. The numerical ID of the tweet you are retweeting. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/statuses/retweet/%s.json" % (version, `id`), "POST")) + except HTTPError, e: + raise TwythonError("reTweet() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("reTweet() requires you to be authenticated.") + + def getRetweets(self, id, count = None, version = None): + """ getRetweets(self, id, count): + + Returns up to 100 of the first retweets of a given tweet. + + Parameters: + id - Required. The numerical ID of the tweet you want the retweets of. + count - Optional. Specifies the number of retweets to retrieve. May not be greater than 100. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + apiURL = "http://api.twitter.com/%d/statuses/retweets/%s.json" % (version, `id`) + if count is not None: + apiURL += "?count=%s" % `count` + try: + return simplejson.load(self.opener.open(apiURL)) + except HTTPError, e: + raise TwythonError("getRetweets failed with a %s eroror code." % `e.code`, e.code) + else: + raise AuthError("getRetweets() requires you to be authenticated.") + + def retweetedOfMe(self, version = None, **kwargs): + """retweetedOfMe(**kwargs) + + Returns the 20 most recent tweets of the authenticated user that have been retweeted by others. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + retweetURL = self.constructApiURL("http://api.twitter.com/%d/statuses/retweets_of_me.json" % version, kwargs) + return simplejson.load(self.opener.open(retweetURL)) + except HTTPError, e: + raise TwythonError("retweetedOfMe() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("retweetedOfMe() requires you to be authenticated.") + + def retweetedByMe(self, version = None, **kwargs): + """retweetedByMe(**kwargs) + + Returns the 20 most recent retweets posted by the authenticating user. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + retweetURL = self.constructApiURL("http://api.twitter.com/%d/statuses/retweeted_by_me.json" % version, kwargs) + return simplejson.load(self.opener.open(retweetURL)) + except HTTPError, e: + raise TwythonError("retweetedByMe() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("retweetedByMe() requires you to be authenticated.") + + def retweetedToMe(self, version = None, **kwargs): + """retweetedToMe(**kwargs) + + Returns the 20 most recent retweets posted by the authenticating user's friends. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + retweetURL = self.constructApiURL("http://api.twitter.com/%d/statuses/retweeted_to_me.json" % version, kwargs) + return simplejson.load(self.opener.open(retweetURL)) + except HTTPError, e: + raise TwythonError("retweetedToMe() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("retweetedToMe() requires you to be authenticated.") + + def searchUsers(self, q, per_page = 20, page = 1, version = None): + """ searchUsers(q, per_page = None, page = None): + + Query Twitter to find a set of users who match the criteria we have. (Note: This, oddly, requires authentication - go figure) + + Parameters: + q (string) - Required. The query you wanna search against; self explanatory. ;) + per_page (number) - Optional, defaults to 20. Specify the number of users Twitter should return per page (no more than 20, just fyi) + page (number) - Optional, defaults to 1. The page of users you want to pull down. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/users/search.json?q=%s&per_page=%d&page=%d" % (version, q, per_page, page))) + except HTTPError, e: + raise TwythonError("searchUsers() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("searchUsers(), oddly, requires you to be authenticated.") + + def showUser(self, id = None, user_id = None, screen_name = None, version = None): + """showUser(id = None, user_id = None, screen_name = None) + + Returns extended information of a given user. The author's most recent status will be returned inline. + + Parameters: + ** Note: One of the following must always be specified. + id - The ID or screen name of a user. + user_id - Specfies the ID of the user to return. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Specfies the screen name of the user to return. Helpful for disambiguating when a valid screen name is also a user ID. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + + Usage Notes: + Requests for protected users without credentials from + 1) the user requested or + 2) a user that is following the protected user will omit the nested status element. + + ...will result in only publicly available data being returned. + """ + version = version or self.apiVersion + apiURL = "" + if id is not None: + apiURL = "http://api.twitter.com/%d/users/show/%s.json" % (version, id) + if user_id is not None: + apiURL = "http://api.twitter.com/%d/users/show.json?user_id=%s" % (version, `user_id`) + if screen_name is not None: + apiURL = "http://api.twitter.com/%d/users/show.json?screen_name=%s" % (version, screen_name) + if apiURL != "": + try: + if self.authenticated is True: + return simplejson.load(self.opener.open(apiURL)) + else: + return simplejson.load(urllib2.urlopen(apiURL)) + except HTTPError, e: + raise TwythonError("showUser() failed with a %s error code." % `e.code`, e.code) + + def getFriendsStatus(self, id = None, user_id = None, screen_name = None, page = None, cursor="-1", version = None): + """getFriendsStatus(id = None, user_id = None, screen_name = None, page = None, cursor="-1") + + Returns a user's friends, each with current status inline. They are ordered by the order in which they were added as friends, 100 at a time. + (Please note that the result set isn't guaranteed to be 100 every time, as suspended users will be filtered out.) Use the page option to access + older friends. With no user specified, the request defaults to the authenticated users friends. + + It's also possible to request another user's friends list via the id, screen_name or user_id parameter. + + Note: The previously documented page-based pagination mechanism is still in production, but please migrate to cursor-based pagination for increase reliability and performance. + + Parameters: + ** Note: One of the following is required. (id, user_id, or screen_name) + id - Optional. The ID or screen name of the user for whom to request a list of friends. + user_id - Optional. Specfies the ID of the user for whom to return the list of friends. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Optional. Specfies the screen name of the user for whom to return the list of friends. Helpful for disambiguating when a valid screen name is also a user ID. + page - (BEING DEPRECATED) Optional. Specifies the page of friends to receive. + cursor - Optional. Breaks the results into pages. A single page contains 100 users. This is recommended for users who are following many users. Provide a value of -1 to begin paging. Provide values as returned to in the response body's next_cursor and previous_cursor attributes to page back and forth in the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + apiURL = "" + if id is not None: + apiURL = "http://api.twitter.com/%d/statuses/friends/%s.json" % (version, id) + if user_id is not None: + apiURL = "http://api.twitter.com/%d/statuses/friends.json?user_id=%s" % (version, `user_id`) + if screen_name is not None: + apiURL = "http://api.twitter.com/%d/statuses/friends.json?screen_name=%s" % (version, screen_name) + try: + if page is not None: + return simplejson.load(self.opener.open(apiURL + "&page=%s" % `page`)) + else: + return simplejson.load(self.opener.open(apiURL + "&cursor=%s" % cursor)) + except HTTPError, e: + raise TwythonError("getFriendsStatus() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("getFriendsStatus() requires you to be authenticated.") + + def getFollowersStatus(self, id = None, user_id = None, screen_name = None, page = None, cursor = "-1", version = None): + """getFollowersStatus(id = None, user_id = None, screen_name = None, page = None, cursor = "-1") + + Returns the authenticating user's followers, each with current status inline. + They are ordered by the order in which they joined Twitter, 100 at a time. + (Note that the result set isn't guaranteed to be 100 every time, as suspended users will be filtered out.) + + Use the page option to access earlier followers. + + Note: The previously documented page-based pagination mechanism is still in production, but please migrate to cursor-based pagination for increase reliability and performance. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Optional. The ID or screen name of the user for whom to request a list of followers. + user_id - Optional. Specfies the ID of the user for whom to return the list of followers. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Optional. Specfies the screen name of the user for whom to return the list of followers. Helpful for disambiguating when a valid screen name is also a user ID. + page - (BEING DEPRECATED) Optional. Specifies the page to retrieve. + cursor - Optional. Breaks the results into pages. A single page contains 100 users. This is recommended for users who are following many users. Provide a value of -1 to begin paging. Provide values as returned to in the response body's next_cursor and previous_cursor attributes to page back and forth in the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + apiURL = "" + if id is not None: + apiURL = "http://api.twitter.com/%d/statuses/followers/%s.json" % (version, id) + if user_id is not None: + apiURL = "http://api.twitter.com/%d/statuses/followers.json?user_id=%s" % (version, `user_id`) + if screen_name is not None: + apiURL = "http://api.twitter.com/%d/statuses/followers.json?screen_name=%s" % (version, screen_name) + try: + if page is not None: + return simplejson.load(self.opener.open(apiURL + "&page=%s" % page)) + else: + return simplejson.load(self.opener.open(apiURL + "&cursor=%s" % cursor)) + except HTTPError, e: + raise TwythonError("getFollowersStatus() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("getFollowersStatus() requires you to be authenticated.") + + def showStatus(self, id, version = None): + """showStatus(id) + + Returns a single status, specified by the id parameter below. + The status's author will be returned inline. + + Parameters: + id - Required. The numerical ID of the status to retrieve. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion try: if self.authenticated is True: - return simplejson.load(self.opener.open("http://twitter.com/statuses/show/%s.json" % id)) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/statuses/show/%s.json" % (version, id))) else: - return simplejson.load(urllib2.urlopen("http://twitter.com/statuses/show/%s.json" % id)) + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/statuses/show/%s.json" % (version, id))) except HTTPError, e: - raise TangoError("Failed with a %s error code. Does this user hide/protect their updates? You'll need to authenticate and be friends to get their timeline." + raise TwythonError("Failed with a %s error code. Does this user hide/protect their updates? You'll need to authenticate and be friends to get their timeline." % `e.code`, e.code) - - def updateStatus(self, status, in_reply_to_status_id = None): + + def updateStatus(self, status, in_reply_to_status_id = None, latitude = None, longitude = None, version = None): + """updateStatus(status, in_reply_to_status_id = None) + + Updates the authenticating user's status. Requires the status parameter specified below. + A status update with text identical to the authenticating users current status will be ignored to prevent duplicates. + + Parameters: + status - Required. The text of your status update. URL encode as necessary. Statuses over 140 characters will be forceably truncated. + in_reply_to_status_id - Optional. The ID of an existing status that the update is in reply to. + latitude (string) - Optional. The location's latitude that this tweet refers to. + longitude (string) - Optional. The location's longitude that this tweet refers to. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + + ** Note: in_reply_to_status_id will be ignored unless the author of the tweet this parameter references + is mentioned within the status text. Therefore, you must include @username, where username is + the author of the referenced tweet, within the update. + + ** Note: valid ranges for latitude/longitude are, for example, -180.0 to +180.0 (East is positive) inclusive. + This parameter will be ignored if outside that range, not a number, if geo_enabled is disabled, or if there not a corresponding latitude parameter with this tweet. + """ + version = version or self.apiVersion + if len(list(status)) > 140: + raise TwythonError("This status message is over 140 characters. Trim it down!") + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/statuses/update.json?" % version, urllib.urlencode({ + "status": self.unicode2utf8(status), + "in_reply_to_status_id": in_reply_to_status_id, + "lat": latitude, + "long": longitude + }))) + except HTTPError, e: + raise TwythonError("updateStatus() failed with a %s error code." % `e.code`, e.code) + + def destroyStatus(self, id, version = None): + """destroyStatus(id) + + Destroys the status specified by the required ID parameter. + The authenticating user must be the author of the specified status. + + Parameters: + id - Required. The ID of the status to destroy. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: - if len(list(status)) > 140: - raise TangoError("This status message is over 140 characters. Trim it down!") try: - return simplejson.load(self.opener.open("http://twitter.com/statuses/update.json?", urllib.urlencode({"status": status, "in_reply_to_status_id": in_reply_to_status_id}))) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/status/destroy/%s.json" % (version, `id`), "DELETE")) except HTTPError, e: - raise TangoError("updateStatus() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("destroyStatus() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("updateStatus() requires you to be authenticated.") - - def destroyStatus(self, id): + raise AuthError("destroyStatus() requires you to be authenticated.") + + def endSession(self, version = None): + """endSession() + + Ends the session of the authenticating user, returning a null cookie. + Use this method to sign users out of client-facing applications (widgets, etc). + + Parameters: + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/status/destroy/%s.json", "POST" % id)) - except HTTPError, e: - raise TangoError("destroyStatus() failed with a %s error code." % `e.code`, e.code) - else: - raise TangoError("destroyStatus() requires you to be authenticated.") - - def endSession(self): - if self.authenticated is True: - try: - self.opener.open("http://twitter.com/account/end_session.json", "") + self.opener.open("http://api.twitter.com/%d/account/end_session.json" % version, "") self.authenticated = False except HTTPError, e: - raise TangoError("endSession failed with a %s error code." % `e.code`, e.code) + raise TwythonError("endSession failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("You can't end a session when you're not authenticated to begin with.") - - def getDirectMessages(self, since_id = None, max_id = None, count = None, page = "1"): + raise AuthError("You can't end a session when you're not authenticated to begin with.") + + def getDirectMessages(self, since_id = None, max_id = None, count = None, page = "1", version = None): + """getDirectMessages(since_id = None, max_id = None, count = None, page = "1") + + Returns a list of the 20 most recent direct messages sent to the authenticating user. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: - apiURL = "http://twitter.com/direct_messages.json?page=" + page + apiURL = "http://api.twitter.com/%d/direct_messages.json?page=%s" % (version, `page`) if since_id is not None: - apiURL += "&since_id=" + since_id + apiURL += "&since_id=%s" % `since_id` if max_id is not None: - apiURL += "&max_id=" + max_id + apiURL += "&max_id=%s" % `max_id` if count is not None: - apiURL += "&count=" + count - + apiURL += "&count=%s" % `count` + try: return simplejson.load(self.opener.open(apiURL)) except HTTPError, e: - raise TangoError("getDirectMessages() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("getDirectMessages() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("getDirectMessages() requires you to be authenticated.") - - def getSentMessages(self, since_id = None, max_id = None, count = None, page = "1"): + raise AuthError("getDirectMessages() requires you to be authenticated.") + + def getSentMessages(self, since_id = None, max_id = None, count = None, page = "1", version = None): + """getSentMessages(since_id = None, max_id = None, count = None, page = "1") + + Returns a list of the 20 most recent direct messages sent by the authenticating user. + + Parameters: + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + page - Optional. Specifies the page of results to retrieve. Note: there are pagination limits. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: - apiURL = "http://twitter.com/direct_messages/sent.json?page=" + page + apiURL = "http://api.twitter.com/%d/direct_messages/sent.json?page=%s" % (version, `page`) if since_id is not None: - apiURL += "&since_id=" + since_id + apiURL += "&since_id=%s" % `since_id` if max_id is not None: - apiURL += "&max_id=" + max_id + apiURL += "&max_id=%s" % `max_id` if count is not None: - apiURL += "&count=" + count - + apiURL += "&count=%s" % `count` + try: return simplejson.load(self.opener.open(apiURL)) except HTTPError, e: - raise TangoError("getSentMessages() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("getSentMessages() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("getSentMessages() requires you to be authenticated.") - - def sendDirectMessage(self, user, text): + raise AuthError("getSentMessages() requires you to be authenticated.") + + def sendDirectMessage(self, user, text, version = None): + """sendDirectMessage(user, text) + + Sends a new direct message to the specified user from the authenticating user. Requires both the user and text parameters. + Returns the sent message in the requested format when successful. + + Parameters: + user - Required. The ID or screen name of the recipient user. + text - Required. The text of your direct message. Be sure to keep it under 140 characters. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: if len(list(text)) < 140: try: - return self.opener.open("http://twitter.com/direct_messages/new.json", urllib.urlencode({"user": user, "text": text})) + return self.opener.open("http://api.twitter.com/%d/direct_messages/new.json" % version, urllib.urlencode({"user": user, "text": text})) except HTTPError, e: - raise TangoError("sendDirectMessage() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("sendDirectMessage() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("Your message must not be longer than 140 characters") + raise TwythonError("Your message must not be longer than 140 characters") else: - raise TangoError("You must be authenticated to send a new direct message.") - - def destroyDirectMessage(self, id): + raise AuthError("You must be authenticated to send a new direct message.") + + def destroyDirectMessage(self, id, version = None): + """destroyDirectMessage(id) + + Destroys the direct message specified in the required ID parameter. + The authenticating user must be the recipient of the specified direct message. + + Parameters: + id - Required. The ID of the direct message to destroy. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return self.opener.open("http://twitter.com/direct_messages/destroy/%s.json" % id, "") + return self.opener.open("http://api.twitter.com/%d/direct_messages/destroy/%s.json" % (version, id), "") except HTTPError, e: - raise TangoError("destroyDirectMessage() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("destroyDirectMessage() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("You must be authenticated to destroy a direct message.") - - def createFriendship(self, id = None, user_id = None, screen_name = None, follow = "false"): + raise AuthError("You must be authenticated to destroy a direct message.") + + def createFriendship(self, id = None, user_id = None, screen_name = None, follow = "false", version = None): + """createFriendship(id = None, user_id = None, screen_name = None, follow = "false") + + Allows the authenticating users to follow the user specified in the ID parameter. + Returns the befriended user in the requested format when successful. Returns a + string describing the failure condition when unsuccessful. If you are already + friends with the user an HTTP 403 will be returned. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Required. The ID or screen name of the user to befriend. + user_id - Required. Specfies the ID of the user to befriend. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Required. Specfies the screen name of the user to befriend. Helpful for disambiguating when a valid screen name is also a user ID. + follow - Optional. Enable notifications for the target user in addition to becoming friends. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: apiURL = "" - if id is not None: - apiURL = "http://twitter.com/friendships/create/" + id + ".json" + "?follow=" + follow if user_id is not None: - apiURL = "http://twitter.com/friendships/create.json?user_id=" + user_id + "&follow=" + follow + apiURL = "?user_id=%s&follow=%s" %(`user_id`, follow) if screen_name is not None: - apiURL = "http://twitter.com/friendships/create.json?screen_name=" + screen_name + "&follow=" + follow + apiURL = "?screen_name=%s&follow=%s" %(screen_name, follow) try: - return simplejson.load(self.opener.open(apiURL)) + if id is not None: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/friendships/create/%s.json" % (version, id), "?folow=%s" % follow)) + else: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/friendships/create.json" % version, apiURL)) except HTTPError, e: # Rate limiting is done differently here for API reasons... if e.code == 403: - raise TangoError("You've hit the update limit for this method. Try again in 24 hours.") - raise TangoError("createFriendship() failed with a %s error code." % `e.code`, e.code) + raise APILimit("You've hit the update limit for this method. Try again in 24 hours.") + raise TwythonError("createFriendship() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("createFriendship() requires you to be authenticated.") - - def destroyFriendship(self, id = None, user_id = None, screen_name = None): + raise AuthError("createFriendship() requires you to be authenticated.") + + def destroyFriendship(self, id = None, user_id = None, screen_name = None, version = None): + """destroyFriendship(id = None, user_id = None, screen_name = None) + + Allows the authenticating users to unfollow the user specified in the ID parameter. + Returns the unfollowed user in the requested format when successful. Returns a string describing the failure condition when unsuccessful. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Required. The ID or screen name of the user to unfollow. + user_id - Required. Specfies the ID of the user to unfollow. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Required. Specfies the screen name of the user to unfollow. Helpful for disambiguating when a valid screen name is also a user ID. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: apiURL = "" - if id is not None: - apiURL = "http://twitter.com/friendships/destroy/" + id + ".json" if user_id is not None: - apiURL = "http://twitter.com/friendships/destroy.json?user_id=" + user_id + apiURL = "?user_id=%s" % `user_id` if screen_name is not None: - apiURL = "http://twitter.com/friendships/destroy.json?screen_name=" + screen_name + apiURL = "?screen_name=%s" % screen_name try: + if id is not None: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/friendships/destroy/%s.json" % (version, `id`), "lol=1")) # Random string hack for POST reasons ;P + else: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/friendships/destroy.json" % version, apiURL)) + except HTTPError, e: + raise TwythonError("destroyFriendship() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("destroyFriendship() requires you to be authenticated.") + + def checkIfFriendshipExists(self, user_a, user_b, version = None): + """checkIfFriendshipExists(user_a, user_b) + + Tests for the existence of friendship between two users. + Will return true if user_a follows user_b; otherwise, it'll return false. + + Parameters: + user_a - Required. The ID or screen_name of the subject user. + user_b - Required. The ID or screen_name of the user to test for following. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + friendshipURL = "http://api.twitter.com/%d/friendships/exists.json?%s" % (version, urllib.urlencode({"user_a": user_a, "user_b": user_b})) + return simplejson.load(self.opener.open(friendshipURL)) + except HTTPError, e: + raise TwythonError("checkIfFriendshipExists() failed with a %s error code." % `e.code`, e.code) + else: + raise AuthError("checkIfFriendshipExists(), oddly, requires that you be authenticated.") + + def showFriendship(self, source_id = None, source_screen_name = None, target_id = None, target_screen_name = None, version = None): + """showFriendship(source_id, source_screen_name, target_id, target_screen_name) + + Returns detailed information about the relationship between two users. + + Parameters: + ** Note: One of the following is required if the request is unauthenticated + source_id - The user_id of the subject user. + source_screen_name - The screen_name of the subject user. + + ** Note: One of the following is required at all times + target_id - The user_id of the target user. + target_screen_name - The screen_name of the target user. + + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + apiURL = "http://api.twitter.com/%d/friendships/show.json?lol=1" % version # Another quick hack, look away if you want. :D + if source_id is not None: + apiURL += "&source_id=%s" % `source_id` + if source_screen_name is not None: + apiURL += "&source_screen_name=%s" % source_screen_name + if target_id is not None: + apiURL += "&target_id=%s" % `target_id` + if target_screen_name is not None: + apiURL += "&target_screen_name=%s" % target_screen_name + try: + if self.authenticated is True: return simplejson.load(self.opener.open(apiURL)) - except HTTPError, e: - raise TangoError("destroyFriendship() failed with a %s error code." % `e.code`, e.code) - else: - raise TangoError("destroyFriendship() requires you to be authenticated.") + else: + return simplejson.load(urllib2.urlopen(apiURL)) + except HTTPError, e: + # Catch this for now + if e.code == 403: + raise AuthError("You're unauthenticated, and forgot to pass a source for this method. Try again!") + raise TwythonError("showFriendship() failed with a %s error code." % `e.code`, e.code) - def checkIfFriendshipExists(self, user_a, user_b): + def updateDeliveryDevice(self, device_name = "none", version = None): + """updateDeliveryDevice(device_name = "none") + + Sets which device Twitter delivers updates to for the authenticating user. + Sending "none" as the device parameter will disable IM or SMS updates. (Simply calling .updateDeliveryService() also accomplishes this) + + Parameters: + device - Required. Must be one of: sms, im, none. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/friendships/exists.json", urllib.urlencode({"user_a": user_a, "user_b": user_b}))) + return self.opener.open("http://api.twitter.com/%d/account/update_delivery_device.json?" % version, urllib.urlencode({"device": self.unicode2utf8(device_name)})) except HTTPError, e: - raise TangoError("checkIfFriendshipExists() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("updateDeliveryDevice() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("checkIfFriendshipExists(), oddly, requires that you be authenticated.") - - def updateDeliveryDevice(self, device_name = "none"): + raise AuthError("updateDeliveryDevice() requires you to be authenticated.") + + def updateProfileColors(self, version = None, **kwargs): + """updateProfileColors(**kwargs) + + Sets one or more hex values that control the color scheme of the authenticating user's profile page on api.twitter.com. + + Parameters: + ** Note: One or more of the following parameters must be present. Each parameter's value must + be a valid hexidecimal value, and may be either three or six characters (ex: #fff or #ffffff). + + profile_background_color - Optional. + profile_text_color - Optional. + profile_link_color - Optional. + profile_sidebar_fill_color - Optional. + profile_sidebar_border_color - Optional. + + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return self.opener.open("http://twitter.com/account/update_delivery_device.json?", urllib.urlencode({"device": device_name})) + return self.opener.open(self.constructApiURL("http://api.twitter.com/%d/account/update_profile_colors.json?" % version, kwargs)) except HTTPError, e: - raise TangoError("updateDeliveryDevice() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("updateProfileColors() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("updateDeliveryDevice() requires you to be authenticated.") - - def updateProfileColors(self, **kwargs): - if self.authenticated is True: - try: - return self.opener.open(self.constructApiURL("http://twitter.com/account/update_profile_colors.json?", kwargs)) - except HTTPError, e: - raise TangoError("updateProfileColors() failed with a %s error code." % `e.code`, e.code) - else: - raise TangoError("updateProfileColors() requires you to be authenticated.") - - def updateProfile(self, name = None, email = None, url = None, location = None, description = None): + raise AuthError("updateProfileColors() requires you to be authenticated.") + + def updateProfile(self, name = None, email = None, url = None, location = None, description = None, version = None): + """updateProfile(name = None, email = None, url = None, location = None, description = None) + + Sets values that users are able to set under the "Account" tab of their settings page. + Only the parameters specified will be updated. + + Parameters: + One or more of the following parameters must be present. Each parameter's value + should be a string. See the individual parameter descriptions below for further constraints. + + name - Optional. Maximum of 20 characters. + email - Optional. Maximum of 40 characters. Must be a valid email address. + url - Optional. Maximum of 100 characters. Will be prepended with "http://" if not present. + location - Optional. Maximum of 30 characters. The contents are not normalized or geocoded in any way. + description - Optional. Maximum of 160 characters. + + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: useAmpersands = False updateProfileQueryString = "" @@ -337,7 +909,7 @@ class setup: updateProfileQueryString += "name=" + name useAmpersands = True else: - raise TangoError("Twitter has a character limit of 20 for all usernames. Try again.") + raise TwythonError("Twitter has a character limit of 20 for all usernames. Try again.") if email is not None and "@" in email: if len(list(email)) < 40: if useAmpersands is True: @@ -346,197 +918,376 @@ class setup: updateProfileQueryString += "email=" + email useAmpersands = True else: - raise TangoError("Twitter has a character limit of 40 for all email addresses, and the email address must be valid. Try again.") + raise TwythonError("Twitter has a character limit of 40 for all email addresses, and the email address must be valid. Try again.") if url is not None: if len(list(url)) < 100: if useAmpersands is True: - updateProfileQueryString += "&" + urllib.urlencode({"url": url}) + updateProfileQueryString += "&" + urllib.urlencode({"url": self.unicode2utf8(url)}) else: - updateProfileQueryString += urllib.urlencode({"url": url}) + updateProfileQueryString += urllib.urlencode({"url": self.unicode2utf8(url)}) useAmpersands = True else: - raise TangoError("Twitter has a character limit of 100 for all urls. Try again.") + raise TwythonError("Twitter has a character limit of 100 for all urls. Try again.") if location is not None: if len(list(location)) < 30: if useAmpersands is True: - updateProfileQueryString += "&" + urllib.urlencode({"location": location}) + updateProfileQueryString += "&" + urllib.urlencode({"location": self.unicode2utf8(location)}) else: - updateProfileQueryString += urllib.urlencode({"location": location}) + updateProfileQueryString += urllib.urlencode({"location": self.unicode2utf8(location)}) useAmpersands = True else: - raise TangoError("Twitter has a character limit of 30 for all locations. Try again.") + raise TwythonError("Twitter has a character limit of 30 for all locations. Try again.") if description is not None: if len(list(description)) < 160: if useAmpersands is True: - updateProfileQueryString += "&" + urllib.urlencode({"description": description}) + updateProfileQueryString += "&" + urllib.urlencode({"description": self.unicode2utf8(description)}) else: - updateProfileQueryString += urllib.urlencode({"description": description}) + updateProfileQueryString += urllib.urlencode({"description": self.unicode2utf8(description)}) else: - raise TangoError("Twitter has a character limit of 160 for all descriptions. Try again.") - + raise TwythonError("Twitter has a character limit of 160 for all descriptions. Try again.") + if updateProfileQueryString != "": try: - return self.opener.open("http://twitter.com/account/update_profile.json?", updateProfileQueryString) + return self.opener.open("http://api.twitter.com/%d/account/update_profile.json?" % version, updateProfileQueryString) except HTTPError, e: - raise TangoError("updateProfile() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("updateProfile() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("updateProfile() requires you to be authenticated.") - - def getFavorites(self, page = "1"): + raise AuthError("updateProfile() requires you to be authenticated.") + + def getFavorites(self, page = "1", version = None): + """getFavorites(page = "1") + + Returns the 20 most recent favorite statuses for the authenticating user or user specified by the ID parameter in the requested format. + + Parameters: + page - Optional. Specifies the page of favorites to retrieve. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/favorites.json?page=" + page)) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/favorites.json?page=%s" % (version, `page`))) except HTTPError, e: - raise TangoError("getFavorites() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("getFavorites() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("getFavorites() requires you to be authenticated.") - - def createFavorite(self, id): + raise AuthError("getFavorites() requires you to be authenticated.") + + def createFavorite(self, id, version = None): + """createFavorite(id) + + Favorites the status specified in the ID parameter as the authenticating user. Returns the favorite status when successful. + + Parameters: + id - Required. The ID of the status to favorite. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/favorites/create/" + id + ".json", "")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/favorites/create/%s.json" % (version, `id`), "")) except HTTPError, e: - raise TangoError("createFavorite() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("createFavorite() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("createFavorite() requires you to be authenticated.") - - def destroyFavorite(self, id): + raise AuthError("createFavorite() requires you to be authenticated.") + + def destroyFavorite(self, id, version = None): + """destroyFavorite(id) + + Un-favorites the status specified in the ID parameter as the authenticating user. Returns the un-favorited status in the requested format when successful. + + Parameters: + id - Required. The ID of the status to un-favorite. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/favorites/destroy/" + id + ".json", "")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/favorites/destroy/%s.json" % (version, `id`), "")) except HTTPError, e: - raise TangoError("destroyFavorite() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("destroyFavorite() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("destroyFavorite() requires you to be authenticated.") - - def notificationFollow(self, id = None, user_id = None, screen_name = None): + raise AuthError("destroyFavorite() requires you to be authenticated.") + + def notificationFollow(self, id = None, user_id = None, screen_name = None, version = None): + """notificationFollow(id = None, user_id = None, screen_name = None) + + Enables device notifications for updates from the specified user. Returns the specified user when successful. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Required. The ID or screen name of the user to follow with device updates. + user_id - Required. Specfies the ID of the user to follow with device updates. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Required. Specfies the screen name of the user to follow with device updates. Helpful for disambiguating when a valid screen name is also a user ID. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: apiURL = "" if id is not None: - apiURL = "http://twitter.com/notifications/follow/" + id + ".json" + apiURL = "http://api.twitter.com/%d/notifications/follow/%s.json" % (version, id) if user_id is not None: - apiURL = "http://twitter.com/notifications/follow/follow.json?user_id=" + user_id + apiURL = "http://api.twitter.com/%d/notifications/follow/follow.json?user_id=%s" % (version, `user_id`) if screen_name is not None: - apiURL = "http://twitter.com/notifications/follow/follow.json?screen_name=" + screen_name + apiURL = "http://api.twitter.com/%d/notifications/follow/follow.json?screen_name=%s" % (version, screen_name) try: return simplejson.load(self.opener.open(apiURL, "")) except HTTPError, e: - raise TangoError("notificationFollow() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("notificationFollow() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("notificationFollow() requires you to be authenticated.") - - def notificationLeave(self, id = None, user_id = None, screen_name = None): + raise AuthError("notificationFollow() requires you to be authenticated.") + + def notificationLeave(self, id = None, user_id = None, screen_name = None, version = None): + """notificationLeave(id = None, user_id = None, screen_name = None) + + Disables notifications for updates from the specified user to the authenticating user. Returns the specified user when successful. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Required. The ID or screen name of the user to follow with device updates. + user_id - Required. Specfies the ID of the user to follow with device updates. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Required. Specfies the screen name of the user to follow with device updates. Helpful for disambiguating when a valid screen name is also a user ID. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: apiURL = "" if id is not None: - apiURL = "http://twitter.com/notifications/leave/" + id + ".json" + apiURL = "http://api.twitter.com/%d/notifications/leave/%s.json" % (version, id) if user_id is not None: - apiURL = "http://twitter.com/notifications/leave/leave.json?user_id=" + user_id + apiURL = "http://api.twitter.com/%d/notifications/leave/leave.json?user_id=%s" % (version, `user_id`) if screen_name is not None: - apiURL = "http://twitter.com/notifications/leave/leave.json?screen_name=" + screen_name + apiURL = "http://api.twitter.com/%d/notifications/leave/leave.json?screen_name=%s" % (version, screen_name) try: return simplejson.load(self.opener.open(apiURL, "")) except HTTPError, e: - raise TangoError("notificationLeave() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("notificationLeave() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("notificationLeave() requires you to be authenticated.") - - def getFriendsIDs(self, id = None, user_id = None, screen_name = None, page = "1"): + raise AuthError("notificationLeave() requires you to be authenticated.") + + def getFriendsIDs(self, id = None, user_id = None, screen_name = None, page = None, cursor = "-1", version = None): + """getFriendsIDs(id = None, user_id = None, screen_name = None, page = None, cursor = "-1") + + Returns an array of numeric IDs for every user the specified user is following. + + Note: The previously documented page-based pagination mechanism is still in production, but please migrate to cursor-based pagination for increase reliability and performance. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Required. The ID or screen name of the user to follow with device updates. + user_id - Required. Specfies the ID of the user to follow with device updates. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Required. Specfies the screen name of the user to follow with device updates. Helpful for disambiguating when a valid screen name is also a user ID. + page - (BEING DEPRECATED) Optional. Specifies the page number of the results beginning at 1. A single page contains up to 5000 ids. This is recommended for users with large ID lists. If not provided all ids are returned. (Please note that the result set isn't guaranteed to be 5000 every time as suspended users will be filtered out.) + cursor - Optional. Breaks the results into pages. A single page contains 5000 ids. This is recommended for users with large ID lists. Provide a value of -1 to begin paging. Provide values as returned to in the response body's "next_cursor" and "previous_cursor" attributes to page back and forth in the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion apiURL = "" + breakResults = "cursor=%s" % cursor + if page is not None: + breakResults = "page=%s" % page if id is not None: - apiURL = "http://twitter.com/friends/ids/" + id + ".json" + "?page=" + page + apiURL = "http://api.twitter.com/%d/friends/ids/%s.json?%s" %(version, id, breakResults) if user_id is not None: - apiURL = "http://twitter.com/friends/ids.json?user_id=" + user_id + "&page=" + page + apiURL = "http://api.twitter.com/%d/friends/ids.json?user_id=%s&%s" %(version, `user_id`, breakResults) if screen_name is not None: - apiURL = "http://twitter.com/friends/ids.json?screen_name=" + screen_name + "&page=" + page + apiURL = "http://api.twitter.com/%d/friends/ids.json?screen_name=%s&%s" %(version, screen_name, breakResults) try: return simplejson.load(urllib2.urlopen(apiURL)) except HTTPError, e: - raise TangoError("getFriendsIDs() failed with a %s error code." % `e.code`, e.code) - - def getFollowersIDs(self, id = None, user_id = None, screen_name = None, page = "1"): + raise TwythonError("getFriendsIDs() failed with a %s error code." % `e.code`, e.code) + + def getFollowersIDs(self, id = None, user_id = None, screen_name = None, page = None, cursor = "-1", version = None): + """getFollowersIDs(id = None, user_id = None, screen_name = None, page = None, cursor = "-1") + + Returns an array of numeric IDs for every user following the specified user. + + Note: The previously documented page-based pagination mechanism is still in production, but please migrate to cursor-based pagination for increase reliability and performance. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Required. The ID or screen name of the user to follow with device updates. + user_id - Required. Specfies the ID of the user to follow with device updates. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Required. Specfies the screen name of the user to follow with device updates. Helpful for disambiguating when a valid screen name is also a user ID. + page - (BEING DEPRECATED) Optional. Specifies the page number of the results beginning at 1. A single page contains 5000 ids. This is recommended for users with large ID lists. If not provided all ids are returned. (Please note that the result set isn't guaranteed to be 5000 every time as suspended users will be filtered out.) + cursor - Optional. Breaks the results into pages. A single page contains 5000 ids. This is recommended for users with large ID lists. Provide a value of -1 to begin paging. Provide values as returned to in the response body's "next_cursor" and "previous_cursor" attributes to page back and forth in the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion apiURL = "" + breakResults = "cursor=%s" % cursor + if page is not None: + breakResults = "page=%s" % page if id is not None: - apiURL = "http://twitter.com/followers/ids/" + id + ".json" + "?page=" + page + apiURL = "http://api.twitter.com/%d/followers/ids/%s.json?%s" % (version, `id`, breakResults) if user_id is not None: - apiURL = "http://twitter.com/followers/ids.json?user_id=" + user_id + "&page=" + page + apiURL = "http://api.twitter.com/%d/followers/ids.json?user_id=%s&%s" %(version, `user_id`, breakResults) if screen_name is not None: - apiURL = "http://twitter.com/followers/ids.json?screen_name=" + screen_name + "&page=" + page + apiURL = "http://api.twitter.com/%d/followers/ids.json?screen_name=%s&%s" %(version, screen_name, breakResults) try: return simplejson.load(urllib2.urlopen(apiURL)) except HTTPError, e: - raise TangoError("getFollowersIDs() failed with a %s error code." % `e.code`, e.code) - - def createBlock(self, id): + raise TwythonError("getFollowersIDs() failed with a %s error code." % `e.code`, e.code) + + def createBlock(self, id, version = None): + """createBlock(id) + + Blocks the user specified in the ID parameter as the authenticating user. Destroys a friendship to the blocked user if it exists. + Returns the blocked user in the requested format when successful. + + Parameters: + id - The ID or screen name of a user to block. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/blocks/create/" + id + ".json", "")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/blocks/create/%s.json" % (version, `id`), "")) except HTTPError, e: - raise TangoError("createBlock() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("createBlock() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("createBlock() requires you to be authenticated.") - - def destroyBlock(self, id): + raise AuthError("createBlock() requires you to be authenticated.") + + def destroyBlock(self, id, version = None): + """destroyBlock(id) + + Un-blocks the user specified in the ID parameter for the authenticating user. + Returns the un-blocked user in the requested format when successful. + + Parameters: + id - Required. The ID or screen_name of the user to un-block + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/blocks/destroy/" + id + ".json", "")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/blocks/destroy/%s.json" % (version, `id`), "")) except HTTPError, e: - raise TangoError("destroyBlock() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("destroyBlock() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("destroyBlock() requires you to be authenticated.") - - def checkIfBlockExists(self, id = None, user_id = None, screen_name = None): + raise AuthError("destroyBlock() requires you to be authenticated.") + + def checkIfBlockExists(self, id = None, user_id = None, screen_name = None, version = None): + """checkIfBlockExists(id = None, user_id = None, screen_name = None) + + Returns if the authenticating user is blocking a target user. Will return the blocked user's object if a block exists, and + error with an HTTP 404 response code otherwise. + + Parameters: + ** Note: One of the following is required. (id, user_id, screen_name) + id - Optional. The ID or screen_name of the potentially blocked user. + user_id - Optional. Specfies the ID of the potentially blocked user. Helpful for disambiguating when a valid user ID is also a valid screen name. + screen_name - Optional. Specfies the screen name of the potentially blocked user. Helpful for disambiguating when a valid screen name is also a user ID. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion apiURL = "" if id is not None: - apiURL = "http://twitter.com/blocks/exists/" + id + ".json" + apiURL = "http://api.twitter.com/%d/blocks/exists/%s.json" % (version, `id`) if user_id is not None: - apiURL = "http://twitter.com/blocks/exists.json?user_id=" + user_id + apiURL = "http://api.twitter.com/%d/blocks/exists.json?user_id=%s" % (version, `user_id`) if screen_name is not None: - apiURL = "http://twitter.com/blocks/exists.json?screen_name=" + screen_name + apiURL = "http://api.twitter.com/%d/blocks/exists.json?screen_name=%s" % (version, screen_name) try: return simplejson.load(urllib2.urlopen(apiURL)) except HTTPError, e: - raise TangoError("checkIfBlockExists() failed with a %s error code." % `e.code`, e.code) - - def getBlocking(self, page = "1"): + raise TwythonError("checkIfBlockExists() failed with a %s error code." % `e.code`, e.code) + + def getBlocking(self, page = "1", version = None): + """getBlocking(page = "1") + + Returns an array of user objects that the authenticating user is blocking. + + Parameters: + page - Optional. Specifies the page number of the results beginning at 1. A single page contains 20 ids. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/blocks/blocking.json?page=" + page)) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/blocks/blocking.json?page=%s" % (version, `page`))) except HTTPError, e: - raise TangoError("getBlocking() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("getBlocking() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("getBlocking() requires you to be authenticated") - - def getBlockedIDs(self): + raise AuthError("getBlocking() requires you to be authenticated") + + def getBlockedIDs(self, version = None): + """getBlockedIDs() + + Returns an array of numeric user ids the authenticating user is blocking. + + Parameters: + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/blocks/blocking/ids.json")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/blocks/blocking/ids.json" % version)) except HTTPError, e: - raise TangoError("getBlockedIDs() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("getBlockedIDs() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("getBlockedIDs() requires you to be authenticated.") - + raise AuthError("getBlockedIDs() requires you to be authenticated.") + def searchTwitter(self, search_query, **kwargs): - searchURL = self.constructApiURL("http://search.twitter.com/search.json", kwargs) + "&" + urllib.urlencode({"q": search_query}) + """searchTwitter(search_query, **kwargs) + + Returns tweets that match a specified query. + + Parameters: + callback - Optional. Only available for JSON format. If supplied, the response will use the JSONP format with a callback of the given name. + lang - Optional. Restricts tweets to the given language, given by an ISO 639-1 code. + locale - Optional. Language of the query you're sending (only ja is currently effective). Intended for language-specific clients; default should work in most cases. + rpp - Optional. The number of tweets to return per page, up to a max of 100. + page - Optional. The page number (starting at 1) to return, up to a max of roughly 1500 results (based on rpp * page. Note: there are pagination limits.) + since_id - Optional. Returns tweets with status ids greater than the given id. + geocode - Optional. Returns tweets by users located within a given radius of the given latitude/longitude, where the user's location is taken from their Twitter profile. The parameter value is specified by "latitide,longitude,radius", where radius units must be specified as either "mi" (miles) or "km" (kilometers). Note that you cannot use the near operator via the API to geocode arbitrary locations; however you can use this geocode parameter to search near geocodes directly. + show_user - Optional. When true, prepends ":" to the beginning of the tweet. This is useful for readers that do not display Atom's author field. The default is false. + + Usage Notes: + Queries are limited 140 URL encoded characters. + Some users may be absent from search results. + The since_id parameter will be removed from the next_page element as it is not supported for pagination. If since_id is removed a warning will be added to alert you. + This method will return an HTTP 404 error if since_id is used and is too old to be in the search index. + + Applications must have a meaningful and unique User Agent when using this method. + An HTTP Referrer is expected but not required. Search traffic that does not include a User Agent will be rate limited to fewer API calls per hour than + applications including a User Agent string. You can set your custom UA headers by passing it as a respective argument to the setup() method. + """ + searchURL = self.constructApiURL("http://search.twitter.com/search.json", kwargs) + "&" + urllib.urlencode({"q": self.unicode2utf8(search_query)}) try: return simplejson.load(urllib2.urlopen(searchURL)) except HTTPError, e: - raise TangoError("getSearchTimeline() failed with a %s error code." % `e.code`, e.code) - + raise TwythonError("getSearchTimeline() failed with a %s error code." % `e.code`, e.code) + def getCurrentTrends(self, excludeHashTags = False): + """getCurrentTrends(excludeHashTags = False) + + Returns the current top 10 trending topics on Twitter. The response includes the time of the request, the name of each trending topic, and the query used + on Twitter Search results page for that topic. + + Parameters: + excludeHashTags - Optional. Setting this equal to hashtags will remove all hashtags from the trends list. + """ apiURL = "http://search.twitter.com/trends/current.json" if excludeHashTags is True: apiURL += "?exclude=hashtags" try: return simplejson.load(urllib.urlopen(apiURL)) except HTTPError, e: - raise TangoError("getCurrentTrends() failed with a %s error code." % `e.code`, e.code) - + raise TwythonError("getCurrentTrends() failed with a %s error code." % `e.code`, e.code) + def getDailyTrends(self, date = None, exclude = False): + """getDailyTrends(date = None, exclude = False) + + Returns the top 20 trending topics for each hour in a given day. + + Parameters: + date - Optional. Permits specifying a start date for the report. The date should be formatted YYYY-MM-DD. + exclude - Optional. Setting this equal to hashtags will remove all hashtags from the trends list. + """ apiURL = "http://search.twitter.com/trends/daily.json" questionMarkUsed = False if date is not None: - apiURL += "?date=" + date + apiURL += "?date=%s" % date questionMarkUsed = True if exclude is True: if questionMarkUsed is True: @@ -546,13 +1297,21 @@ class setup: try: return simplejson.load(urllib.urlopen(apiURL)) except HTTPError, e: - raise TangoError("getDailyTrends() failed with a %s error code." % `e.code`, e.code) - + raise TwythonError("getDailyTrends() failed with a %s error code." % `e.code`, e.code) + def getWeeklyTrends(self, date = None, exclude = False): + """getWeeklyTrends(date = None, exclude = False) + + Returns the top 30 trending topics for each day in a given week. + + Parameters: + date - Optional. Permits specifying a start date for the report. The date should be formatted YYYY-MM-DD. + exclude - Optional. Setting this equal to hashtags will remove all hashtags from the trends list. + """ apiURL = "http://search.twitter.com/trends/daily.json" questionMarkUsed = False if date is not None: - apiURL += "?date=" + date + apiURL += "?date=%s" % date questionMarkUsed = True if exclude is True: if questionMarkUsed is True: @@ -562,73 +1321,440 @@ class setup: try: return simplejson.load(urllib.urlopen(apiURL)) except HTTPError, e: - raise TangoError("getWeeklyTrends() failed with a %s error code." % `e.code`, e.code) - - def getSavedSearches(self): + raise TwythonError("getWeeklyTrends() failed with a %s error code." % `e.code`, e.code) + + def getSavedSearches(self, version = None): + """getSavedSearches() + + Returns the authenticated user's saved search queries. + + Parameters: + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/saved_searches.json")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/saved_searches.json" % version)) except HTTPError, e: - raise TangoError("getSavedSearches() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("getSavedSearches() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("getSavedSearches() requires you to be authenticated.") - - def showSavedSearch(self, id): + raise AuthError("getSavedSearches() requires you to be authenticated.") + + def showSavedSearch(self, id, version = None): + """showSavedSearch(id) + + Retrieve the data for a saved search owned by the authenticating user specified by the given id. + + Parameters: + id - Required. The id of the saved search to be retrieved. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/saved_searches/show/" + id + ".json")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/saved_searches/show/%s.json" % (version, `id`))) except HTTPError, e: - raise TangoError("showSavedSearch() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("showSavedSearch() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("showSavedSearch() requires you to be authenticated.") - - def createSavedSearch(self, query): + raise AuthError("showSavedSearch() requires you to be authenticated.") + + def createSavedSearch(self, query, version = None): + """createSavedSearch(query) + + Creates a saved search for the authenticated user. + + Parameters: + query - Required. The query of the search the user would like to save. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/saved_searches/create.json?query=" + query, "")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/saved_searches/create.json?query=%s" % (version, query), "")) except HTTPError, e: - raise TangoError("createSavedSearch() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("createSavedSearch() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("createSavedSearch() requires you to be authenticated.") - - def destroySavedSearch(self, id): + raise AuthError("createSavedSearch() requires you to be authenticated.") + + def destroySavedSearch(self, id, version = None): + """ destroySavedSearch(id) + + Destroys a saved search for the authenticated user. + The search specified by id must be owned by the authenticating user. + + Parameters: + id - Required. The id of the saved search to be deleted. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - return simplejson.load(self.opener.open("http://twitter.com/saved_searches/destroy/" + id + ".json", "")) + return simplejson.load(self.opener.open("http://api.twitter.com/%d/saved_searches/destroy/%s.json" % (version, `id`), "")) except HTTPError, e: - raise TangoError("destroySavedSearch() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("destroySavedSearch() failed with a %s error code." % `e.code`, e.code) else: - raise TangoError("destroySavedSearch() requires you to be authenticated.") + raise AuthError("destroySavedSearch() requires you to be authenticated.") + + def createList(self, name, mode = "public", description = "", version = None): + """ createList(self, name, mode, description, version) + + Creates a new list for the currently authenticated user. (Note: This may encounter issues if you authenticate with an email; try username (screen name) instead). + + Parameters: + name - Required. The name for the new list. + description - Optional, in the sense that you can leave it blank if you don't want one. ;) + mode - Optional. This is a string indicating "public" or "private", defaults to "public". + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/lists.json" % (version, self.username), + urllib.urlencode({"name": name, "mode": mode, "description": description}))) + except HTTPError, e: + raise TwythonError("createList() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("createList() requires you to be authenticated.") + + def updateList(self, list_id, name, mode = "public", description = "", version = None): + """ updateList(self, list_id, name, mode, description, version) + + Updates an existing list for the authenticating user. (Note: This may encounter issues if you authenticate with an email; try username (screen name) instead). + This method is a bit cumbersome for the time being; I'd personally avoid using it unless you're positive you know what you're doing. Twitter should really look + at this... + + Parameters: + list_id - Required. The name of the list (this gets turned into a slug - e.g, "Huck Hound" becomes "huck-hound"). + name - Required. The name of the list, possibly for renaming or such. + description - Optional, in the sense that you can leave it blank if you don't want one. ;) + mode - Optional. This is a string indicating "public" or "private", defaults to "public". + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/lists/%s.json" % (version, self.username, list_id), + urllib.urlencode({"name": name, "mode": mode, "description": description}))) + except HTTPError, e: + raise TwythonError("updateList() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("updateList() requires you to be authenticated.") + + def showLists(self, version = None): + """ showLists(self, version) + + Show all the lists for the currently authenticated user (i.e, they own these lists). + (Note: This may encounter issues if you authenticate with an email; try username (screen name) instead). + + Parameters: + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/lists.json" % (version, self.username))) + except HTTPError, e: + raise TwythonError("showLists() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("showLists() requires you to be authenticated.") + + def getListMemberships(self, version = None): + """ getListMemberships(self, version) + + Get all the lists for the currently authenticated user (i.e, they're on all the lists that are returned, the lists belong to other people) + (Note: This may encounter issues if you authenticate with an email; try username (screen name) instead). + + Parameters: + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/lists/followers.json" % (version, self.username))) + except HTTPError, e: + raise TwythonError("getLists() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("getLists() requires you to be authenticated.") + + def deleteList(self, list_id, version = None): + """ deleteList(self, list_id, version) + + Deletes a list for the authenticating user. + + Parameters: + list_id - Required. The name of the list to delete - this gets turned into a slug, so you can pass it as that, or hope the transformation works out alright. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/lists/%s.json" % (version, self.username, list_id), "_method=DELETE")) + except HTTPError, e: + raise TwythonError("deleteList() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("deleteList() requires you to be authenticated.") + + def getListTimeline(self, list_id, cursor = "-1", version = None, **kwargs): + """ getListTimeline(self, list_id, cursor, version, **kwargs) + + Retrieves a timeline representing everyone in the list specified. + + Parameters: + list_id - Required. The name of the list to get a timeline for - this gets turned into a slug, so you can pass it as that, or hope the transformation works out alright. + since_id - Optional. Returns only statuses with an ID greater than (that is, more recent than) the specified ID. + max_id - Optional. Returns only statuses with an ID less than (that is, older than) or equal to the specified ID. + count - Optional. Specifies the number of statuses to retrieve. May not be greater than 200. + cursor - Optional. Breaks the results into pages. Provide a value of -1 to begin paging. + Provide values returned in the response's "next_cursor" and "previous_cursor" attributes to page back and forth in the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + try: + baseURL = self.constructApiURL("http://api.twitter.com/%d/%s/lists/%s/statuses.json" % (version, self.username, list_id), kwargs) + return simplejson.load(self.opener.open(baseURL + "&cursor=%s" % cursor)) + except HTTPError, e: + if e.code == 404: + raise AuthError("It seems the list you're trying to access is private/protected, and you don't have access. Are you authenticated and allowed?") + raise TwythonError("getListTimeline() failed with a %d error code." % e.code, e.code) + + def getSpecificList(self, list_id, version = None): + """ getSpecificList(self, list_id, version) + + Retrieve a specific list - this only requires authentication if the list you're requesting is protected/private (if it is, you need to have access as well). + + Parameters: + list_id - Required. The name of the list to get - this gets turned into a slug, so you can pass it as that, or hope the transformation works out alright. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + try: + if self.authenticated is True: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/lists/%s/statuses.json" % (version, self.username, list_id))) + else: + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/%s/lists/%s/statuses.json" % (version, self.username, list_id))) + except HTTPError, e: + if e.code == 404: + raise AuthError("It seems the list you're trying to access is private/protected, and you don't have access. Are you authenticated and allowed?") + raise TwythonError("getSpecificList() failed with a %d error code." % e.code, e.code) + + def addListMember(self, list_id, version = None): + """ addListMember(self, list_id, id, version) + + Adds a new Member (the passed in id) to the specified list. + + Parameters: + list_id - Required. The slug of the list to add the new member to. + id - Required. The ID of the user that's being added to the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/%s/members.json" % (version, self.username, list_id), "id=%s" % `id`)) + except HTTPError, e: + raise TwythonError("addListMember() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("addListMember requires you to be authenticated.") + + def getListMembers(self, list_id, version = None): + """ getListMembers(self, list_id, version = None) + + Show all members of a specified list. This method requires authentication if the list is private/protected. + + Parameters: + list_id - Required. The slug of the list to retrieve members for. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + try: + if self.authenticated is True: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/%s/members.json" % (version, self.username, list_id))) + else: + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/%s/%s/members.json" % (version, self.username, list_id))) + except HTTPError, e: + raise TwythonError("getListMembers() failed with a %d error code." % e.code, e.code) + + def removeListMember(self, list_id, id, version = None): + """ removeListMember(self, list_id, id, version) + + Remove the specified user (id) from the specified list (list_id). Requires you to be authenticated and in control of the list in question. + + Parameters: + list_id - Required. The slug of the list to remove the specified user from. + id - Required. The ID of the user that's being added to the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/%s/members.json" % (version, self.username, list_id), "_method=DELETE")) + except HTTPError, e: + raise TwythonError("getListMembers() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("removeListMember() requires you to be authenticated.") + + def isListMember(self, list_id, id, version = None): + """ isListMember(self, list_id, id, version) + + Check if a specified user (id) is a member of the list in question (list_id). + + **Note: This method may not work for private/protected lists, unless you're authenticated and have access to those lists. + + Parameters: + list_id - Required. The slug of the list to check against. + id - Required. The ID of the user being checked in the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + try: + if self.authenticated is True: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/%s/members/%s.json" % (version, self.username, list_id, `id`))) + else: + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/%s/%s/members/%s.json" % (version, self.username, list_id, `id`))) + except HTTPError, e: + raise TwythonError("isListMember() failed with a %d error code." % e.code, e.code) + + def subscribeToList(self, list_id, version): + """ subscribeToList(self, list_id, version) + + Subscribe the authenticated user to the list provided (must be public). + + Parameters: + list_id - Required. The list to subscribe to. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/%s/following.json" % (version, self.username, list_id), "")) + except HTTPError, e: + raise TwythonError("subscribeToList() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("subscribeToList() requires you to be authenticated.") + + def unsubscribeFromList(self, list_id, version): + """ unsubscribeFromList(self, list_id, version) + + Unsubscribe the authenticated user from the list in question (must be public). + + Parameters: + list_id - Required. The list to unsubscribe from. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + if self.authenticated is True: + try: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/%s/following.json" % (version, self.username, list_id), "_method=DELETE")) + except HTTPError, e: + raise TwythonError("unsubscribeFromList() failed with a %d error code." % e.code, e.code) + else: + raise AuthError("unsubscribeFromList() requires you to be authenticated.") + + def isListSubscriber(self, list_id, id, version = None): + """ isListSubscriber(self, list_id, id, version) + + Check if a specified user (id) is a subscriber of the list in question (list_id). + + **Note: This method may not work for private/protected lists, unless you're authenticated and have access to those lists. + + Parameters: + list_id - Required. The slug of the list to check against. + id - Required. The ID of the user being checked in the list. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + try: + if self.authenticated is True: + return simplejson.load(self.opener.open("http://api.twitter.com/%d/%s/%s/following/%s.json" % (version, self.username, list_id, `id`))) + else: + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/%s/%s/following/%s.json" % (version, self.username, list_id, `id`))) + except HTTPError, e: + raise TwythonError("isListMember() failed with a %d error code." % e.code, e.code) + + def availableTrends(self, latitude = None, longitude = None, version = None): + """ availableTrends(latitude, longitude, version): + + Gets all available trends, optionally filtering by geolocation based stuff. + + Note: If you choose to pass a latitude/longitude, keep in mind that you have to pass both - one won't work by itself. ;P + + Parameters: + latitude (string) - Optional. A latitude to sort by. + longitude (string) - Optional. A longitude to sort by. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + try: + if latitude is not None and longitude is not None: + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/trends/available.json?latitude=%s&longitude=%s" % (version, latitude, longitude))) + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/trends/available.json" % version)) + except HTTPError, e: + raise TwythonError("availableTrends() failed with a %d error code." % e.code, e.code) + + def trendsByLocation(self, woeid, version = None): + """ trendsByLocation(woeid, version): + + Gets all available trends, filtering by geolocation (woeid - see http://developer.yahoo.com/geo/geoplanet/guide/concepts.html). + + Note: If you choose to pass a latitude/longitude, keep in mind that you have to pass both - one won't work by itself. ;P + + Parameters: + woeid (string) - Required. WoeID of the area you're searching in. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion + try: + return simplejson.load(urllib2.urlopen("http://api.twitter.com/%d/trends/%s.json" % (version, woeid))) + except HTTPError, e: + raise TwythonError("trendsByLocation() failed with a %d error code." % e.code, e.code) # The following methods are apart from the other Account methods, because they rely on a whole multipart-data posting function set. - def updateProfileBackgroundImage(self, filename, tile="true"): + def updateProfileBackgroundImage(self, filename, tile="true", version = None): + """ updateProfileBackgroundImage(filename, tile="true") + + Updates the authenticating user's profile background image. + + Parameters: + image - Required. Must be a valid GIF, JPG, or PNG image of less than 800 kilobytes in size. Images with width larger than 2048 pixels will be forceably scaled down. + tile - Optional (defaults to true). If set to true the background image will be displayed tiled. The image will not be tiled otherwise. + ** Note: It's sad, but when using this method, pass the tile value as a string, e.g tile="false" + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - files = [("image", filename, open(filename).read())] + files = [("image", filename, open(filename, 'rb').read())] fields = [] content_type, body = self.encode_multipart_formdata(fields, files) headers = {'Content-Type': content_type, 'Content-Length': str(len(body))} - r = urllib2.Request("http://twitter.com/account/update_profile_background_image.json?tile=" + tile, body, headers) + r = urllib2.Request("http://api.twitter.com/%d/account/update_profile_background_image.json?tile=%s" % (version, tile), body, headers) return self.opener.open(r).read() except HTTPError, e: - raise TangoError("updateProfileBackgroundImage() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("updateProfileBackgroundImage() failed with a %d error code." % e.code, e.code) else: - raise TangoError("You realize you need to be authenticated to change a background image, right?") - - def updateProfileImage(self, filename): + raise AuthError("You realize you need to be authenticated to change a background image, right?") + + def updateProfileImage(self, filename, version = None): + """ updateProfileImage(filename) + + Updates the authenticating user's profile image (avatar). + + Parameters: + image - Required. Must be a valid GIF, JPG, or PNG image of less than 700 kilobytes in size. Images with width larger than 500 pixels will be scaled down. + version (number) - Optional. API version to request. Entire Twython class defaults to 1, but you can override on a function-by-function or class basis - (version=2), etc. + """ + version = version or self.apiVersion if self.authenticated is True: try: - files = [("image", filename, open(filename).read())] + files = [("image", filename, open(filename, 'rb').read())] fields = [] content_type, body = self.encode_multipart_formdata(fields, files) headers = {'Content-Type': content_type, 'Content-Length': str(len(body))} - r = urllib2.Request("http://twitter.com/account/update_profile_image.json", body, headers) + r = urllib2.Request("http://api.twitter.com/%d/account/update_profile_image.json" % version, body, headers) return self.opener.open(r).read() except HTTPError, e: - raise TangoError("updateProfileImage() failed with a %s error code." % `e.code`, e.code) + raise TwythonError("updateProfileImage() failed with a %d error code." % e.code, e.code) else: - raise TangoError("You realize you need to be authenticated to change a profile image, right?") - + raise AuthError("You realize you need to be authenticated to change a profile image, right?") + def encode_multipart_formdata(self, fields, files): BOUNDARY = mimetools.choose_boundary() CRLF = '\r\n' @@ -649,6 +1775,18 @@ class setup: body = CRLF.join(L) content_type = 'multipart/form-data; boundary=%s' % BOUNDARY return content_type, body - + def get_content_type(self, filename): + """ get_content_type(self, filename) + + Exactly what you think it does. :D + """ return mimetypes.guess_type(filename)[0] or 'application/octet-stream' + + def unicode2utf8(self, text): + try: + if isinstance(text, unicode): + text = text.encode('utf-8') + except: + pass + return text diff --git a/dist/twython-0.9.macosx-10.5-i386.tar.gz b/dist/twython-0.9.macosx-10.5-i386.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6e3e62b54f47a51b73cf3c728d7ffbb45b12c1c2 GIT binary patch literal 58118 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 PeDl9w3Q+;<0|NXH=9Phb literal 0 HcmV?d00001 diff --git a/dist/twython-0.9.win32.exe b/dist/twython-0.9.win32.exe new file mode 100644 index 0000000000000000000000000000000000000000..c1f416ea0d91f4d504b81d4322276e55593a7341 GIT binary patch literal 90830 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 CfJ>nO literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index fb1900c..f5c956f 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ import sys, os __author__ = 'Ryan McGrath ' -__version__ = '0.8' +__version__ = '0.9' # For the love of god, use Pip to install this. @@ -12,13 +12,13 @@ METADATA = dict( name = "twython", version = __version__, py_modules = ['twython'], - author='Ryan McGrath', - author_email='ryan@venodesigns.net', - description='A new and easy way to access Twitter data with Python.', - long_description= open("README.markdown").read(), - license='MIT License', - url='http://github.com/ryanmcgrath/twython/tree/master', - keywords='twitter search api tweet twython', + author = 'Ryan McGrath', + author_email = 'ryan@venodesigns.net', + description = 'An easy (and up to date) way to access Twitter data with Python.', + long_description = open("README.markdown").read(), + license = 'MIT License', + url = 'http://github.com/ryanmcgrath/twython/tree/master', + keywords = 'twitter search api tweet twython', ) # Setuptools version diff --git a/twython.egg-info/PKG-INFO b/twython.egg-info/PKG-INFO index ade4232..8359b77 100644 --- a/twython.egg-info/PKG-INFO +++ b/twython.egg-info/PKG-INFO @@ -1,13 +1,13 @@ Metadata-Version: 1.0 Name: twython -Version: 0.8 -Summary: A new and easy way to access Twitter data with Python. +Version: 0.9 +Summary: An easy (and up to date) way to access Twitter data with Python. Home-page: http://github.com/ryanmcgrath/twython/tree/master Author: Ryan McGrath Author-email: ryan@venodesigns.net License: MIT License Description: Twython - Easy Twitter utilities in Python - ----------------------------------------------------------------------------------------------------- + ========================================================================================= I wrote Twython because I found that other Python Twitter libraries weren't that up to date. Certain things like the Search API, OAuth, etc, don't seem to be fully covered. This is my attempt at a library that offers more coverage. @@ -16,28 +16,27 @@ Description: Twython - Easy Twitter utilities in Python make a seasoned Python vet scratch his head, or possibly call me insane. It's open source, though, and I'm open to anything that'll improve the library as a whole. - OAuth support is in the works, but every other part of the Twitter API should be covered. Twython - handles both Basic (HTTP) Authentication and OAuth, and OAuth is the default method for - Authentication. To override this, specify 'authtype="Basic"' in your twython.setup() call. - - Documentation is forthcoming, but Twython attempts to mirror the Twitter API in a large way. All - parameters for API calls should translate over as function arguments. + OAuth and Streaming API support is in the works, but every other part of the Twitter API should be covered. Twython + handles both Basic (HTTP) Authentication and OAuth (Older versions (pre 0.9) of Twython need Basic Auth specified - + to override this, specify 'authtype="Basic"' in your twython.setup() call). + Twython has Docstrings if you want function-by-function plays; otherwise, check the Twython Wiki or + Twitter's API Wiki (Twython calls mirror most of the methods listed there). Requirements ----------------------------------------------------------------------------------------------------- Twython requires (much like Python-Twitter, because they had the right idea :D) a library called "simplejson". You can grab it at the following link: - http://pypi.python.org/pypi/simplejson + > http://pypi.python.org/pypi/simplejson Example Use ----------------------------------------------------------------------------------------------------- - import twython - - twitter = twython.setup(authtype="Basic", username="example", password="example") - twitter.updateStatus("See how easy this was?") + > import twython + > + > twitter = twython.setup(username="example", password="example") + > twitter.updateStatus("See how easy this was?") Twython 3k diff --git a/twython.egg-info/SOURCES.txt b/twython.egg-info/SOURCES.txt index 3a6ce67..26a7786 100644 --- a/twython.egg-info/SOURCES.txt +++ b/twython.egg-info/SOURCES.txt @@ -1,4 +1,3 @@ -README setup.py twython.py twython.egg-info/PKG-INFO diff --git a/twython.py b/twython.py index cf05f71..ffe31e5 100644 --- a/twython.py +++ b/twython.py @@ -16,7 +16,7 @@ from urlparse import urlparse from urllib2 import HTTPError __author__ = "Ryan McGrath " -__version__ = "0.8" +__version__ = "0.9" """Twython - Easy Twitter utilities in Python""" diff --git a/twython3k.py b/twython3k.py index dc7026c..b05b1f2 100644 --- a/twython3k.py +++ b/twython3k.py @@ -16,7 +16,7 @@ from urllib.parse import urlparse from urllib.error import HTTPError __author__ = "Ryan McGrath " -__version__ = "0.8" +__version__ = "0.9" """Twython - Easy Twitter utilities in Python"""