api.py 23.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
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
    def __init__(self, auth_handler=None,
            host='api.twitter.com', search_host='search.twitter.com',
19
             cache=None, secure=True, api_root='/1.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

Ferenc Szalai's avatar
Ferenc Szalai committed
34
    """ statuses/home_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
35
36
    home_timeline = bind_api(
        path = '/statuses/home_timeline.json',
37
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
38
39
40
41
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

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

50
    """ statuses/user_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
51
52
    user_timeline = bind_api(
        path = '/statuses/user_timeline.json',
53
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
54
        allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
55
                          'max_id', 'count', 'page', 'include_rts']
Josh Roesslein's avatar
Josh Roesslein committed
56
57
    )

58
    """ statuses/mentions """
Josh Roesslein's avatar
Josh Roesslein committed
59
60
    mentions = bind_api(
        path = '/statuses/mentions.json',
61
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
62
63
64
65
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

66
67
68
69
70
71
72
73
    """/statuses/retweeted_by_user.format"""
    retweeted_by_user = bind_api(
        path = '/statuses/retweeted_by_user.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['screen_name', 'id', 'count', 'since_id',
                            'max_id', 'page', 'include_entities']
    )

74
75
76
77
78
79
80
    """/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
    )
81

Aaron Swartz's avatar
Aaron Swartz committed
82
83
84
85
86
87
88
    """/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
	)
89
90
91
92
93
94
95
96
97

    """/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
98
    """ statuses/retweeted_by_me """
Josh Roesslein's avatar
Josh Roesslein committed
99
100
    retweeted_by_me = bind_api(
        path = '/statuses/retweeted_by_me.json',
101
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
102
103
104
105
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

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

Alejandro Gómez's avatar
Alejandro Gómez committed
114
115
116
117
118
119
120
121
    """ statuses/retweeted_by_user """
    retweeted_by_user = bind_api(
        path = '/statuses/retweeted_by_user.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['screen_name', 'id', 'since_id', 'max_id', 'count', 'page', 'trim_user', 'include_entities'],
        require_auth = False
    )

122
    """ statuses/retweets_of_me """
Josh Roesslein's avatar
Josh Roesslein committed
123
124
    retweets_of_me = bind_api(
        path = '/statuses/retweets_of_me.json',
125
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
126
127
128
129
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

130
    """ statuses/show """
Josh Roesslein's avatar
Josh Roesslein committed
131
132
    get_status = bind_api(
        path = '/statuses/show.json',
133
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
134
135
136
        allowed_param = ['id']
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
137
    """ statuses/update """
Josh Roesslein's avatar
Josh Roesslein committed
138
139
140
    update_status = bind_api(
        path = '/statuses/update.json',
        method = 'POST',
141
        payload_type = 'status',
142
        allowed_param = ['status', 'in_reply_to_status_id', 'lat', 'long', 'source', 'place_id'],
Josh Roesslein's avatar
Josh Roesslein committed
143
144
145
        require_auth = True
    )

146
    """ statuses/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
147
148
149
    destroy_status = bind_api(
        path = '/statuses/destroy.json',
        method = 'DELETE',
150
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
151
152
153
154
        allowed_param = ['id'],
        require_auth = True
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
155
    """ statuses/retweet """
156
157
158
    retweet = bind_api(
        path = '/statuses/retweet/{id}.json',
        method = 'POST',
159
        payload_type = 'status',
160
161
162
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
163

Ferenc Szalai's avatar
Ferenc Szalai committed
164
    """ statuses/retweets """
165
166
    retweets = bind_api(
        path = '/statuses/retweets/{id}.json',
167
        payload_type = 'status', payload_list = True,
168
169
170
        allowed_param = ['id', 'count'],
        require_auth = True
    )
171

172
    """ users/show """
Josh Roesslein's avatar
Josh Roesslein committed
173
174
    get_user = bind_api(
        path = '/users/show.json',
175
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
176
177
178
        allowed_param = ['id', 'user_id', 'screen_name']
    )

179
180
181
182
183
184
185
186
187
188
    """ 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'],
    )

189
    """ Get the authenticated user """
Josh Roesslein's avatar
Josh Roesslein committed
190
    def me(self):
Josh Roesslein's avatar
Josh Roesslein committed
191
        return self.get_user(screen_name=self.auth.get_username())
Josh Roesslein's avatar
Josh Roesslein committed
192

193
194
195
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
196
        payload_type = 'user', payload_list = True,
197
198
199
200
        require_auth = True,
        allowed_param = ['q', 'per_page', 'page']
    )

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    """ users/suggestions/:slug """
    suggested_users = bind_api(
        path = '/users/suggestions/{slug}.json',
        payload_type = 'user', payload_list = True,
        require_auth = True,
        allowed_param = ['slug', 'lang']
    )

    """ users/suggestions """
    suggested_categories = bind_api(
        path = '/users/suggestions.json',
        payload_type = 'category', payload_list = True,
        allowed_param = ['lang'],
        require_auth = True
    )

    """ users/suggestions/:slug/members """
    suggested_users_tweets = bind_api(
        path = '/users/suggestions/{slug}/members.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['slug'],
        require_auth = True
    )

225
    """ statuses/friends """
Josh Roesslein's avatar
Josh Roesslein committed
226
227
    friends = bind_api(
        path = '/statuses/friends.json',
228
        payload_type = 'user', payload_list = True,
229
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
230
231
    )

232
    """ statuses/followers """
Josh Roesslein's avatar
Josh Roesslein committed
233
234
    followers = bind_api(
        path = '/statuses/followers.json',
235
        payload_type = 'user', payload_list = True,
236
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
237
238
    )

239
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
240
241
    direct_messages = bind_api(
        path = '/direct_messages.json',
242
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
243
244
245
246
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

247
248
249
250
251
252
253
254
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

255
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
256
257
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
258
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
259
260
261
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
262

263
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
264
265
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
266
        method = 'POST',
267
        payload_type = 'direct_message',
268
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
269
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
270
    )
271

272
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
273
274
275
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
276
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
277
278
279
280
        allowed_param = ['id'],
        require_auth = True
    )

281
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
282
283
    create_friendship = bind_api(
        path = '/friendships/create.json',
284
        method = 'POST',
285
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
286
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
287
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
288
289
    )

290
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
291
292
293
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
294
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
295
296
297
298
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

299
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
300
301
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
302
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
303
304
305
        allowed_param = ['user_a', 'user_b']
    )

306
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
307
308
    show_friendship = bind_api(
        path = '/friendships/show.json',
309
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
310
311
312
313
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

314
315
316
317
318
319
320
321
322
323
324
325
326

    """ Perform bulk look up of friendships from user ID or screenname """
    def lookup_friendships(self, user_ids=None, screen_names=None):
	    return self._lookup_friendships(list_to_csv(user_ids), list_to_csv(screen_names))

    _lookup_friendships = bind_api(
        path = '/friendships/lookup.json',
        payload_type = 'relationship', payload_list = True,
        allowed_param = ['user_id', 'screen_name'],
        require_auth = True
    )


327
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
328
329
    friends_ids = bind_api(
        path = '/friends/ids.json',
330
        payload_type = 'ids',
331
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
332
333
    )

334
335
336
337
338
339
340
341
342
343
344
345
346
347
    """ 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']
    )

348
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
349
350
    followers_ids = bind_api(
        path = '/followers/ids.json',
351
        payload_type = 'ids',
352
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
353
354
    )

355
    """ account/verify_credentials """
356
    def verify_credentials(self, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
357
358
359
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
360
                payload_type = 'user',
361
362
363
                require_auth = True,
                allowed_param = ['include_entities', 'skip_status'],
            )(self, **kargs)
364
365
366
367
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
368

369
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
370
371
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
372
373
        payload_type = 'json',
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
374
375
    )

376
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
377
378
379
380
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
381
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
382
383
384
        require_auth = True
    )

385
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
386
387
388
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
389
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
390
391
392
393
394
395
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

396
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
397
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
398
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
399
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
400
401
            path = '/account/update_profile_image.json',
            method = 'POST',
402
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
403
404
405
            require_auth = True
        )(self, post_data=post_data, headers=headers)

406
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
407
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
408
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
409
410
411
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
412
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
413
414
415
416
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

417
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
418
419
420
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
421
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
422
        allowed_param = ['name', 'url', 'location', 'description'],
423
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
424
425
    )

426
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
427
428
    favorites = bind_api(
        path = '/favorites.json',
429
        payload_type = 'status', payload_list = True,
430
        allowed_param = ['id', 'max_id', 'page']
Josh Roesslein's avatar
Josh Roesslein committed
431
432
    )

433
    """ favorites/create """
434
    create_favorite = bind_api(
435
        path = '/favorites/create.json',
436
        method = 'POST',
437
        payload_type = 'status',
438
439
440
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
441

442
    """ favorites/destroy """
443
    destroy_favorite = bind_api(
444
445
        path = '/favorites/destroy.json',
        method = 'POST',
446
        payload_type = 'status',
447
448
449
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
450

451
    """ blocks/create """
Josh Roesslein's avatar
Josh Roesslein committed
452
453
454
    create_block = bind_api(
        path = '/blocks/create.json',
        method = 'POST',
455
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
456
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
457
458
459
        require_auth = True
    )

460
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
461
462
463
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
464
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
465
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
466
467
468
        require_auth = True
    )

469
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
470
    blocks = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
471
        path = '/blocks/list.json',
472
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
473
474
475
476
        allowed_param = ['page'],
        require_auth = True
    )

477
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
478
    blocks_ids = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
479
        path = '/blocks/ids.json',
480
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
481
482
483
        require_auth = True
    )

484
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
485
486
487
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
488
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
489
490
491
492
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

493
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
494
495
    saved_searches = bind_api(
        path = '/saved_searches.json',
496
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
497
498
499
        require_auth = True
    )

500
    """ saved_searches/show """
501
502
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
503
        payload_type = 'saved_search',
504
505
506
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
507

508
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
509
510
511
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
512
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
513
514
515
516
        allowed_param = ['query'],
        require_auth = True
    )

517
    """ saved_searches/destroy """
518
519
520
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
521
        payload_type = 'saved_search',
522
523
524
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
525

526
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
527
    def test(self):
528
        try:
529
            bind_api(
530
531
532
533
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
534
        return True
535

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

Josh Roesslein's avatar
Josh Roesslein committed
545
546
547
548
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
549
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
550
551
552
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
553
554
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
555
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
556
            method = 'POST',
557
            payload_type = 'list',
558
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
559
560
561
            require_auth = True
        )(self, *args, **kargs)

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

569
570
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
571
        payload_type = 'list', payload_list = True,
572
573
574
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
575

576
577
    lists_subscriptions = bind_api(
        path = '/{user}/lists/subscriptions.json',
578
        payload_type = 'list', payload_list = True,
579
580
581
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
582

583
584
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
585
        payload_type = 'status', payload_list = True,
586
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
587
    )
Josh Roesslein's avatar
Josh Roesslein committed
588

589
590
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
591
        payload_type = 'list',
592
593
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
594

595
596
597
598
599
600
601
    add_list_member = bind_api(
        path = '/lists/members/create.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['screen_name', 'user_id', 'owner_screen_name', 'owner_id', 'slug', 'list_id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
602

603
604
605
606
607
608
609
    remove_list_member = bind_api(
        path = '/lists/members/destroy.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['screen_name', 'user_id', 'owner_screen_name', 'owner_id', 'slug', 'list_id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
610

611
612
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
613
        payload_type = 'user', payload_list = True,
614
615
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
616
617
618
619
620

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
621
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
622
623
624
625
            )(self)
        except TweepError:
            return False

626
627
628
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
629
        payload_type = 'list',
630
631
632
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
633

634
635
636
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
637
        payload_type = 'list',
638
639
640
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
641

642
643
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
644
        payload_type = 'user', payload_list = True,
645
646
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
647
648
649
650
651

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
652
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
653
654
655
656
            )(self)
        except TweepError:
            return False

657
    """ trends/available """
658
659
    trends_available = bind_api(
        path = '/trends/available.json',
660
        payload_type = 'json',
661
662
663
        allowed_param = ['lat', 'long']
    )

664
    """ trends/location """
665
666
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
667
        payload_type = 'json',
668
669
        allowed_param = ['woeid']
    )
670

671
    """ search """
672
673
674
    search = bind_api(
        search_api = True,
        path = '/search.json',
675
        payload_type = 'search_result', payload_list = True,
676
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
677
    )
678
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
679

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

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

694
695
696
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
697
        payload_type = 'place', payload_list = True,
698
699
700
701
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/nearby_places """
702
    # listed as deprecated on twitter's API documents
703
704
    nearby_places = bind_api(
        path = '/geo/nearby_places.json',
705
        payload_type = 'place', payload_list = True,
706
707
708
709
710
711
        allowed_param = ['lat', 'long', 'ip', 'accuracy', 'granularity', 'max_results']
    )

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

716
717
718
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
719
        payload_type = 'place', payload_list = True,
720
721
722
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

723
724
725
726
727
728
729
    """ geo/similar_places """
    geo_similar_places = bind_api(
        path = '/geo/similar_places.json',
        payload_type = 'place', payload_list = True,
        allowed_param = ['lat', 'long', 'name', 'contained_within']
    )

730
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
731
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
732
733
734
735
736
737
    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.')
738
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
            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',
766
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
767
768
769
        }

        return headers, body
770