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