from base64 import b64encode
from urllib import urlencode
import urllib2
from exceptions import Exception
from twitter.twitter_globals import POST_ACTIONS
def _py26OrGreater():
import sys
return sys.hexversion > 0x20600f0
if _py26OrGreater():
import json
else:
import simplejson as json
class TwitterError(Exception):
"""
Exception thrown by the Twitter object when there is an
error interacting with twitter.com.
"""
pass
class TwitterCall(object):
def __init__(
self, username, password, format, domain, uri="", agent=None):
self.username = username
self.password = password
self.format = format
self.domain = domain
self.uri = uri
self.agent = agent
def __getattr__(self, k):
try:
return object.__getattr__(self, k)
except AttributeError:
return TwitterCall(
self.username, self.password, self.format, self.domain,
self.uri + "/" + k, self.agent)
def __call__(self, **kwargs):
uri = self.uri
method = "GET"
for action in POST_ACTIONS:
if self.uri.endswith(action):
method = "POST"
if (self.agent):
kwargs["source"] = self.agent
break
id = kwargs.pop('id', None)
if id:
uri += "/%s" %(id)
argStr = ""
argData = None
encoded_kwargs = urlencode(kwargs.items())
if (method == "GET"):
if kwargs:
argStr = "?%s" %(encoded_kwargs)
else:
argData = encoded_kwargs
headers = {}
if (self.agent):
headers["X-Twitter-Client"] = self.agent
if (self.username):
headers["Authorization"] = "Basic " + b64encode("%s:%s" %(
self.username, self.password))
req = urllib2.Request(
"http://%s/%s.%s%s" %(self.domain, uri, self.format, argStr),
argData, headers
)
try:
handle = urllib2.urlopen(req)
if "json" == self.format:
return json.loads(handle.read())
else:
return handle.read()
except urllib2.HTTPError, e:
if (e.code == 304):
return []
else:
raise TwitterError(
"Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
e.code, uri, self.format, encoded_kwargs, e.fp.read()))
class Twitter(TwitterCall):
"""
The minimalist yet fully featured Twitter API class.
Get RESTful data by accessing members of this class. The result
is decoded python objects (lists and dicts).
The Twitter API is documented here:
http://apiwiki.twitter.com/
http://groups.google.com/group/twitter-development-talk/web/api-documentation
Examples::
twitter = Twitter("hello@foo.com", "password123")
# Get the public timeline
twitter.statuses.public_timeline()
# Get a particular friend's timeline
twitter.statuses.friends_timeline(id="billybob")
# Also supported (but totally weird)
twitter.statuses.friends_timeline.billybob()
# Send a direct message
twitter.direct_messages.new(
user="billybob",
text="I think yer swell!")
Searching Twitter::
twitter_search = Twitter(domain="search.twitter.com")
# Find the latest search trends
twitter_search.trends()
# Search for the latest News on #gaza
twitter_search.search(q="#gaza")
Using the data returned::
Twitter API calls return decoded JSON. This is converted into
a bunch of Python lists, dicts, ints, and strings. For example,
x = twitter.statuses.public_timeline()
# The first 'tweet' in the timeline
x[0]
# The screen name of the user who wrote the first 'tweet'
x[0]['user']['screen_name']
Getting raw XML data::
If you prefer to get your Twitter data in XML format, pass
format="xml" to the Twitter object when you instantiate it:
twitter = Twitter(format="xml")
The output will not be parsed in any way. It will be a raw string
of XML.
"""
def __init__(
self, email=None, password=None, format="json", domain="twitter.com",
agent=None):
"""
Create a new twitter API connector using the specified
credentials (email and password). Format specifies the output
format ("json" (default) or "xml").
"""
if (format not in ("json", "xml")):
raise TwitterError("Unknown data format '%s'" %(format))
TwitterCall.__init__(self, email, password, format, domain, "", agent)
__all__ = ["Twitter", "TwitterError"]