]> jfr.im git - z_archive/twitter.git/blob - twitter/api.py
fix the encoded_kwargs bug
[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 from twitter.twitter_globals import POST_ACTIONS
10
11 def _py26OrGreater():
12 import sys
13 return sys.hexversion > 0x20600f0
14
15 if _py26OrGreater():
16 import json
17 else:
18 import simplejson as json
19
20 class TwitterError(Exception):
21 """
22 Exception thrown by the Twitter object when there is an
23 error interacting with twitter.com.
24 """
25 pass
26
27 class TwitterCall(object):
28 def __init__(
29 self, username, password, format, domain, uri="", agent=None,
30 encoded_args=None, secure=True):
31 self.username = username
32 self.password = password
33 self.format = format
34 self.domain = domain
35 self.uri = uri
36 self.agent = agent
37 self.encoded_args = encoded_args
38 self.secure = secure
39
40 def __getattr__(self, k):
41 try:
42 return object.__getattr__(self, k)
43 except AttributeError:
44 return TwitterCall(
45 self.username, self.password, self.format, self.domain,
46 self.uri + "/" + k, self.agent, self.encoded_args)
47
48 def __call__(self, **kwargs):
49 uri = self.uri
50 method = "GET"
51 for action in POST_ACTIONS:
52 if self.uri.endswith(action):
53 method = "POST"
54 if (self.agent):
55 kwargs["source"] = self.agent
56 break
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
64 argStr = ""
65 argData = None
66 if (method == "GET"):
67 if self.encoded_args:
68 argStr = "?%s" %(self.encoded_args)
69 else:
70 argData = self.encoded_args
71
72 headers = {}
73 if (self.agent):
74 headers["X-Twitter-Client"] = self.agent
75 if (self.username):
76 headers["Authorization"] = "Basic " + b64encode("%s:%s" %(
77 self.username, self.password))
78
79 secure_str = ''
80 if self.secure:
81 secure_str = 's'
82
83 req = urllib2.Request(
84 "http%s://%s/%s.%s%s" %(
85 secure_str, self.domain, uri, self.format, argStr),
86 argData, headers)
87
88 try:
89 handle = urllib2.urlopen(req)
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):
96 return []
97 else:
98 raise TwitterError(
99 "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
100 e.code, uri, self.format, self.encoded_args, e.fp.read()))
101
102 class Twitter(TwitterCall):
103 """
104 The minimalist yet fully featured Twitter API class.
105
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:
110
111 http://apiwiki.twitter.com/
112 http://groups.google.com/group/twitter-development-talk/web/api-documentation
113
114 Examples::
115
116 twitter = Twitter("hello@foo.com", "password123")
117
118 # Get the public timeline
119 twitter.statuses.public_timeline()
120
121 # Get a particular friend's timeline
122 twitter.statuses.friends_timeline(id="billybob")
123
124 # Also supported (but totally weird)
125 twitter.statuses.friends_timeline.billybob()
126
127 # Send a direct message
128 twitter.direct_messages.new(
129 user="billybob",
130 text="I think yer swell!")
131
132 Searching Twitter::
133
134 twitter_search = Twitter(domain="search.twitter.com")
135
136 # Find the latest search trends
137 twitter_search.trends()
138
139 # Search for the latest News on #gaza
140 twitter_search.search(q="#gaza")
141
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']
154
155 Getting raw XML data::
156
157 If you prefer to get your Twitter data in XML format, pass
158 format="xml" to the Twitter object when you instantiate it:
159
160 twitter = Twitter(format="xml")
161
162 The output will not be parsed in any way. It will be a raw string
163 of XML.
164 """
165 def __init__(
166 self, email=None, password=None, format="json", domain="twitter.com",
167 agent=None, secure=True):
168 """
169 Create a new twitter API connector using the specified
170 credentials (email and password). Format specifies the output
171 format ("json" (default) or "xml").
172 """
173 if (format not in ("json", "xml")):
174 raise TwitterError("Unknown data format '%s'" %(format))
175 TwitterCall.__init__(
176 self, email, password, format, domain, "", agent,
177 secure=secure)
178
179 __all__ = ["Twitter", "TwitterError"]