]> jfr.im git - z_archive/twitter.git/blame - twitter/api.py
Dont require simplejson if python is 2.6 or better
[z_archive/twitter.git] / twitter / api.py
CommitLineData
7364ea65 1
de072195 2import urllib2
7364ea65 3
5251ea48 4from exceptions import Exception
5
612ececa 6from twitter.twitter_globals import POST_ACTIONS
d20da7f3 7from twitter.auth import UserPassAuth, NoAuth
4e9d6343 8
f1a8ed67 9def _py26OrGreater():
10 import sys
11 return sys.hexversion > 0x20600f0
12
13if _py26OrGreater():
14 import json
15else:
16 import simplejson as json
17
5251ea48 18class TwitterError(Exception):
21e3bd23 19 """
20 Exception thrown by the Twitter object when there is an
21 error interacting with twitter.com.
22 """
5251ea48 23 pass
24
7364ea65 25class TwitterCall(object):
c8d451e8 26 def __init__(
568331a9 27 self, auth, format, domain, uri="", agent=None,
9a148ed1 28 encoded_args=None, secure=True):
568331a9 29 self.auth = auth
a55e6a11 30 self.format = format
153dee29 31 self.domain = domain
7364ea65 32 self.uri = uri
4a6070c8 33 self.agent = agent
fd2bc885 34 self.encoded_args = encoded_args
9a148ed1 35 self.secure = secure
fd2bc885 36
7364ea65 37 def __getattr__(self, k):
38 try:
39 return object.__getattr__(self, k)
40 except AttributeError:
41 return TwitterCall(
568331a9
MH
42 self.auth, self.format, self.domain,
43 self.uri + "/" + k, self.agent, self.encoded_args, self.secure)
fd2bc885 44
7364ea65 45 def __call__(self, **kwargs):
568331a9 46 uri = self.uri.strip("/")
7364ea65 47 method = "GET"
612ececa 48 for action in POST_ACTIONS:
2dab41b1
MV
49 if self.uri.endswith(action):
50 method = "POST"
4ad03f81
MV
51 if (self.agent):
52 kwargs["source"] = self.agent
2dab41b1 53 break
fd2bc885 54
568331a9
MH
55 secure_str = ''
56 if self.secure:
57 secure_str = 's'
58 uriBase = "http%s://%s/%s.%s" %(
59 secure_str, self.domain, uri, self.format)
60
fd2bc885
WD
61 if (not self.encoded_args):
62 if kwargs.has_key('id'):
63 uri += "/%s" %(kwargs['id'])
568331a9
MH
64
65 self.encoded_args = self.auth.encode_params(uriBase, method, kwargs)
fd2bc885 66
7364ea65 67 argStr = ""
de072195 68 argData = None
102acdb1 69 if (method == "GET"):
fd2bc885
WD
70 if self.encoded_args:
71 argStr = "?%s" %(self.encoded_args)
102acdb1 72 else:
fd2bc885 73 argData = self.encoded_args
5b8b1ead 74
75 headers = {}
4a6070c8
HN
76 if (self.agent):
77 headers["X-Twitter-Client"] = self.agent
568331a9
MH
78 if self.auth is not None:
79 headers.update(self.auth.generate_headers())
102acdb1 80
568331a9 81 req = urllib2.Request(uriBase+argStr, argData, headers)
9a148ed1 82
7364ea65 83 try:
102acdb1 84 handle = urllib2.urlopen(req)
de072195
HN
85 if "json" == self.format:
86 return json.loads(handle.read())
87 else:
88 return handle.read()
89 except urllib2.HTTPError, e:
90 if (e.code == 304):
7364ea65 91 return []
de072195 92 else:
1c11e6d7 93 raise TwitterError(
da45d039 94 "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
374057c9 95 e.code, uri, self.format, self.encoded_args, e.fp.read()))
102acdb1 96
7364ea65 97class Twitter(TwitterCall):
98 """
99 The minimalist yet fully featured Twitter API class.
4e9d6343 100
7364ea65 101 Get RESTful data by accessing members of this class. The result
102 is decoded python objects (lists and dicts).
103
104 The Twitter API is documented here:
153dee29 105
0b486eda
HN
106 http://apiwiki.twitter.com/
107 http://groups.google.com/group/twitter-development-talk/web/api-documentation
4e9d6343 108
7364ea65 109 Examples::
4e9d6343 110
7364ea65 111 twitter = Twitter("hello@foo.com", "password123")
4e9d6343 112
7364ea65 113 # Get the public timeline
114 twitter.statuses.public_timeline()
4e9d6343 115
7364ea65 116 # Get a particular friend's timeline
117 twitter.statuses.friends_timeline(id="billybob")
4e9d6343 118
7364ea65 119 # Also supported (but totally weird)
120 twitter.statuses.friends_timeline.billybob()
4e9d6343 121
7364ea65 122 # Send a direct message
123 twitter.direct_messages.new(
124 user="billybob",
125 text="I think yer swell!")
126
153dee29 127 Searching Twitter::
4e9d6343 128
0b486eda 129 twitter_search = Twitter(domain="search.twitter.com")
153dee29 130
0b486eda
HN
131 # Find the latest search trends
132 twitter_search.trends()
153dee29 133
0b486eda
HN
134 # Search for the latest News on #gaza
135 twitter_search.search(q="#gaza")
153dee29 136
7364ea65 137 Using the data returned::
138
139 Twitter API calls return decoded JSON. This is converted into
140 a bunch of Python lists, dicts, ints, and strings. For example,
141
142 x = twitter.statuses.public_timeline()
143
144 # The first 'tweet' in the timeline
145 x[0]
146
147 # The screen name of the user who wrote the first 'tweet'
148 x[0]['user']['screen_name']
4e9d6343 149
a55e6a11 150 Getting raw XML data::
4e9d6343 151
a55e6a11 152 If you prefer to get your Twitter data in XML format, pass
153 format="xml" to the Twitter object when you instantiate it:
4e9d6343 154
a55e6a11 155 twitter = Twitter(format="xml")
4e9d6343 156
a55e6a11 157 The output will not be parsed in any way. It will be a raw string
158 of XML.
7364ea65 159 """
45688301
MV
160 def __init__(
161 self, email=None, password=None, format="json", domain="twitter.com",
568331a9 162 agent=None, secure=True, auth=None):
7364ea65 163 """
164 Create a new twitter API connector using the specified
a55e6a11 165 credentials (email and password). Format specifies the output
166 format ("json" (default) or "xml").
7364ea65 167 """
568331a9
MH
168
169 if email is not None or password is not None:
170 if auth is not None:
171 raise ValueError, "can't specify 'email' or 'password' and 'auth' params"
172 auth = UserPassAuth(email, password)
173
d20da7f3
MV
174 if not auth:
175 auth = NoAuth()
176
a55e6a11 177 if (format not in ("json", "xml")):
178 raise TwitterError("Unknown data format '%s'" %(format))
9a148ed1 179 TwitterCall.__init__(
568331a9 180 self, auth, format, domain, "", agent,
7985672c 181 secure=secure)
7364ea65 182
5b8b1ead 183__all__ = ["Twitter", "TwitterError"]