]> jfr.im git - z_archive/twitter.git/blame - twitter/api.py
Bump ircbot version
[z_archive/twitter.git] / twitter / api.py
CommitLineData
7364ea65 1
2from base64 import b64encode
5251ea48 3from urllib import urlencode
7364ea65 4
5import httplib
7364ea65 6
5251ea48 7from exceptions import Exception
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
2dab41b1
MV
25# These actions require POST http requests instead of GET
26_POST_ACTIONS = [
27 "create", "update", "destroy", "new", "follow", "leave",
28 ]
29
7364ea65 30class TwitterCall(object):
c8d451e8 31 def __init__(
45688301 32 self, username, password, format, domain, uri="", agent=None):
7364ea65 33 self.username = username
34 self.password = password
a55e6a11 35 self.format = format
153dee29 36 self.domain = domain
7364ea65 37 self.uri = uri
4a6070c8 38 self.agent = agent
7364ea65 39 def __getattr__(self, k):
40 try:
41 return object.__getattr__(self, k)
42 except AttributeError:
43 return TwitterCall(
153dee29 44 self.username, self.password, self.format, self.domain,
45688301 45 self.uri + "/" + k, self.agent)
7364ea65 46 def __call__(self, **kwargs):
da45d039 47 uri = self.uri
7364ea65 48 method = "GET"
2dab41b1
MV
49 for action in _POST_ACTIONS:
50 if self.uri.endswith(action):
51 method = "POST"
52 break
22b472f8
HN
53 if (self.agent):
54 kwargs["source"] = self.agent
da45d039
MV
55
56 id = kwargs.pop('id', None)
57 if id:
58 uri += "/%s" %(id)
2dab41b1 59
5b8b1ead 60 encoded_kwargs = urlencode(kwargs.items())
7364ea65 61 argStr = ""
5b8b1ead 62 if kwargs and (method == "GET"):
63 argStr = "?" + encoded_kwargs
64
65 headers = {}
4a6070c8
HN
66 if (self.agent):
67 headers["X-Twitter-Client"] = self.agent
5b8b1ead 68 if (self.username):
69 headers["Authorization"] = "Basic " + b64encode("%s:%s" %(
70 self.username, self.password))
71 if method == "POST":
72 headers["Content-type"] = "application/x-www-form-urlencoded"
73 headers["Content-length"] = len(encoded_kwargs)
74
153dee29 75 c = httplib.HTTPConnection(self.domain)
7364ea65 76 try:
5b8b1ead 77 c.putrequest(method, "%s.%s%s" %(
da45d039 78 uri, self.format, argStr))
5b8b1ead 79 for item in headers.iteritems():
80 c.putheader(*item)
7364ea65 81 c.endheaders()
5b8b1ead 82 if method == "POST":
83 c.send(encoded_kwargs)
7364ea65 84 r = c.getresponse()
5b8b1ead 85
7364ea65 86 if (r.status == 304):
87 return []
88 elif (r.status != 200):
1c11e6d7 89 raise TwitterError(
da45d039
MV
90 "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
91 r.status, uri, self.format, encoded_kwargs, r.read()))
5b8b1ead 92 if "json" == self.format:
f1a8ed67 93 return json.loads(r.read())
a55e6a11 94 else:
95 return r.read()
7364ea65 96 finally:
97 c.close()
98
99class Twitter(TwitterCall):
100 """
101 The minimalist yet fully featured Twitter API class.
102
103 Get RESTful data by accessing members of this class. The result
104 is decoded python objects (lists and dicts).
105
106 The Twitter API is documented here:
153dee29 107
0b486eda
HN
108 http://apiwiki.twitter.com/
109 http://groups.google.com/group/twitter-development-talk/web/api-documentation
7364ea65 110
111 Examples::
112
113 twitter = Twitter("hello@foo.com", "password123")
114
115 # Get the public timeline
116 twitter.statuses.public_timeline()
117
118 # Get a particular friend's timeline
119 twitter.statuses.friends_timeline(id="billybob")
120
121 # Also supported (but totally weird)
122 twitter.statuses.friends_timeline.billybob()
123
124 # Send a direct message
125 twitter.direct_messages.new(
126 user="billybob",
127 text="I think yer swell!")
128
153dee29
HN
129 Searching Twitter::
130
0b486eda 131 twitter_search = Twitter(domain="search.twitter.com")
153dee29 132
0b486eda
HN
133 # Find the latest search trends
134 twitter_search.trends()
153dee29 135
0b486eda
HN
136 # Search for the latest News on #gaza
137 twitter_search.search(q="#gaza")
153dee29 138
7364ea65 139 Using the data returned::
140
141 Twitter API calls return decoded JSON. This is converted into
142 a bunch of Python lists, dicts, ints, and strings. For example,
143
144 x = twitter.statuses.public_timeline()
145
146 # The first 'tweet' in the timeline
147 x[0]
148
149 # The screen name of the user who wrote the first 'tweet'
150 x[0]['user']['screen_name']
a55e6a11 151
152 Getting raw XML data::
153
154 If you prefer to get your Twitter data in XML format, pass
155 format="xml" to the Twitter object when you instantiate it:
156
157 twitter = Twitter(format="xml")
7364ea65 158
a55e6a11 159 The output will not be parsed in any way. It will be a raw string
160 of XML.
7364ea65 161 """
45688301
MV
162 def __init__(
163 self, email=None, password=None, format="json", domain="twitter.com",
164 agent=None):
7364ea65 165 """
166 Create a new twitter API connector using the specified
a55e6a11 167 credentials (email and password). Format specifies the output
168 format ("json" (default) or "xml").
7364ea65 169 """
a55e6a11 170 if (format not in ("json", "xml")):
171 raise TwitterError("Unknown data format '%s'" %(format))
153dee29 172 TwitterCall.__init__(self, email, password, format, domain)
7364ea65 173
5b8b1ead 174__all__ = ["Twitter", "TwitterError"]