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