]> jfr.im git - z_archive/twitter.git/blob - twitter/api.py
- Documentation updates.
[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("hello@foo.com", "password123")
131
132 # Get the public timeline
133 twitter.statuses.public_timeline()
134
135 # Get a particular friend's timeline
136 twitter.statuses.friends_timeline(id="billybob")
137
138 # Also supported (but totally weird)
139 twitter.statuses.friends_timeline.billybob()
140
141 # Send a direct message
142 twitter.direct_messages.new(
143 user="billybob",
144 text="I think yer swell!")
145
146 Searching Twitter::
147
148 twitter_search = Twitter(domain="search.twitter.com")
149
150 # Find the latest search trends
151 twitter_search.trends()
152
153 # Search for the latest News on #gaza
154 twitter_search.search(q="#gaza")
155
156
157 Using the data returned
158 -----------------------
159
160 Twitter API calls return decoded JSON. This is converted into
161 a bunch of Python lists, dicts, ints, and strings. For example::
162
163 x = twitter.statuses.public_timeline()
164
165 # The first 'tweet' in the timeline
166 x[0]
167
168 # The screen name of the user who wrote the first 'tweet'
169 x[0]['user']['screen_name']
170
171
172 Getting raw XML data
173 --------------------
174
175 If you prefer to get your Twitter data in XML format, pass
176 format="xml" to the Twitter object when you instantiate it::
177
178 twitter = Twitter(format="xml")
179
180 The output will not be parsed in any way. It will be a raw string
181 of XML.
182
183 """
184 def __init__(
185 self, email=None, password=None, format="json",
186 domain="api.twitter.com", agent=None, secure=True, auth=None,
187 api_version=1):
188 """
189 Create a new twitter API connector.
190
191 Pass an `auth` parameter to use the credentials of a specific
192 user. Generally you'll want to pass an `OAuth`
193 instance. Alternately you can pass `email` and `password`
194 parameters but this authentication mode will be deactive by
195 Twitter in the future and is not recommended.
196
197 `domain` lets you change the domain you are connecting. By
198 default it's twitter.com but `search.twitter.com` may be
199 useful too.
200
201 If `secure` is False you will connect with HTTP instead of
202 HTTPS.
203
204 The value of `agent` is sent in the `X-Twitter-Client`
205 header. This is deprecated. Instead Twitter determines the
206 application using the OAuth Client Key and Client Key Secret
207 parameters.
208 """
209
210 if email is not None or password is not None:
211 if auth:
212 raise (
213 "Can't specify 'email'/'password' and 'auth' params"
214 " simultaneously.")
215 auth = UserPassAuth(email, password)
216
217 if not auth:
218 auth = NoAuth()
219
220 if (format not in ("json", "xml", "")):
221 raise ValueError("Unknown data format '%s'" %(format))
222
223 uri = ""
224 if api_version:
225 uri = str(api_version)
226
227 TwitterCall.__init__(
228 self, auth, format, domain, uri, agent,
229 secure=secure)
230
231 __all__ = ["Twitter", "TwitterError", "TwitterHTTPError"]