Fairly large commit - this should fix a slew of issues with passing results from functions (follower ids, for instance) to other functions. Before, they were returned as Numbers, but most functions expect Strings, so there's an extra conversion layer now which should help out on that front. urlencode also properly encodes to utf-8 now (major thanks to contributions from Maatsu on this). Password is also no longer stored as an instance variable. These changes are mirrored in Twython3k, but I've not yet had time to test that in full - as with anything Python3k related, proceed with caution. (There are also some changes relating to how string concatenation is done, but that's all minor in scope)

This commit is contained in:
Ryan McGrath 2009-08-24 02:47:02 -04:00
parent 6ab69d4636
commit 90789b73eb
2 changed files with 207 additions and 200 deletions

View file

@ -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 <ryan@venodesigns.net>"
__version__ = "0.6"
__version__ = "0.7a"
"""Twython - Easy Twitter utilities in Python"""
@ -55,18 +53,11 @@ class AuthError(TwythonError):
def __str__(self):
return repr(self.msg)
# A simple decorator to clean up some authentication checks that exist all over.
# Not implemented yet -
def requires_authentication(func):
print func
# raise AuthError("This function requires you to be authenticated. Double check that and try again!")
class setup:
def __init__(self, authtype = "OAuth", username = None, password = None, consumer_secret = None, consumer_key = None, headers = None):
self.authtype = authtype
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'
@ -77,11 +68,11 @@ class setup:
self.request_token = None
self.access_token = None
# Check and set up authentication
if self.username is not None and self.password is not None:
if self.username is not None and 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.auth_manager.add_password(None, "http://twitter.com", self.username, password)
self.handler = urllib2.HTTPBasicAuthHandler(self.auth_manager)
self.opener = urllib2.build_opener(self.handler)
if headers is not None:
@ -121,7 +112,7 @@ class setup:
# URL Shortening function huzzah
def shortenURL(self, url_to_shorten, shortener = "http://is.gd/api.php", query = "longurl"):
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 TwythonError("shortenURL() failed with a %s error code." % `e.code`)
@ -154,7 +145,7 @@ class setup:
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 TwythonError("getHomeTimeline() requires you to be authenticated.")
raise AuthError("getHomeTimeline() requires you to be authenticated.")
def getFriendsTimeline(self, **kwargs):
if self.authenticated is True:
@ -164,13 +155,13 @@ class setup:
except HTTPError, e:
raise TwythonError("getFriendsTimeline() failed with a %s error code." % `e.code`)
else:
raise TwythonError("getFriendsTimeline() requires you to be authenticated.")
raise AuthError("getFriendsTimeline() requires you to be authenticated.")
def getUserTimeline(self, id = None, **kwargs):
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://twitter.com/statuses/user_timeline/%s.json" % `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://twitter.com/statuses/user_timeline/%s.json" % self.username, kwargs)
else:
userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline.json", kwargs)
try:
@ -191,7 +182,7 @@ class setup:
except HTTPError, e:
raise TwythonError("getUserMentions() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("getUserMentions() requires you to be authenticated.")
raise AuthError("getUserMentions() requires you to be authenticated.")
def retweetedOfMe(self, **kwargs):
if self.authenticated is True:
@ -201,7 +192,7 @@ class setup:
except HTTPError, e:
raise TwythonError("retweetedOfMe() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("retweetedOfMe() requires you to be authenticated.")
raise AuthError("retweetedOfMe() requires you to be authenticated.")
def retweetedByMe(self, **kwargs):
if self.authenticated is True:
@ -211,7 +202,7 @@ class setup:
except HTTPError, e:
raise TwythonError("retweetedByMe() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("retweetedByMe() requires you to be authenticated.")
raise AuthError("retweetedByMe() requires you to be authenticated.")
def retweetedToMe(self, **kwargs):
if self.authenticated is True:
@ -221,7 +212,7 @@ class setup:
except HTTPError, e:
raise TwythonError("retweetedToMe() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("retweetedToMe() requires you to be authenticated.")
raise AuthError("retweetedToMe() requires you to be authenticated.")
def showStatus(self, id):
try:
@ -237,7 +228,7 @@ class setup:
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://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://twitter.com/statuses/update.json?", urllib.urlencode({"status": self.unicode2utf8(status), "in_reply_to_status_id": in_reply_to_status_id})))
except HTTPError, e:
raise TwythonError("updateStatus() failed with a %s error code." % `e.code`, e.code)
@ -248,7 +239,7 @@ class setup:
except HTTPError, e:
raise TwythonError("destroyStatus() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("destroyStatus() requires you to be authenticated.")
raise AuthError("destroyStatus() requires you to be authenticated.")
def reTweet(self, id):
if self.authenticated is True:
@ -257,7 +248,7 @@ class setup:
except HTTPError, e:
raise TwythonError("reTweet() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("reTweet() requires you to be authenticated.")
raise AuthError("reTweet() requires you to be authenticated.")
def endSession(self):
if self.authenticated is True:
@ -267,41 +258,41 @@ class setup:
except HTTPError, e:
raise TwythonError("endSession failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("You can't end a session when you're not authenticated to begin with.")
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"):
if self.authenticated is True:
apiURL = "http://twitter.com/direct_messages.json?page=" + page
apiURL = "http://twitter.com/direct_messages.json?page=%s" % `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 TwythonError("getDirectMessages() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("getDirectMessages() requires you to be authenticated.")
raise AuthError("getDirectMessages() requires you to be authenticated.")
def getSentMessages(self, since_id = None, max_id = None, count = None, page = "1"):
if self.authenticated is True:
apiURL = "http://twitter.com/direct_messages/sent.json?page=" + page
apiURL = "http://twitter.com/direct_messages/sent.json?page=%s" % `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 TwythonError("getSentMessages() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("getSentMessages() requires you to be authenticated.")
raise AuthError("getSentMessages() requires you to be authenticated.")
def sendDirectMessage(self, user, text):
if self.authenticated is True:
@ -313,7 +304,7 @@ class setup:
else:
raise TwythonError("Your message must not be longer than 140 characters")
else:
raise TwythonError("You must be authenticated to send a new direct message.")
raise AuthError("You must be authenticated to send a new direct message.")
def destroyDirectMessage(self, id):
if self.authenticated is True:
@ -322,17 +313,17 @@ class setup:
except HTTPError, e:
raise TwythonError("destroyDirectMessage() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("You must be authenticated to destroy a direct message.")
raise AuthError("You must be authenticated to destroy a direct message.")
def createFriendship(self, id = None, user_id = None, screen_name = None, follow = "false"):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/friendships/create/" + id + ".json" + "?follow=" + follow
apiURL = "http://twitter.com/friendships/create/%s.json?follow=%s" %(id, follow)
if user_id is not None:
apiURL = "http://twitter.com/friendships/create.json?user_id=" + user_id + "&follow=" + follow
apiURL = "http://twitter.com/friendships/create.json?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 = "http://twitter.com/friendships/create.json?screen_name=%s&follow=%s" %(screen_name, follow)
try:
return simplejson.load(self.opener.open(apiURL))
except HTTPError, e:
@ -341,23 +332,23 @@ class setup:
raise TwythonError("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 TwythonError("createFriendship() requires you to be authenticated.")
raise AuthError("createFriendship() requires you to be authenticated.")
def destroyFriendship(self, id = None, user_id = None, screen_name = None):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/friendships/destroy/" + id + ".json"
apiURL = "http://twitter.com/friendships/destroy/%s.json" % id
if user_id is not None:
apiURL = "http://twitter.com/friendships/destroy.json?user_id=" + user_id
apiURL = "http://twitter.com/friendships/destroy.json?user_id=%s" % `user_id`
if screen_name is not None:
apiURL = "http://twitter.com/friendships/destroy.json?screen_name=" + screen_name
apiURL = "http://twitter.com/friendships/destroy.json?screen_name=%s" % screen_name
try:
return simplejson.load(self.opener.open(apiURL))
except HTTPError, e:
raise TwythonError("destroyFriendship() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("destroyFriendship() requires you to be authenticated.")
raise AuthError("destroyFriendship() requires you to be authenticated.")
def checkIfFriendshipExists(self, user_a, user_b):
if self.authenticated is True:
@ -366,16 +357,16 @@ class setup:
except HTTPError, e:
raise TwythonError("checkIfFriendshipExists() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("checkIfFriendshipExists(), oddly, requires that you be authenticated.")
raise AuthError("checkIfFriendshipExists(), oddly, requires that you be authenticated.")
def updateDeliveryDevice(self, device_name = "none"):
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("http://twitter.com/account/update_delivery_device.json?", urllib.urlencode({"device": self.unicode2utf8(device_name)}))
except HTTPError, e:
raise TwythonError("updateDeliveryDevice() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("updateDeliveryDevice() requires you to be authenticated.")
raise AuthError("updateDeliveryDevice() requires you to be authenticated.")
def updateProfileColors(self, **kwargs):
if self.authenticated is True:
@ -384,7 +375,7 @@ class setup:
except HTTPError, e:
raise TwythonError("updateProfileColors() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("updateProfileColors() requires you to be authenticated.")
raise AuthError("updateProfileColors() requires you to be authenticated.")
def updateProfile(self, name = None, email = None, url = None, location = None, description = None):
if self.authenticated is True:
@ -408,27 +399,27 @@ class setup:
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 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 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 TwythonError("Twitter has a character limit of 160 for all descriptions. Try again.")
@ -438,75 +429,75 @@ class setup:
except HTTPError, e:
raise TwythonError("updateProfile() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("updateProfile() requires you to be authenticated.")
raise AuthError("updateProfile() requires you to be authenticated.")
def getFavorites(self, page = "1"):
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://twitter.com/favorites.json?page=%s" % `page`))
except HTTPError, e:
raise TwythonError("getFavorites() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("getFavorites() requires you to be authenticated.")
raise AuthError("getFavorites() requires you to be authenticated.")
def createFavorite(self, id):
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://twitter.com/favorites/create/%s.json" % `id`, ""))
except HTTPError, e:
raise TwythonError("createFavorite() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("createFavorite() requires you to be authenticated.")
raise AuthError("createFavorite() requires you to be authenticated.")
def destroyFavorite(self, id):
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://twitter.com/favorites/destroy/%s.json" % `id`, ""))
except HTTPError, e:
raise TwythonError("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 TwythonError("destroyFavorite() requires you to be authenticated.")
raise AuthError("destroyFavorite() requires you to be authenticated.")
def notificationFollow(self, id = None, user_id = None, screen_name = None):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/notifications/follow/" + id + ".json"
apiURL = "http://twitter.com/notifications/follow/%s.json" % id
if user_id is not None:
apiURL = "http://twitter.com/notifications/follow/follow.json?user_id=" + user_id
apiURL = "http://twitter.com/notifications/follow/follow.json?user_id=%s" % `user_id`
if screen_name is not None:
apiURL = "http://twitter.com/notifications/follow/follow.json?screen_name=" + screen_name
apiURL = "http://twitter.com/notifications/follow/follow.json?screen_name=%s" % screen_name
try:
return simplejson.load(self.opener.open(apiURL, ""))
except HTTPError, e:
raise TwythonError("notificationFollow() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("notificationFollow() requires you to be authenticated.")
raise AuthError("notificationFollow() requires you to be authenticated.")
def notificationLeave(self, id = None, user_id = None, screen_name = None):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/notifications/leave/" + id + ".json"
apiURL = "http://twitter.com/notifications/leave/%s.json" % id
if user_id is not None:
apiURL = "http://twitter.com/notifications/leave/leave.json?user_id=" + user_id
apiURL = "http://twitter.com/notifications/leave/leave.json?user_id=%s" % `user_id`
if screen_name is not None:
apiURL = "http://twitter.com/notifications/leave/leave.json?screen_name=" + screen_name
apiURL = "http://twitter.com/notifications/leave/leave.json?screen_name=%s" % screen_name
try:
return simplejson.load(self.opener.open(apiURL, ""))
except HTTPError, e:
raise TwythonError("notificationLeave() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("notificationLeave() requires you to be authenticated.")
raise AuthError("notificationLeave() requires you to be authenticated.")
def getFriendsIDs(self, id = None, user_id = None, screen_name = None, page = "1"):
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/friends/ids/" + id + ".json" + "?page=" + page
apiURL = "http://twitter.com/friends/ids/%s.json?page=%s" %(id, `page`)
if user_id is not None:
apiURL = "http://twitter.com/friends/ids.json?user_id=" + user_id + "&page=" + page
apiURL = "http://twitter.com/friends/ids.json?user_id=%s&page=%s" %(`user_id`, `page`)
if screen_name is not None:
apiURL = "http://twitter.com/friends/ids.json?screen_name=" + screen_name + "&page=" + page
apiURL = "http://twitter.com/friends/ids.json?screen_name=%s&page=%s" %(screen_name, `page`)
try:
return simplejson.load(urllib2.urlopen(apiURL))
except HTTPError, e:
@ -515,11 +506,11 @@ class setup:
def getFollowersIDs(self, id = None, user_id = None, screen_name = None, page = "1"):
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/followers/ids/" + id + ".json" + "?page=" + page
apiURL = "http://twitter.com/followers/ids/%s.json?page=%s" %(`id`, `page`)
if user_id is not None:
apiURL = "http://twitter.com/followers/ids.json?user_id=" + user_id + "&page=" + page
apiURL = "http://twitter.com/followers/ids.json?user_id=%s&page=%s" %(`user_id`, `page`)
if screen_name is not None:
apiURL = "http://twitter.com/followers/ids.json?screen_name=" + screen_name + "&page=" + page
apiURL = "http://twitter.com/followers/ids.json?screen_name=%s&page=%s" %(screen_name, `page`)
try:
return simplejson.load(urllib2.urlopen(apiURL))
except HTTPError, e:
@ -528,29 +519,29 @@ class setup:
def createBlock(self, id):
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://twitter.com/blocks/create/%s.json" % `id`, ""))
except HTTPError, e:
raise TwythonError("createBlock() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("createBlock() requires you to be authenticated.")
raise AuthError("createBlock() requires you to be authenticated.")
def destroyBlock(self, id):
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://twitter.com/blocks/destroy/%s.json" % `id`, ""))
except HTTPError, e:
raise TwythonError("destroyBlock() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("destroyBlock() requires you to be authenticated.")
raise AuthError("destroyBlock() requires you to be authenticated.")
def checkIfBlockExists(self, id = None, user_id = None, screen_name = None):
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/blocks/exists/" + id + ".json"
apiURL = "http://twitter.com/blocks/exists/%s.json" % `id`
if user_id is not None:
apiURL = "http://twitter.com/blocks/exists.json?user_id=" + user_id
apiURL = "http://twitter.com/blocks/exists.json?user_id=%s" % `user_id`
if screen_name is not None:
apiURL = "http://twitter.com/blocks/exists.json?screen_name=" + screen_name
apiURL = "http://twitter.com/blocks/exists.json?screen_name=%s" % screen_name
try:
return simplejson.load(urllib2.urlopen(apiURL))
except HTTPError, e:
@ -559,11 +550,11 @@ class setup:
def getBlocking(self, page = "1"):
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://twitter.com/blocks/blocking.json?page=%s" % `page`))
except HTTPError, e:
raise TwythonError("getBlocking() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("getBlocking() requires you to be authenticated")
raise AuthError("getBlocking() requires you to be authenticated")
def getBlockedIDs(self):
if self.authenticated is True:
@ -572,10 +563,10 @@ class setup:
except HTTPError, e:
raise TwythonError("getBlockedIDs() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("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})
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:
@ -594,7 +585,7 @@ class setup:
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:
@ -610,7 +601,7 @@ class setup:
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:
@ -629,34 +620,34 @@ class setup:
except HTTPError, e:
raise TwythonError("getSavedSearches() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("getSavedSearches() requires you to be authenticated.")
raise AuthError("getSavedSearches() requires you to be authenticated.")
def showSavedSearch(self, id):
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://twitter.com/saved_searches/show/%s.json" % `id`))
except HTTPError, e:
raise TwythonError("showSavedSearch() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("showSavedSearch() requires you to be authenticated.")
raise AuthError("showSavedSearch() requires you to be authenticated.")
def createSavedSearch(self, query):
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://twitter.com/saved_searches/create.json?query=%s" % query, ""))
except HTTPError, e:
raise TwythonError("createSavedSearch() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("createSavedSearch() requires you to be authenticated.")
raise AuthError("createSavedSearch() requires you to be authenticated.")
def destroySavedSearch(self, id):
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://twitter.com/saved_searches/destroy/%s.json" % `id`, ""))
except HTTPError, e:
raise TwythonError("destroySavedSearch() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("destroySavedSearch() requires you to be authenticated.")
raise AuthError("destroySavedSearch() requires you to be authenticated.")
# 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"):
@ -671,7 +662,7 @@ class setup:
except HTTPError, e:
raise TwythonError("updateProfileBackgroundImage() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("You realize you need to be authenticated to change a background image, right?")
raise AuthError("You realize you need to be authenticated to change a background image, right?")
def updateProfileImage(self, filename):
if self.authenticated is True:
@ -685,7 +676,7 @@ class setup:
except HTTPError, e:
raise TwythonError("updateProfileImage() failed with a %s error code." % `e.code`, e.code)
else:
raise TwythonError("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()
@ -710,3 +701,11 @@ class setup:
def get_content_type(self, filename):
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

View file

@ -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 urllib.parse import urlparse
from urllib.error import HTTPError
__author__ = "Ryan McGrath <ryan@venodesigns.net>"
__version__ = "0.6"
__version__ = "0.7a"
"""Twython - Easy Twitter utilities in Python"""
@ -49,12 +47,17 @@ class APILimit(TwythonError):
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
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'
@ -65,11 +68,11 @@ class setup:
self.request_token = None
self.access_token = None
# Check and set up authentication
if self.username is not None and self.password is not None:
if self.username is not None and password is not None:
if self.authtype == "Basic":
# Basic authentication ritual
self.auth_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
self.auth_manager.add_password(None, "http://twitter.com", self.username, self.password)
self.auth_manager.add_password(None, "http://twitter.com", self.username, password)
self.handler = urllib.request.HTTPBasicAuthHandler(self.auth_manager)
self.opener = urllib.request.build_opener(self.handler)
if headers is not None:
@ -109,7 +112,7 @@ class setup:
# URL Shortening function huzzah
def shortenURL(self, url_to_shorten, shortener = "http://is.gd/api.php", query = "longurl"):
try:
return urllib.request.urlopen(shortener + "?" + urllib.urlencode({query: url_to_shorten})).read()
return urllib.request.urlopen(shortener + "?" + urllib.urlencode({query: self.unicode2utf8(url_to_shorten)})).read()
except HTTPError as e:
raise TwythonError("shortenURL() failed with a %s error code." % repr(e.code))
@ -142,7 +145,7 @@ class setup:
except HTTPError as 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)" % repr(e.code))
else:
raise TwythonError("getHomeTimeline() requires you to be authenticated.")
raise AuthError("getHomeTimeline() requires you to be authenticated.")
def getFriendsTimeline(self, **kwargs):
if self.authenticated is True:
@ -152,13 +155,13 @@ class setup:
except HTTPError as e:
raise TwythonError("getFriendsTimeline() failed with a %s error code." % repr(e.code))
else:
raise TwythonError("getFriendsTimeline() requires you to be authenticated.")
raise AuthError("getFriendsTimeline() requires you to be authenticated.")
def getUserTimeline(self, id = None, **kwargs):
if id is not None and ("user_id" in kwargs) is False and ("screen_name" in kwargs) is False:
userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline/" + id + ".json", kwargs)
userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline/%s.json" % repr(id), kwargs)
elif id is None and ("user_id" in kwargs) is False and ("screen_name" in kwargs) is False and self.authenticated is True:
userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline/" + self.username + ".json", kwargs)
userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline/%s.json" % self.username, kwargs)
else:
userTimelineURL = self.constructApiURL("http://twitter.com/statuses/user_timeline.json", kwargs)
try:
@ -179,7 +182,7 @@ class setup:
except HTTPError as e:
raise TwythonError("getUserMentions() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("getUserMentions() requires you to be authenticated.")
raise AuthError("getUserMentions() requires you to be authenticated.")
def retweetedOfMe(self, **kwargs):
if self.authenticated is True:
@ -189,7 +192,7 @@ class setup:
except HTTPError as e:
raise TwythonError("retweetedOfMe() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("retweetedOfMe() requires you to be authenticated.")
raise AuthError("retweetedOfMe() requires you to be authenticated.")
def retweetedByMe(self, **kwargs):
if self.authenticated is True:
@ -199,7 +202,7 @@ class setup:
except HTTPError as e:
raise TwythonError("retweetedByMe() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("retweetedByMe() requires you to be authenticated.")
raise AuthError("retweetedByMe() requires you to be authenticated.")
def retweetedToMe(self, **kwargs):
if self.authenticated is True:
@ -209,7 +212,7 @@ class setup:
except HTTPError as e:
raise TwythonError("retweetedToMe() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("retweetedToMe() requires you to be authenticated.")
raise AuthError("retweetedToMe() requires you to be authenticated.")
def showStatus(self, id):
try:
@ -222,15 +225,12 @@ class setup:
% repr(e.code), e.code)
def updateStatus(self, status, in_reply_to_status_id = None):
if self.authenticated is True:
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://twitter.com/statuses/update.json?", urllib.parse.urlencode({"status": status, "in_reply_to_status_id": in_reply_to_status_id})))
except HTTPError as e:
raise TwythonError("updateStatus() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("updateStatus() requires you to be authenticated.")
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://twitter.com/statuses/update.json?", urllib.parse.urlencode({"status": self.unicode2utf8(status), "in_reply_to_status_id": in_reply_to_status_id})))
except HTTPError as e:
raise TwythonError("updateStatus() failed with a %s error code." % repr(e.code), e.code)
def destroyStatus(self, id):
if self.authenticated is True:
@ -239,7 +239,7 @@ class setup:
except HTTPError as e:
raise TwythonError("destroyStatus() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("destroyStatus() requires you to be authenticated.")
raise AuthError("destroyStatus() requires you to be authenticated.")
def reTweet(self, id):
if self.authenticated is True:
@ -248,7 +248,7 @@ class setup:
except HTTPError as e:
raise TwythonError("reTweet() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("reTweet() requires you to be authenticated.")
raise AuthError("reTweet() requires you to be authenticated.")
def endSession(self):
if self.authenticated is True:
@ -258,41 +258,41 @@ class setup:
except HTTPError as e:
raise TwythonError("endSession failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("You can't end a session when you're not authenticated to begin with.")
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"):
if self.authenticated is True:
apiURL = "http://twitter.com/direct_messages.json?page=" + page
apiURL = "http://twitter.com/direct_messages.json?page=%s" % repr(page)
if since_id is not None:
apiURL += "&since_id=" + since_id
apiURL += "&since_id=%s" % repr(since_id)
if max_id is not None:
apiURL += "&max_id=" + max_id
apiURL += "&max_id=%s" % repr(max_id)
if count is not None:
apiURL += "&count=" + count
apiURL += "&count=%s" % repr(count)
try:
return simplejson.load(self.opener.open(apiURL))
except HTTPError as e:
raise TwythonError("getDirectMessages() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("getDirectMessages() requires you to be authenticated.")
raise AuthError("getDirectMessages() requires you to be authenticated.")
def getSentMessages(self, since_id = None, max_id = None, count = None, page = "1"):
if self.authenticated is True:
apiURL = "http://twitter.com/direct_messages/sent.json?page=" + page
apiURL = "http://twitter.com/direct_messages/sent.json?page=%s" % repr(page)
if since_id is not None:
apiURL += "&since_id=" + since_id
apiURL += "&since_id=%s" % repr(since_id)
if max_id is not None:
apiURL += "&max_id=" + max_id
apiURL += "&max_id=%s" % repr(max_id)
if count is not None:
apiURL += "&count=" + count
apiURL += "&count=%s" % repr(count)
try:
return simplejson.load(self.opener.open(apiURL))
except HTTPError as e:
raise TwythonError("getSentMessages() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("getSentMessages() requires you to be authenticated.")
raise AuthError("getSentMessages() requires you to be authenticated.")
def sendDirectMessage(self, user, text):
if self.authenticated is True:
@ -304,7 +304,7 @@ class setup:
else:
raise TwythonError("Your message must not be longer than 140 characters")
else:
raise TwythonError("You must be authenticated to send a new direct message.")
raise AuthError("You must be authenticated to send a new direct message.")
def destroyDirectMessage(self, id):
if self.authenticated is True:
@ -313,17 +313,17 @@ class setup:
except HTTPError as e:
raise TwythonError("destroyDirectMessage() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("You must be authenticated to destroy a direct message.")
raise AuthError("You must be authenticated to destroy a direct message.")
def createFriendship(self, id = None, user_id = None, screen_name = None, follow = "false"):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/friendships/create/" + id + ".json" + "?follow=" + follow
apiURL = "http://twitter.com/friendships/create/%s.json?follow=%s" %(id, follow)
if user_id is not None:
apiURL = "http://twitter.com/friendships/create.json?user_id=" + user_id + "&follow=" + follow
apiURL = "http://twitter.com/friendships/create.json?user_id=%s&follow=%s" %(repr(user_id), follow)
if screen_name is not None:
apiURL = "http://twitter.com/friendships/create.json?screen_name=" + screen_name + "&follow=" + follow
apiURL = "http://twitter.com/friendships/create.json?screen_name=%s&follow=%s" %(screen_name, follow)
try:
return simplejson.load(self.opener.open(apiURL))
except HTTPError as e:
@ -332,23 +332,23 @@ class setup:
raise TwythonError("You've hit the update limit for this method. Try again in 24 hours.")
raise TwythonError("createFriendship() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("createFriendship() requires you to be authenticated.")
raise AuthError("createFriendship() requires you to be authenticated.")
def destroyFriendship(self, id = None, user_id = None, screen_name = None):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/friendships/destroy/" + id + ".json"
apiURL = "http://twitter.com/friendships/destroy/%s.json" % id
if user_id is not None:
apiURL = "http://twitter.com/friendships/destroy.json?user_id=" + user_id
apiURL = "http://twitter.com/friendships/destroy.json?user_id=%s" % repr(user_id)
if screen_name is not None:
apiURL = "http://twitter.com/friendships/destroy.json?screen_name=" + screen_name
apiURL = "http://twitter.com/friendships/destroy.json?screen_name=%s" % screen_name
try:
return simplejson.load(self.opener.open(apiURL))
except HTTPError as e:
raise TwythonError("destroyFriendship() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("destroyFriendship() requires you to be authenticated.")
raise AuthError("destroyFriendship() requires you to be authenticated.")
def checkIfFriendshipExists(self, user_a, user_b):
if self.authenticated is True:
@ -357,16 +357,16 @@ class setup:
except HTTPError as e:
raise TwythonError("checkIfFriendshipExists() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("checkIfFriendshipExists(), oddly, requires that you be authenticated.")
raise AuthError("checkIfFriendshipExists(), oddly, requires that you be authenticated.")
def updateDeliveryDevice(self, device_name = "none"):
if self.authenticated is True:
try:
return self.opener.open("http://twitter.com/account/update_delivery_device.json?", urllib.parse.urlencode({"device": device_name}))
return self.opener.open("http://twitter.com/account/update_delivery_device.json?", urllib.parse.urlencode({"device": self.unicode2utf8(device_name)}))
except HTTPError as e:
raise TwythonError("updateDeliveryDevice() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("updateDeliveryDevice() requires you to be authenticated.")
raise AuthError("updateDeliveryDevice() requires you to be authenticated.")
def updateProfileColors(self, **kwargs):
if self.authenticated is True:
@ -375,7 +375,7 @@ class setup:
except HTTPError as e:
raise TwythonError("updateProfileColors() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("updateProfileColors() requires you to be authenticated.")
raise AuthError("updateProfileColors() requires you to be authenticated.")
def updateProfile(self, name = None, email = None, url = None, location = None, description = None):
if self.authenticated is True:
@ -399,27 +399,27 @@ class setup:
if url is not None:
if len(list(url)) < 100:
if useAmpersands is True:
updateProfileQueryString += "&" + urllib.parse.urlencode({"url": url})
updateProfileQueryString += "&" + urllib.parse.urlencode({"url": self.unicode2utf8(url)})
else:
updateProfileQueryString += urllib.parse.urlencode({"url": url})
updateProfileQueryString += urllib.parse.urlencode({"url": self.unicode2utf8(url)})
useAmpersands = True
else:
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.parse.urlencode({"location": location})
updateProfileQueryString += "&" + urllib.parse.urlencode({"location": self.unicode2utf8(location)})
else:
updateProfileQueryString += urllib.parse.urlencode({"location": location})
updateProfileQueryString += urllib.parse.urlencode({"location": self.unicode2utf8(location)})
useAmpersands = True
else:
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.parse.urlencode({"description": description})
updateProfileQueryString += "&" + urllib.parse.urlencode({"description": self.unicode2utf8(description)})
else:
updateProfileQueryString += urllib.parse.urlencode({"description": description})
updateProfileQueryString += urllib.parse.urlencode({"description": self.unicode2utf8(description)})
else:
raise TwythonError("Twitter has a character limit of 160 for all descriptions. Try again.")
@ -429,75 +429,75 @@ class setup:
except HTTPError as e:
raise TwythonError("updateProfile() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("updateProfile() requires you to be authenticated.")
raise AuthError("updateProfile() requires you to be authenticated.")
def getFavorites(self, page = "1"):
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://twitter.com/favorites.json?page=%s" % repr(page)))
except HTTPError as e:
raise TwythonError("getFavorites() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("getFavorites() requires you to be authenticated.")
raise AuthError("getFavorites() requires you to be authenticated.")
def createFavorite(self, id):
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://twitter.com/favorites/create/%s.json" % repr(id), ""))
except HTTPError as e:
raise TwythonError("createFavorite() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("createFavorite() requires you to be authenticated.")
raise AuthError("createFavorite() requires you to be authenticated.")
def destroyFavorite(self, id):
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://twitter.com/favorites/destroy/%s.json" % repr(id), ""))
except HTTPError as e:
raise TwythonError("destroyFavorite() failed with a %s error code." % repr(e.code), e.code)
raise TwythonError("destroyFavorite() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("destroyFavorite() requires you to be authenticated.")
raise AuthError("destroyFavorite() requires you to be authenticated.")
def notificationFollow(self, id = None, user_id = None, screen_name = None):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/notifications/follow/" + id + ".json"
apiURL = "http://twitter.com/notifications/follow/%s.json" % id
if user_id is not None:
apiURL = "http://twitter.com/notifications/follow/follow.json?user_id=" + user_id
apiURL = "http://twitter.com/notifications/follow/follow.json?user_id=%s" % repr(user_id)
if screen_name is not None:
apiURL = "http://twitter.com/notifications/follow/follow.json?screen_name=" + screen_name
apiURL = "http://twitter.com/notifications/follow/follow.json?screen_name=%s" % screen_name
try:
return simplejson.load(self.opener.open(apiURL, ""))
except HTTPError as e:
raise TwythonError("notificationFollow() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("notificationFollow() requires you to be authenticated.")
raise AuthError("notificationFollow() requires you to be authenticated.")
def notificationLeave(self, id = None, user_id = None, screen_name = None):
if self.authenticated is True:
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/notifications/leave/" + id + ".json"
apiURL = "http://twitter.com/notifications/leave/%s.json" % id
if user_id is not None:
apiURL = "http://twitter.com/notifications/leave/leave.json?user_id=" + user_id
apiURL = "http://twitter.com/notifications/leave/leave.json?user_id=%s" % repr(user_id)
if screen_name is not None:
apiURL = "http://twitter.com/notifications/leave/leave.json?screen_name=" + screen_name
apiURL = "http://twitter.com/notifications/leave/leave.json?screen_name=%s" % screen_name
try:
return simplejson.load(self.opener.open(apiURL, ""))
except HTTPError as e:
raise TwythonError("notificationLeave() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("notificationLeave() requires you to be authenticated.")
raise AuthError("notificationLeave() requires you to be authenticated.")
def getFriendsIDs(self, id = None, user_id = None, screen_name = None, page = "1"):
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/friends/ids/" + id + ".json" + "?page=" + page
apiURL = "http://twitter.com/friends/ids/%s.json?page=%s" %(id, repr(page))
if user_id is not None:
apiURL = "http://twitter.com/friends/ids.json?user_id=" + user_id + "&page=" + page
apiURL = "http://twitter.com/friends/ids.json?user_id=%s&page=%s" %(repr(user_id), repr(page))
if screen_name is not None:
apiURL = "http://twitter.com/friends/ids.json?screen_name=" + screen_name + "&page=" + page
apiURL = "http://twitter.com/friends/ids.json?screen_name=%s&page=%s" %(screen_name, repr(page))
try:
return simplejson.load(urllib.request.urlopen(apiURL))
except HTTPError as e:
@ -506,11 +506,11 @@ class setup:
def getFollowersIDs(self, id = None, user_id = None, screen_name = None, page = "1"):
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/followers/ids/" + id + ".json" + "?page=" + page
apiURL = "http://twitter.com/followers/ids/%s.json?page=%s" %(repr(id), repr(page))
if user_id is not None:
apiURL = "http://twitter.com/followers/ids.json?user_id=" + user_id + "&page=" + page
apiURL = "http://twitter.com/followers/ids.json?user_id=%s&page=%s" %(repr(user_id), repr(page))
if screen_name is not None:
apiURL = "http://twitter.com/followers/ids.json?screen_name=" + screen_name + "&page=" + page
apiURL = "http://twitter.com/followers/ids.json?screen_name=%s&page=%s" %(screen_name, repr(page))
try:
return simplejson.load(urllib.request.urlopen(apiURL))
except HTTPError as e:
@ -519,29 +519,29 @@ class setup:
def createBlock(self, id):
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://twitter.com/blocks/create/%s.json" % repr(id), ""))
except HTTPError as e:
raise TwythonError("createBlock() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("createBlock() requires you to be authenticated.")
raise AuthError("createBlock() requires you to be authenticated.")
def destroyBlock(self, id):
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://twitter.com/blocks/destroy/%s.json" % repr(id), ""))
except HTTPError as e:
raise TwythonError("destroyBlock() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("destroyBlock() requires you to be authenticated.")
raise AuthError("destroyBlock() requires you to be authenticated.")
def checkIfBlockExists(self, id = None, user_id = None, screen_name = None):
apiURL = ""
if id is not None:
apiURL = "http://twitter.com/blocks/exists/" + id + ".json"
apiURL = "http://twitter.com/blocks/exists/%s.json" % repr(id)
if user_id is not None:
apiURL = "http://twitter.com/blocks/exists.json?user_id=" + user_id
apiURL = "http://twitter.com/blocks/exists.json?user_id=%s" % repr(user_id)
if screen_name is not None:
apiURL = "http://twitter.com/blocks/exists.json?screen_name=" + screen_name
apiURL = "http://twitter.com/blocks/exists.json?screen_name=%s" % screen_name
try:
return simplejson.load(urllib.request.urlopen(apiURL))
except HTTPError as e:
@ -550,11 +550,11 @@ class setup:
def getBlocking(self, page = "1"):
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://twitter.com/blocks/blocking.json?page=%s" % repr(page)))
except HTTPError as e:
raise TwythonError("getBlocking() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("getBlocking() requires you to be authenticated")
raise AuthError("getBlocking() requires you to be authenticated")
def getBlockedIDs(self):
if self.authenticated is True:
@ -563,10 +563,10 @@ class setup:
except HTTPError as e:
raise TwythonError("getBlockedIDs() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("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.parse.urlencode({"q": search_query})
searchURL = self.constructApiURL("http://search.twitter.com/search.json", kwargs) + "&" + urllib.parse.urlencode({"q": self.unicode2utf8(search_query)})
try:
return simplejson.load(urllib.request.urlopen(searchURL))
except HTTPError as e:
@ -585,7 +585,7 @@ class setup:
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:
@ -601,7 +601,7 @@ class setup:
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:
@ -620,34 +620,34 @@ class setup:
except HTTPError as e:
raise TwythonError("getSavedSearches() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("getSavedSearches() requires you to be authenticated.")
raise AuthError("getSavedSearches() requires you to be authenticated.")
def showSavedSearch(self, id):
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://twitter.com/saved_searches/show/%s.json" % repr(id)))
except HTTPError as e:
raise TwythonError("showSavedSearch() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("showSavedSearch() requires you to be authenticated.")
raise AuthError("showSavedSearch() requires you to be authenticated.")
def createSavedSearch(self, query):
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://twitter.com/saved_searches/create.json?query=%s" % query, ""))
except HTTPError as e:
raise TwythonError("createSavedSearch() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("createSavedSearch() requires you to be authenticated.")
raise AuthError("createSavedSearch() requires you to be authenticated.")
def destroySavedSearch(self, id):
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://twitter.com/saved_searches/destroy/%s.json" % repr(id), ""))
except HTTPError as e:
raise TwythonError("destroySavedSearch() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("destroySavedSearch() requires you to be authenticated.")
raise AuthError("destroySavedSearch() requires you to be authenticated.")
# 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"):
@ -662,7 +662,7 @@ class setup:
except HTTPError as e:
raise TwythonError("updateProfileBackgroundImage() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("You realize you need to be authenticated to change a background image, right?")
raise AuthError("You realize you need to be authenticated to change a background image, right?")
def updateProfileImage(self, filename):
if self.authenticated is True:
@ -676,7 +676,7 @@ class setup:
except HTTPError as e:
raise TwythonError("updateProfileImage() failed with a %s error code." % repr(e.code), e.code)
else:
raise TwythonError("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()
@ -701,3 +701,11 @@ class setup:
def get_content_type(self, filename):
return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
def unicode2utf8(self, text):
try:
if isinstance(text, str):
text = text.encode('utf-8')
except:
pass
return text