]> jfr.im git - z_archive/twitter.git/blame - twitter/api.py
Cleanup argument parsing to support default format in config file
[z_archive/twitter.git] / twitter / api.py
CommitLineData
7364ea65 1
2from base64 import b64encode
5251ea48 3from urllib import urlencode
7364ea65 4
de072195 5import urllib2
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"
4ad03f81
MV
52 if (self.agent):
53 kwargs["source"] = self.agent
2dab41b1 54 break
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 = ""
de072195
HN
62 argData = None
63 encoded_kwargs = urlencode(kwargs.items())
64 if kwargs:
65 if (method == "GET"):
66 argStr = "?%s" %(encoded_kwargs)
67 else:
68 argData = encoded_kwargs
5b8b1ead 69
70 headers = {}
4a6070c8
HN
71 if (self.agent):
72 headers["X-Twitter-Client"] = self.agent
5b8b1ead 73 if (self.username):
74 headers["Authorization"] = "Basic " + b64encode("%s:%s" %(
75 self.username, self.password))
5b8b1ead 76
de072195
HN
77 req = urllib2.Request(
78 "http://%s/%s.%s%s" %(self.domain, self.uri, self.format, argStr),
79 argData, headers
80 )
7364ea65 81 try:
de072195
HN
82 handle = urllib2.urlopen(req)
83 if "json" == self.format:
84 return json.loads(handle.read())
85 else:
86 return handle.read()
87 except urllib2.HTTPError, e:
88 if (e.code == 304):
7364ea65 89 return []
de072195 90 else:
1c11e6d7 91 raise TwitterError(
da45d039 92 "Twitter sent status %i for URL: %s.%s using parameters: (%s)\ndetails: %s" %(
25de7f81 93 e.code, uri, self.format, encoded_kwargs, e.fp.read()))
de072195 94
7364ea65 95class Twitter(TwitterCall):
96 """
97 The minimalist yet fully featured Twitter API class.
98
99 Get RESTful data by accessing members of this class. The result
100 is decoded python objects (lists and dicts).
101
102 The Twitter API is documented here:
153dee29 103
0b486eda
HN
104 http://apiwiki.twitter.com/
105 http://groups.google.com/group/twitter-development-talk/web/api-documentation
7364ea65 106
107 Examples::
108
109 twitter = Twitter("hello@foo.com", "password123")
110
111 # Get the public timeline
112 twitter.statuses.public_timeline()
113
114 # Get a particular friend's timeline
115 twitter.statuses.friends_timeline(id="billybob")
116
117 # Also supported (but totally weird)
118 twitter.statuses.friends_timeline.billybob()
119
120 # Send a direct message
121 twitter.direct_messages.new(
122 user="billybob",
123 text="I think yer swell!")
124
153dee29
HN
125 Searching Twitter::
126
0b486eda 127 twitter_search = Twitter(domain="search.twitter.com")
153dee29 128
0b486eda
HN
129 # Find the latest search trends
130 twitter_search.trends()
153dee29 131
0b486eda
HN
132 # Search for the latest News on #gaza
133 twitter_search.search(q="#gaza")
153dee29 134
7364ea65 135 Using the data returned::
136
137 Twitter API calls return decoded JSON. This is converted into
138 a bunch of Python lists, dicts, ints, and strings. For example,
139
140 x = twitter.statuses.public_timeline()
141
142 # The first 'tweet' in the timeline
143 x[0]
144
145 # The screen name of the user who wrote the first 'tweet'
146 x[0]['user']['screen_name']
a55e6a11 147
148 Getting raw XML data::
149
150 If you prefer to get your Twitter data in XML format, pass
151 format="xml" to the Twitter object when you instantiate it:
152
153 twitter = Twitter(format="xml")
7364ea65 154
a55e6a11 155 The output will not be parsed in any way. It will be a raw string
156 of XML.
7364ea65 157 """
45688301
MV
158 def __init__(
159 self, email=None, password=None, format="json", domain="twitter.com",
160 agent=None):
7364ea65 161 """
162 Create a new twitter API connector using the specified
a55e6a11 163 credentials (email and password). Format specifies the output
164 format ("json" (default) or "xml").
7364ea65 165 """
a55e6a11 166 if (format not in ("json", "xml")):
167 raise TwitterError("Unknown data format '%s'" %(format))
4ad03f81 168 TwitterCall.__init__(self, email, password, format, domain, "", agent)
7364ea65 169
5b8b1ead 170__all__ = ["Twitter", "TwitterError"]