]>
Commit | Line | Data |
---|---|---|
7364ea65 | 1 | |
2 | from base64 import b64encode | |
5251ea48 | 3 | from urllib import urlencode |
7364ea65 | 4 | |
5 | import httplib | |
7364ea65 | 6 | |
5251ea48 | 7 | from exceptions import Exception |
8 | ||
9 | class TwitterError(Exception): | |
10 | pass | |
11 | ||
7364ea65 | 12 | class TwitterCall(object): |
a55e6a11 | 13 | def __init__(self, username, password, format, uri=""): |
7364ea65 | 14 | self.username = username |
15 | self.password = password | |
a55e6a11 | 16 | self.format = format |
7364ea65 | 17 | self.uri = uri |
18 | def __getattr__(self, k): | |
19 | try: | |
20 | return object.__getattr__(self, k) | |
21 | except AttributeError: | |
22 | return TwitterCall( | |
a55e6a11 | 23 | self.username, self.password, self.format, |
24 | self.uri + "/" + k) | |
7364ea65 | 25 | def __call__(self, **kwargs): |
26 | method = "GET" | |
27 | if self.uri.endswith('new') or self.uri.endswith('update'): | |
28 | method = "POST" | |
29 | argStr = "" | |
30 | if kwargs: | |
5251ea48 | 31 | argStr = "?" + urlencode(kwargs.items()) |
7364ea65 | 32 | c = httplib.HTTPConnection("twitter.com") |
33 | try: | |
a55e6a11 | 34 | c.putrequest(method, "/%s.%s%s" %( |
35 | self.uri, self.format, argStr)) | |
7364ea65 | 36 | if (self.username): |
a55e6a11 | 37 | c.putheader( |
38 | "Authorization", "Basic " + b64encode("%s:%s" %( | |
39 | self.username, self.password))) | |
40 | if (method == "POST"): | |
41 | # TODO specify charset | |
42 | pass | |
7364ea65 | 43 | c.endheaders() |
44 | r = c.getresponse() | |
45 | if (r.status == 304): | |
46 | return [] | |
47 | elif (r.status != 200): | |
5251ea48 | 48 | raise TwitterError("Twitter sent status %i: %s" %( |
7364ea65 | 49 | r.status, r.read())) |
a55e6a11 | 50 | if ("json" == self.format): |
51 | import simplejson | |
52 | return simplejson.loads(r.read()) | |
53 | else: | |
54 | return r.read() | |
7364ea65 | 55 | finally: |
56 | c.close() | |
57 | ||
58 | class Twitter(TwitterCall): | |
59 | """ | |
60 | The minimalist yet fully featured Twitter API class. | |
61 | ||
62 | Get RESTful data by accessing members of this class. The result | |
63 | is decoded python objects (lists and dicts). | |
64 | ||
65 | The Twitter API is documented here: | |
66 | http://groups.google.com/group/twitter-development-talk/web/api-documentation | |
67 | ||
68 | Examples:: | |
69 | ||
70 | twitter = Twitter("hello@foo.com", "password123") | |
71 | ||
72 | # Get the public timeline | |
73 | twitter.statuses.public_timeline() | |
74 | ||
75 | # Get a particular friend's timeline | |
76 | twitter.statuses.friends_timeline(id="billybob") | |
77 | ||
78 | # Also supported (but totally weird) | |
79 | twitter.statuses.friends_timeline.billybob() | |
80 | ||
81 | # Send a direct message | |
82 | twitter.direct_messages.new( | |
83 | user="billybob", | |
84 | text="I think yer swell!") | |
85 | ||
86 | Using the data returned:: | |
87 | ||
88 | Twitter API calls return decoded JSON. This is converted into | |
89 | a bunch of Python lists, dicts, ints, and strings. For example, | |
90 | ||
91 | x = twitter.statuses.public_timeline() | |
92 | ||
93 | # The first 'tweet' in the timeline | |
94 | x[0] | |
95 | ||
96 | # The screen name of the user who wrote the first 'tweet' | |
97 | x[0]['user']['screen_name'] | |
a55e6a11 | 98 | |
99 | Getting raw XML data:: | |
100 | ||
101 | If you prefer to get your Twitter data in XML format, pass | |
102 | format="xml" to the Twitter object when you instantiate it: | |
103 | ||
104 | twitter = Twitter(format="xml") | |
7364ea65 | 105 | |
a55e6a11 | 106 | The output will not be parsed in any way. It will be a raw string |
107 | of XML. | |
7364ea65 | 108 | """ |
a55e6a11 | 109 | def __init__(self, email=None, password=None, format="json"): |
7364ea65 | 110 | """ |
111 | Create a new twitter API connector using the specified | |
a55e6a11 | 112 | credentials (email and password). Format specifies the output |
113 | format ("json" (default) or "xml"). | |
7364ea65 | 114 | """ |
a55e6a11 | 115 | if (format not in ("json", "xml")): |
116 | raise TwitterError("Unknown data format '%s'" %(format)) | |
117 | if (format == "json"): | |
118 | try: | |
119 | import simplejson | |
120 | except ImportError: | |
121 | raise TwitterError( | |
122 | "format not available: simplejson is not installed") | |
123 | TwitterCall.__init__(self, email, password, format) | |
7364ea65 | 124 | |
125 | __all__ = ["Twitter"] |