api.py 22.4 KB
Newer Older
1
# Tweepy
2
3
# Copyright 2009-2010 Joshua Roesslein
# See LICENSE for details.
4

5
6
7
import os
import mimetypes

Josh Roesslein's avatar
Josh Roesslein committed
8
9
from tweepy.binder import bind_api
from tweepy.error import TweepError
10
from tweepy.parsers import ModelParser, RawParser
11
from tweepy.utils import list_to_csv
12

Josh Roesslein's avatar
Josh Roesslein committed
13

14
class API(object):
Josh Roesslein's avatar
Josh Roesslein committed
15
16
    """Twitter API"""

17
18
19
    def __init__(self, auth_handler=None,
            host='api.twitter.com', search_host='search.twitter.com',
             cache=None, secure=False, api_root='/1', search_root='',
20
            retry_count=0, retry_delay=0, retry_errors=None,
21
            parser=None):
Josh Roesslein's avatar
Josh Roesslein committed
22
        self.auth = auth_handler
Josh Roesslein's avatar
Josh Roesslein committed
23
        self.host = host
24
        self.search_host = search_host
Josh Roesslein's avatar
Josh Roesslein committed
25
        self.api_root = api_root
26
        self.search_root = search_root
Josh Roesslein's avatar
Josh Roesslein committed
27
28
        self.cache = cache
        self.secure = secure
29
30
        self.retry_count = retry_count
        self.retry_delay = retry_delay
31
        self.retry_errors = retry_errors
32
        self.parser = parser or ModelParser()
Josh Roesslein's avatar
Josh Roesslein committed
33

34
    """ statuses/public_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
35
36
    public_timeline = bind_api(
        path = '/statuses/public_timeline.json',
37
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
38
39
40
        allowed_param = []
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
41
    """ statuses/home_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
42
43
    home_timeline = bind_api(
        path = '/statuses/home_timeline.json',
44
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
45
46
47
48
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

49
    """ statuses/friends_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
50
51
    friends_timeline = bind_api(
        path = '/statuses/friends_timeline.json',
52
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
53
54
55
56
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

57
    """ statuses/user_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
58
59
    user_timeline = bind_api(
        path = '/statuses/user_timeline.json',
60
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
61
        allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
62
                          'max_id', 'count', 'page', 'include_rts']
Josh Roesslein's avatar
Josh Roesslein committed
63
64
    )

65
    """ statuses/mentions """
Josh Roesslein's avatar
Josh Roesslein committed
66
67
    mentions = bind_api(
        path = '/statuses/mentions.json',
68
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
69
70
71
72
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

73
74
75
76
77
78
79
    """/statuses/:id/retweeted_by.format"""
    retweeted_by = bind_api(
        path = '/statuses/{id}/retweeted_by.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['id', 'count', 'page'],
        require_auth = True
    )
80

Aaron Swartz's avatar
Aaron Swartz committed
81
82
83
84
85
86
87
    """/related_results/show/:id.format"""
    related_results = bind_api(
        path = '/related_results/show/{id}.json',
        payload_type = 'relation', payload_list = True,
        allowed_param = ['id'],
        require_auth = False
	)
88
89
90
91
92
93
94
95
96

    """/statuses/:id/retweeted_by/ids.format"""
    retweeted_by_ids = bind_api(
        path = '/statuses/{id}/retweeted_by/ids.json',
        payload_type = 'ids',
        allowed_param = ['id', 'count', 'page'],
        require_auth = True
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
97
    """ statuses/retweeted_by_me """
Josh Roesslein's avatar
Josh Roesslein committed
98
99
    retweeted_by_me = bind_api(
        path = '/statuses/retweeted_by_me.json',
100
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
101
102
103
104
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

105
    """ statuses/retweeted_to_me """
Josh Roesslein's avatar
Josh Roesslein committed
106
107
    retweeted_to_me = bind_api(
        path = '/statuses/retweeted_to_me.json',
108
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
109
110
111
112
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

113
    """ statuses/retweets_of_me """
Josh Roesslein's avatar
Josh Roesslein committed
114
115
    retweets_of_me = bind_api(
        path = '/statuses/retweets_of_me.json',
116
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
117
118
119
120
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

121
    """ statuses/show """
Josh Roesslein's avatar
Josh Roesslein committed
122
123
    get_status = bind_api(
        path = '/statuses/show.json',
124
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
125
126
127
        allowed_param = ['id']
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
128
    """ statuses/update """
Josh Roesslein's avatar
Josh Roesslein committed
129
130
131
    update_status = bind_api(
        path = '/statuses/update.json',
        method = 'POST',
132
        payload_type = 'status',
133
        allowed_param = ['status', 'in_reply_to_status_id', 'lat', 'long', 'source', 'place_id'],
Josh Roesslein's avatar
Josh Roesslein committed
134
135
136
        require_auth = True
    )

137
    """ statuses/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
138
139
140
    destroy_status = bind_api(
        path = '/statuses/destroy.json',
        method = 'DELETE',
141
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
142
143
144
145
        allowed_param = ['id'],
        require_auth = True
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
146
    """ statuses/retweet """
147
148
149
    retweet = bind_api(
        path = '/statuses/retweet/{id}.json',
        method = 'POST',
150
        payload_type = 'status',
151
152
153
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
154

Ferenc Szalai's avatar
Ferenc Szalai committed
155
    """ statuses/retweets """
156
157
    retweets = bind_api(
        path = '/statuses/retweets/{id}.json',
158
        payload_type = 'status', payload_list = True,
159
160
161
        allowed_param = ['id', 'count'],
        require_auth = True
    )
162

163
    """ users/show """
Josh Roesslein's avatar
Josh Roesslein committed
164
165
    get_user = bind_api(
        path = '/users/show.json',
166
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
167
168
169
        allowed_param = ['id', 'user_id', 'screen_name']
    )

170
171
172
173
174
175
176
177
178
179
180
    """ Perform bulk look up of users from user ID or screenname """
    def lookup_users(self, user_ids=None, screen_names=None):
        return self._lookup_users(list_to_csv(user_ids), list_to_csv(screen_names))

    _lookup_users = bind_api(
        path = '/users/lookup.json',
        payload_type = 'user', payload_list = True,
        allowed_param = ['user_id', 'screen_name'],
        require_auth = True
    )

181
    """ Get the authenticated user """
Josh Roesslein's avatar
Josh Roesslein committed
182
    def me(self):
Josh Roesslein's avatar
Josh Roesslein committed
183
        return self.get_user(screen_name=self.auth.get_username())
Josh Roesslein's avatar
Josh Roesslein committed
184

185
186
187
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
188
        payload_type = 'user', payload_list = True,
189
190
191
192
        require_auth = True,
        allowed_param = ['q', 'per_page', 'page']
    )

193
    """ statuses/friends """
Josh Roesslein's avatar
Josh Roesslein committed
194
195
    friends = bind_api(
        path = '/statuses/friends.json',
196
        payload_type = 'user', payload_list = True,
197
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
198
199
    )

200
    """ statuses/followers """
Josh Roesslein's avatar
Josh Roesslein committed
201
202
    followers = bind_api(
        path = '/statuses/followers.json',
203
        payload_type = 'user', payload_list = True,
204
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
205
206
    )

207
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
208
209
    direct_messages = bind_api(
        path = '/direct_messages.json',
210
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
211
212
213
214
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

215
216
217
218
219
220
221
222
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

223
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
224
225
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
226
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
227
228
229
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
230

231
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
232
233
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
234
        method = 'POST',
235
        payload_type = 'direct_message',
236
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
237
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
238
    )
239

240
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
241
242
243
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
244
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
245
246
247
248
        allowed_param = ['id'],
        require_auth = True
    )

249
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
250
251
    create_friendship = bind_api(
        path = '/friendships/create.json',
252
        method = 'POST',
253
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
254
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
255
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
256
257
    )

258
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
259
260
261
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
262
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
263
264
265
266
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

267
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
268
269
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
270
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
271
272
273
        allowed_param = ['user_a', 'user_b']
    )

274
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
275
276
    show_friendship = bind_api(
        path = '/friendships/show.json',
277
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
278
279
280
281
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

282
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
283
284
    friends_ids = bind_api(
        path = '/friends/ids.json',
285
        payload_type = 'ids',
286
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
287
288
    )

289
290
291
292
293
294
295
296
297
298
299
300
301
302
    """ friendships/incoming """
    friendships_incoming = bind_api(
        path = '/friendships/incoming.json',
        payload_type = 'ids',
        allowed_param = ['cursor']
    )

    """ friendships/outgoing"""
    friendships_outgoing = bind_api(
        path = '/friendships/outgoing.json',
        payload_type = 'ids',
        allowed_param = ['cursor']
    )

303
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
304
305
    followers_ids = bind_api(
        path = '/followers/ids.json',
306
        payload_type = 'ids',
307
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
308
309
    )

310
    """ account/verify_credentials """
Josh Roesslein's avatar
Josh Roesslein committed
311
312
313
314
    def verify_credentials(self):
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
315
                payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
316
317
                require_auth = True
            )(self)
318
319
320
321
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
322

323
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
324
325
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
326
327
        payload_type = 'json',
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
328
329
    )

330
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
331
332
333
334
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
335
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
336
337
338
        require_auth = True
    )

339
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
340
341
342
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
343
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
344
345
346
347
348
349
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

350
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
351
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
352
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
353
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
354
355
            path = '/account/update_profile_image.json',
            method = 'POST',
356
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
357
358
359
            require_auth = True
        )(self, post_data=post_data, headers=headers)

360
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
361
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
362
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
363
364
365
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
366
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
367
368
369
370
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

371
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
372
373
374
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
375
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
376
        allowed_param = ['name', 'url', 'location', 'description'],
377
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
378
379
    )

380
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
381
382
    favorites = bind_api(
        path = '/favorites.json',
383
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
384
385
386
        allowed_param = ['id', 'page']
    )

387
    """ favorites/create """
388
389
390
    create_favorite = bind_api(
        path = '/favorites/create/{id}.json',
        method = 'POST',
391
        payload_type = 'status',
392
393
394
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
395

396
    """ favorites/destroy """
397
398
399
    destroy_favorite = bind_api(
        path = '/favorites/destroy/{id}.json',
        method = 'DELETE',
400
        payload_type = 'status',
401
402
403
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
404

405
    """ notifications/follow """
Josh Roesslein's avatar
Josh Roesslein committed
406
407
408
    enable_notifications = bind_api(
        path = '/notifications/follow.json',
        method = 'POST',
409
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
410
411
412
413
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

414
    """ notifications/leave """
Josh Roesslein's avatar
Josh Roesslein committed
415
416
417
    disable_notifications = bind_api(
        path = '/notifications/leave.json',
        method = 'POST',
418
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
419
420
421
422
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

423
    """ blocks/create """
Josh Roesslein's avatar
Josh Roesslein committed
424
425
426
    create_block = bind_api(
        path = '/blocks/create.json',
        method = 'POST',
427
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
428
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
429
430
431
        require_auth = True
    )

432
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
433
434
435
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
436
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
437
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
438
439
440
        require_auth = True
    )

441
    """ blocks/exists """
Josh Roesslein's avatar
Josh Roesslein committed
442
    def exists_block(self, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
443
444
445
446
447
        try:
            bind_api(
                path = '/blocks/exists.json',
                allowed_param = ['id', 'user_id', 'screen_name'],
                require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
448
            )(self, *args, **kargs)
Josh Roesslein's avatar
Josh Roesslein committed
449
450
451
452
        except TweepError:
            return False
        return True

453
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
454
455
    blocks = bind_api(
        path = '/blocks/blocking.json',
456
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
457
458
459
460
        allowed_param = ['page'],
        require_auth = True
    )

461
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
462
463
    blocks_ids = bind_api(
        path = '/blocks/blocking/ids.json',
464
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
465
466
467
        require_auth = True
    )

468
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
469
470
471
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
472
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
473
474
475
476
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

477
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
478
479
    saved_searches = bind_api(
        path = '/saved_searches.json',
480
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
481
482
483
        require_auth = True
    )

484
    """ saved_searches/show """
485
486
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
487
        payload_type = 'saved_search',
488
489
490
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
491

492
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
493
494
495
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
496
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
497
498
499
500
        allowed_param = ['query'],
        require_auth = True
    )

501
    """ saved_searches/destroy """
502
503
504
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
505
        payload_type = 'saved_search',
506
507
508
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
509

510
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
511
    def test(self):
512
        try:
513
            bind_api(
514
515
516
517
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
518
        return True
519

Josh Roesslein's avatar
Josh Roesslein committed
520
521
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
522
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
523
            method = 'POST',
524
            payload_type = 'list',
525
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
526
527
528
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
529
530
531
532
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
533
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
534
535
536
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
537
538
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
539
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
540
            method = 'POST',
541
            payload_type = 'list',
542
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
543
544
545
            require_auth = True
        )(self, *args, **kargs)

546
547
    lists = bind_api(
        path = '/{user}/lists.json',
548
        payload_type = 'list', payload_list = True,
549
550
551
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
552

553
554
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
555
        payload_type = 'list', payload_list = True,
556
557
558
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
559

560
561
    lists_subscriptions = bind_api(
        path = '/{user}/lists/subscriptions.json',
562
        payload_type = 'list', payload_list = True,
563
564
565
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
566

567
568
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
569
        payload_type = 'status', payload_list = True,
570
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
571
    )
Josh Roesslein's avatar
Josh Roesslein committed
572

573
574
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
575
        payload_type = 'list',
576
577
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
578
579
580
581
582

    def add_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'POST',
583
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
584
585
586
587
588
589
590
591
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

    def remove_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
592
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
593
594
595
596
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

597
598
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
599
        payload_type = 'user', payload_list = True,
600
601
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
602
603
604
605
606

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
607
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
608
609
610
611
            )(self)
        except TweepError:
            return False

612
613
614
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
615
        payload_type = 'list',
616
617
618
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
619

620
621
622
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
623
        payload_type = 'list',
624
625
626
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
627

628
629
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
630
        payload_type = 'user', payload_list = True,
631
632
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
633
634
635
636
637

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
638
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
639
640
641
642
            )(self)
        except TweepError:
            return False

643
    """ trends/available """
644
645
    trends_available = bind_api(
        path = '/trends/available.json',
646
        payload_type = 'json',
647
648
649
        allowed_param = ['lat', 'long']
    )

650
    """ trends/location """
651
652
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
653
        payload_type = 'json',
654
655
        allowed_param = ['woeid']
    )
656

657
    """ search """
658
659
660
    search = bind_api(
        search_api = True,
        path = '/search.json',
661
        payload_type = 'search_result', payload_list = True,
662
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
663
    )
664
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
665

666
    """ trends """
667
668
    trends = bind_api(
        path = '/trends.json',
669
        payload_type = 'json'
670
    )
Josh Roesslein's avatar
Josh Roesslein committed
671

672
    """ trends/current """
673
674
    trends_current = bind_api(
        path = '/trends/current.json',
675
        payload_type = 'json',
676
677
        allowed_param = ['exclude']
    )
678

679
    """ trends/daily """
680
681
    trends_daily = bind_api(
        path = '/trends/daily.json',
682
        payload_type = 'json',
683
684
        allowed_param = ['date', 'exclude']
    )
685

686
    """ trends/weekly """
687
688
    trends_weekly = bind_api(
        path = '/trends/weekly.json',
689
        payload_type = 'json',
690
691
        allowed_param = ['date', 'exclude']
    )
692

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
        payload_type = 'json',
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/nearby_places """
    nearby_places = bind_api(
        path = '/geo/nearby_places.json',
        payload_type = 'json',
        allowed_param = ['lat', 'long', 'ip', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/id """
    geo_id = bind_api(
        path = '/geo/id/{id}.json',
        payload_type = 'json',
        allowed_param = ['id']
    )

714
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
715
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
    def _pack_image(filename, max_size):
        """Pack image from file into multipart-formdata post body"""
        # image must be less than 700kb in size
        try:
            if os.path.getsize(filename) > (max_size * 1024):
                raise TweepError('File is too big, must be less than 700kb.')
        except os.error, e:
            raise TweepError('Unable to access file')

        # image must be gif, jpeg, or png
        file_type = mimetypes.guess_type(filename)
        if file_type is None:
            raise TweepError('Could not determine file type')
        file_type = file_type[0]
        if file_type not in ['image/gif', 'image/jpeg', 'image/png']:
            raise TweepError('Invalid file type for image: %s' % file_type)

        # build the mulitpart-formdata body
        fp = open(filename, 'rb')
        BOUNDARY = 'Tw3ePy'
        body = []
        body.append('--' + BOUNDARY)
        body.append('Content-Disposition: form-data; name="image"; filename="%s"' % filename)
        body.append('Content-Type: %s' % file_type)
        body.append('')
        body.append(fp.read())
        body.append('--' + BOUNDARY + '--')
        body.append('')
        fp.close()
        body = '\r\n'.join(body)

        # build headers
        headers = {
            'Content-Type': 'multipart/form-data; boundary=Tw3ePy',
750
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
751
752
753
        }

        return headers, body
754