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