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