]> jfr.im git - z_archive/twitter.git/blob - twitter/api.py
Change docs to show how to use OAuth
[z_archive/twitter.git] / twitter / api.py
1
2 import urllib2
3
4 from exceptions import Exception
5
6 from twitter.twitter_globals import POST_ACTIONS
7 from twitter.auth import UserPassAuth, NoAuth
8
9 def _py26OrGreater():
10 import sys
11 return sys.hexversion > 0x20600f0
12
13 if _py26OrGreater():
14 import json
15 else:
16 import simplejson as json
17
18 class TwitterError(Exception):
19 """
20 Base Exception thrown by the Twitter object when there is a
21 general error interacting with the API.
22 """
23 pass
24
25 class TwitterHTTPError(TwitterError):
26 """
27 Exception thrown by the Twitter object when there is an
28 HTTP error interacting with twitter.com.
29 """
30 def __init__(self, e, uri, format, encoded_args):
31 self.e = e
32 self.uri = uri
33 self.format = format
34 self.encoded_args = encoded_args
35
36 def __str__(self):
37 return (
38 "Twitter sent status %i for URL: %s.%s using parameters: "
39 "(%s)\ndetails: %s" %(
40 self.e.code, self.uri, self.format, self.encoded_args,
41 self.e.fp.read()))
42
43 class TwitterCall(object):
44 def __init__(
45 self, auth, format, domain, uri="", agent=None,
46 encoded_args=None, secure=True):
47 self.auth = auth
48 self.format = format
49 self.domain = domain
50 self.uri = uri
51 self.agent = agent
52 self.encoded_args = encoded_args
53 self.secure = secure
54
55 def __getattr__(self, k):
56 try:
57 return object.__getattr__(self, k)
58 except AttributeError:
59 return TwitterCall(
60 self.auth, self.format, self.domain,
61 self.uri + "/" + k, self.agent, self.encoded_args, self.secure)
62
63 def __call__(self, **kwargs):
64 uri = self.uri.strip("/")
65 method = "GET"
66 for action in POST_ACTIONS:
67 if self.uri.endswith(action):
68 method = "POST"
69 if (self.agent):
70 kwargs["source"] = self.agent
71 break
72
73 secure_str = ''
74 if self.secure:
75 secure_str = 's'
76 dot = ""
77 if self.format != '':
78 dot = "."
79 uriBase = "http%s://%s/%s%s%s" %(
80 secure_str, self.domain, uri, dot, self.format)
81
82 if (not self.encoded_args):
83 if kwargs.has_key('id'):
84 uri += "/%s" %(kwargs['id'])
85
86 self.encoded_args = self.auth.encode_params(uriBase, method, kwargs)
87
88 argStr = ""
89 argData = None
90 if (method == "GET"):
91 if self.encoded_args:
92 argStr = "?%s" %(self.encoded_args)
93 else:
94 argData = self.encoded_args
95
96 headers = {}
97 if (self.agent):
98 headers["X-Twitter-Client"] = self.agent
99 if self.auth is not None:
100 headers.update(self.auth.generate_headers())
101
102 req = urllib2.Request(uriBase+argStr, argData, headers)
103
104 try:
105 handle = urllib2.urlopen(req)
106 if "json" == self.format:
107 return json.loads(handle.read())
108 else:
109 return handle.read()
110 except urllib2.HTTPError, e:
111 if (e.code == 304):
112 return []
113 else:
114 raise TwitterHTTPError(e, uri, self.format, self.encoded_args)
115
116 class Twitter(TwitterCall):
117 """
118 The minimalist yet fully featured Twitter API class.
119
120 Get RESTful data by accessing members of this class. The result
121 is decoded python objects (lists and dicts).
122
123 The Twitter API is documented here:
124
125 http://apiwiki.twitter.com/
126 http://groups.google.com/group/twitter-development-talk/web/api-documentation
127
128 Examples::
129
130 twitter = Twitter(
131 auth=OAuth(token, token_key, con_secret, con_secret_key)))
132
133 # Get the public timeline
134 twitter.statuses.public_timeline()
135
136 # Get a particular friend's timeline
137 twitter.statuses.friends_timeline(id="billybob")
138
139 # Also supported (but totally weird)
140 twitter.statuses.friends_timeline.billybob()
141
142 # Send a direct message
143 twitter.direct_messages.new(
144 user="billybob",
145 text="I think yer swell!")
146
147
148 Searching Twitter::
149
150 twitter_search = Twitter(domain="search.twitter.com")
151
152 # Find the latest search trends
153 twitter_search.trends()
154
155 # Search for the latest News on #gaza
156 twitter_search.search(q="#gaza")
157
158
159 Using the data returned
160 -----------------------
161
162 Twitter API calls return decoded JSON. This is converted into
163 a bunch of Python lists, dicts, ints, and strings. For example::
164
165 x = twitter.statuses.public_timeline()
166
167 # The first 'tweet' in the timeline
168 x[0]
169
170 # The screen name of the user who wrote the first 'tweet'
171 x[0]['user']['screen_name']
172
173
174 Getting raw XML data
175 --------------------
176
177 If you prefer to get your Twitter data in XML format, pass
178 format="xml" to the Twitter object when you instantiate it::
179
180 twitter = Twitter(format="xml")
181
182 The output will not be parsed in any way. It will be a raw string
183 of XML.
184
185 """
186 def __init__(
187 self, email=None, password=None, format="json",
188 domain="api.twitter.com", agent=None, secure=True, auth=None,
189 api_version=''):
190 """
191 Create a new twitter API connector.
192
193 Pass an `auth` parameter to use the credentials of a specific
194 user. Generally you'll want to pass an `OAuth`
195 instance::
196
197 twitter = Twitter(auth=OAuth(
198 token, token_secret, consumer_key, consumer_secret))
199
200
201 Alternately you can pass `email` and `password` parameters but
202 this authentication mode will be deactive by Twitter very soon
203 and is not recommended::
204
205 twitter = Twitter(email="blah@blah.com", password="foobar")
206
207
208 `domain` lets you change the domain you are connecting. By
209 default it's twitter.com but `search.twitter.com` may be
210 useful too.
211
212 If `secure` is False you will connect with HTTP instead of
213 HTTPS.
214
215 The value of `agent` is sent in the `X-Twitter-Client`
216 header. This is deprecated. Instead Twitter determines the
217 application using the OAuth Client Key and Client Key Secret
218 parameters.
219
220 `api_version` is used to set the base uri. By default it's
221 nothing, but if you set it to '1' your URI will start with
222 '1/'.
223 """
224
225 if email is not None or password is not None:
226 if auth:
227 raise ValueError(
228 "Can't specify 'email'/'password' and 'auth' params"
229 " simultaneously.")
230 auth = UserPassAuth(email, password)
231
232 if not auth:
233 auth = NoAuth()
234
235 if (format not in ("json", "xml", "")):
236 raise ValueError("Unknown data format '%s'" %(format))
237
238 uri = ""
239 if api_version:
240 uri = str(api_version)
241
242 TwitterCall.__init__(
243 self, auth, format, domain, uri, agent,
244 secure=secure)
245
246 __all__ = ["Twitter", "TwitterError", "TwitterHTTPError"]