]> jfr.im git - z_archive/twitter.git/blob - twitter/api.py
typo
[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 "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
38 self.e.code, self.uri, self.format, self.encoded_args, self.e.fp.read())
39
40 class TwitterCall(object):
41 def __init__(
42 self, auth, format, domain, uri="", agent=None,
43 encoded_args=None, secure=True):
44 self.auth = auth
45 self.format = format
46 self.domain = domain
47 self.uri = uri
48 self.agent = agent
49 self.encoded_args = encoded_args
50 self.secure = secure
51
52 def __getattr__(self, k):
53 try:
54 return object.__getattr__(self, k)
55 except AttributeError:
56 return TwitterCall(
57 self.auth, self.format, self.domain,
58 self.uri + "/" + k, self.agent, self.encoded_args, self.secure)
59
60 def __call__(self, **kwargs):
61 uri = self.uri.strip("/")
62 method = "GET"
63 for action in POST_ACTIONS:
64 if self.uri.endswith(action):
65 method = "POST"
66 if (self.agent):
67 kwargs["source"] = self.agent
68 break
69
70 secure_str = ''
71 if self.secure:
72 secure_str = 's'
73 dot = ""
74 if self.format != '':
75 dot = "."
76 uriBase = "http%s://%s/%s%s%s" %(
77 secure_str, self.domain, uri, dot, self.format)
78
79 if (not self.encoded_args):
80 if kwargs.has_key('id'):
81 uri += "/%s" %(kwargs['id'])
82
83 self.encoded_args = self.auth.encode_params(uriBase, method, kwargs)
84
85 argStr = ""
86 argData = None
87 if (method == "GET"):
88 if self.encoded_args:
89 argStr = "?%s" %(self.encoded_args)
90 else:
91 argData = self.encoded_args
92
93 headers = {}
94 if (self.agent):
95 headers["X-Twitter-Client"] = self.agent
96 if self.auth is not None:
97 headers.update(self.auth.generate_headers())
98
99 req = urllib2.Request(uriBase+argStr, argData, headers)
100
101 try:
102 handle = urllib2.urlopen(req)
103 if "json" == self.format:
104 return json.loads(handle.read())
105 else:
106 return handle.read()
107 except urllib2.HTTPError, e:
108 if (e.code == 304):
109 return []
110 else:
111 raise TwitterHTTPError(e, uri, self.format, self.encoded_args)
112
113 class Twitter(TwitterCall):
114 """
115 The minimalist yet fully featured Twitter API class.
116
117 Get RESTful data by accessing members of this class. The result
118 is decoded python objects (lists and dicts).
119
120 The Twitter API is documented here:
121
122 http://apiwiki.twitter.com/
123 http://groups.google.com/group/twitter-development-talk/web/api-documentation
124
125 Examples::
126
127 twitter = Twitter("hello@foo.com", "password123")
128
129 # Get the public timeline
130 twitter.statuses.public_timeline()
131
132 # Get a particular friend's timeline
133 twitter.statuses.friends_timeline(id="billybob")
134
135 # Also supported (but totally weird)
136 twitter.statuses.friends_timeline.billybob()
137
138 # Send a direct message
139 twitter.direct_messages.new(
140 user="billybob",
141 text="I think yer swell!")
142
143 Searching Twitter::
144
145 twitter_search = Twitter(domain="search.twitter.com")
146
147 # Find the latest search trends
148 twitter_search.trends()
149
150 # Search for the latest News on #gaza
151 twitter_search.search(q="#gaza")
152
153 Using the data returned::
154
155 Twitter API calls return decoded JSON. This is converted into
156 a bunch of Python lists, dicts, ints, and strings. For example,
157
158 x = twitter.statuses.public_timeline()
159
160 # The first 'tweet' in the timeline
161 x[0]
162
163 # The screen name of the user who wrote the first 'tweet'
164 x[0]['user']['screen_name']
165
166 Getting raw XML data::
167
168 If you prefer to get your Twitter data in XML format, pass
169 format="xml" to the Twitter object when you instantiate it:
170
171 twitter = Twitter(format="xml")
172
173 The output will not be parsed in any way. It will be a raw string
174 of XML.
175 """
176 def __init__(
177 self, email=None, password=None, format="json", domain="twitter.com",
178 agent=None, secure=True, auth=None):
179 """
180 Create a new twitter API connector using the specified
181 credentials (email and password). Format specifies the output
182 format ("json" (default) or "xml").
183 """
184
185 if email is not None or password is not None:
186 if auth is not None:
187 raise ValueError, "can't specify 'email' or 'password' and 'auth' params"
188 auth = UserPassAuth(email, password)
189
190 if not auth:
191 auth = NoAuth()
192
193 if (format not in ("json", "xml", "")):
194 raise TwitterError("Unknown data format '%s'" %(format))
195 TwitterCall.__init__(
196 self, auth, format, domain, "", agent,
197 secure=secure)
198
199 __all__ = ["Twitter", "TwitterError", "TwitterHTTPError"]