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