]> jfr.im git - z_archive/twitter.git/blame - twitter/api.py
Add authorize action to command line tool to use do the oauth dance.
[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'
6c527e72
MV
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)
568331a9 63
fd2bc885
WD
64 if (not self.encoded_args):
65 if kwargs.has_key('id'):
66 uri += "/%s" %(kwargs['id'])
568331a9
MH
67
68 self.encoded_args = self.auth.encode_params(uriBase, method, kwargs)
fd2bc885 69
7364ea65 70 argStr = ""
de072195 71 argData = None
102acdb1 72 if (method == "GET"):
fd2bc885
WD
73 if self.encoded_args:
74 argStr = "?%s" %(self.encoded_args)
102acdb1 75 else:
fd2bc885 76 argData = self.encoded_args
5b8b1ead 77
78 headers = {}
4a6070c8
HN
79 if (self.agent):
80 headers["X-Twitter-Client"] = self.agent
568331a9
MH
81 if self.auth is not None:
82 headers.update(self.auth.generate_headers())
102acdb1 83
568331a9 84 req = urllib2.Request(uriBase+argStr, argData, headers)
9a148ed1 85
7364ea65 86 try:
102acdb1 87 handle = urllib2.urlopen(req)
de072195
HN
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):
7364ea65 94 return []
de072195 95 else:
1c11e6d7 96 raise TwitterError(
da45d039 97 "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
374057c9 98 e.code, uri, self.format, self.encoded_args, e.fp.read()))
102acdb1 99
7364ea65 100class Twitter(TwitterCall):
101 """
102 The minimalist yet fully featured Twitter API class.
4e9d6343 103
7364ea65 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:
153dee29 108
0b486eda
HN
109 http://apiwiki.twitter.com/
110 http://groups.google.com/group/twitter-development-talk/web/api-documentation
4e9d6343 111
7364ea65 112 Examples::
4e9d6343 113
7364ea65 114 twitter = Twitter("hello@foo.com", "password123")
4e9d6343 115
7364ea65 116 # Get the public timeline
117 twitter.statuses.public_timeline()
4e9d6343 118
7364ea65 119 # Get a particular friend's timeline
120 twitter.statuses.friends_timeline(id="billybob")
4e9d6343 121
7364ea65 122 # Also supported (but totally weird)
123 twitter.statuses.friends_timeline.billybob()
4e9d6343 124
7364ea65 125 # Send a direct message
126 twitter.direct_messages.new(
127 user="billybob",
128 text="I think yer swell!")
129
153dee29 130 Searching Twitter::
4e9d6343 131
0b486eda 132 twitter_search = Twitter(domain="search.twitter.com")
153dee29 133
0b486eda
HN
134 # Find the latest search trends
135 twitter_search.trends()
153dee29 136
0b486eda
HN
137 # Search for the latest News on #gaza
138 twitter_search.search(q="#gaza")
153dee29 139
7364ea65 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']
4e9d6343 152
a55e6a11 153 Getting raw XML data::
4e9d6343 154
a55e6a11 155 If you prefer to get your Twitter data in XML format, pass
156 format="xml" to the Twitter object when you instantiate it:
4e9d6343 157
a55e6a11 158 twitter = Twitter(format="xml")
4e9d6343 159
a55e6a11 160 The output will not be parsed in any way. It will be a raw string
161 of XML.
7364ea65 162 """
45688301
MV
163 def __init__(
164 self, email=None, password=None, format="json", domain="twitter.com",
568331a9 165 agent=None, secure=True, auth=None):
7364ea65 166 """
167 Create a new twitter API connector using the specified
a55e6a11 168 credentials (email and password). Format specifies the output
169 format ("json" (default) or "xml").
7364ea65 170 """
568331a9
MH
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
d20da7f3
MV
177 if not auth:
178 auth = NoAuth()
179
6c527e72 180 if (format not in ("json", "xml", "")):
a55e6a11 181 raise TwitterError("Unknown data format '%s'" %(format))
9a148ed1 182 TwitterCall.__init__(
568331a9 183 self, auth, format, domain, "", agent,
7985672c 184 secure=secure)
7364ea65 185
5b8b1ead 186__all__ = ["Twitter", "TwitterError"]