api.py 20 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

Josh Roesslein's avatar
Josh Roesslein committed
12

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

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

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

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

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

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

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

Ferenc Szalai's avatar
Ferenc Szalai committed
72
    """ statuses/retweeted_by_me """
Josh Roesslein's avatar
Josh Roesslein committed
73
74
    retweeted_by_me = bind_api(
        path = '/statuses/retweeted_by_me.json',
75
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
76
77
78
79
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

80
    """ statuses/retweeted_to_me """
Josh Roesslein's avatar
Josh Roesslein committed
81
82
    retweeted_to_me = bind_api(
        path = '/statuses/retweeted_to_me.json',
83
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
84
85
86
87
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

88
    """ statuses/retweets_of_me """
Josh Roesslein's avatar
Josh Roesslein committed
89
90
    retweets_of_me = bind_api(
        path = '/statuses/retweets_of_me.json',
91
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
92
93
94
95
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

96
    """ statuses/show """
Josh Roesslein's avatar
Josh Roesslein committed
97
98
    get_status = bind_api(
        path = '/statuses/show.json',
99
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
100
101
102
        allowed_param = ['id']
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
103
    """ statuses/update """
Josh Roesslein's avatar
Josh Roesslein committed
104
105
106
    update_status = bind_api(
        path = '/statuses/update.json',
        method = 'POST',
107
        payload_type = 'status',
108
        allowed_param = ['status', 'in_reply_to_status_id', 'lat', 'long', 'source'],
Josh Roesslein's avatar
Josh Roesslein committed
109
110
111
        require_auth = True
    )

112
    """ statuses/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
113
114
115
    destroy_status = bind_api(
        path = '/statuses/destroy.json',
        method = 'DELETE',
116
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
117
118
119
120
        allowed_param = ['id'],
        require_auth = True
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
121
    """ statuses/retweet """
122
123
124
    retweet = bind_api(
        path = '/statuses/retweet/{id}.json',
        method = 'POST',
125
        payload_type = 'status',
126
127
128
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
129

Ferenc Szalai's avatar
Ferenc Szalai committed
130
    """ statuses/retweets """
131
132
    retweets = bind_api(
        path = '/statuses/retweets/{id}.json',
133
        payload_type = 'status', payload_list = True,
134
135
136
        allowed_param = ['id', 'count'],
        require_auth = True
    )
137

138
    """ users/show """
Josh Roesslein's avatar
Josh Roesslein committed
139
140
    get_user = bind_api(
        path = '/users/show.json',
141
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
142
143
144
        allowed_param = ['id', 'user_id', 'screen_name']
    )

145
    """ Get the authenticated user """
Josh Roesslein's avatar
Josh Roesslein committed
146
    def me(self):
Josh Roesslein's avatar
Josh Roesslein committed
147
        return self.get_user(screen_name=self.auth.get_username())
Josh Roesslein's avatar
Josh Roesslein committed
148

149
150
151
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
152
        payload_type = 'user', payload_list = True,
153
154
155
156
        require_auth = True,
        allowed_param = ['q', 'per_page', 'page']
    )

157
    """ statuses/friends """
Josh Roesslein's avatar
Josh Roesslein committed
158
159
    friends = bind_api(
        path = '/statuses/friends.json',
160
        payload_type = 'user', payload_list = True,
161
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
162
163
    )

164
    """ statuses/followers """
Josh Roesslein's avatar
Josh Roesslein committed
165
166
    followers = bind_api(
        path = '/statuses/followers.json',
167
        payload_type = 'user', payload_list = True,
168
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
169
170
    )

171
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
172
173
    direct_messages = bind_api(
        path = '/direct_messages.json',
174
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
175
176
177
178
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

179
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
180
181
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
182
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
183
184
185
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
186

187
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
188
189
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
190
        method = 'POST',
191
        payload_type = 'direct_message',
192
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
193
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
194
    )
195

196
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
197
198
199
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
200
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
201
202
203
204
        allowed_param = ['id'],
        require_auth = True
    )

205
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
206
207
    create_friendship = bind_api(
        path = '/friendships/create.json',
208
        method = 'POST',
209
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
210
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
211
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
212
213
    )

214
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
215
216
217
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
218
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
219
220
221
222
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

223
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
224
225
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
226
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
227
228
229
        allowed_param = ['user_a', 'user_b']
    )

230
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
231
232
    show_friendship = bind_api(
        path = '/friendships/show.json',
233
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
234
235
236
237
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

238
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
239
240
    friends_ids = bind_api(
        path = '/friends/ids.json',
241
        payload_type = 'ids',
242
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
243
244
    )

245
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
246
247
    followers_ids = bind_api(
        path = '/followers/ids.json',
248
        payload_type = 'ids',
249
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
250
251
    )

252
    """ account/verify_credentials """
Josh Roesslein's avatar
Josh Roesslein committed
253
254
255
256
    def verify_credentials(self):
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
257
                payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
258
259
260
261
262
                require_auth = True
            )(self)
        except TweepError:
            return False

263
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
264
265
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
266
        payload_type = 'json'
Josh Roesslein's avatar
Josh Roesslein committed
267
268
    )

269
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
270
271
272
273
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
274
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
275
276
277
        require_auth = True
    )

278
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
279
280
281
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
282
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
283
284
285
286
287
288
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

289
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
290
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
291
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
292
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
293
294
            path = '/account/update_profile_image.json',
            method = 'POST',
295
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
296
297
298
            require_auth = True
        )(self, post_data=post_data, headers=headers)

299
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
300
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
301
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
302
303
304
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
305
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
306
307
308
309
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

310
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
311
312
313
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
314
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
315
        allowed_param = ['name', 'url', 'location', 'description'],
316
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
317
318
    )

319
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
320
321
    favorites = bind_api(
        path = '/favorites.json',
322
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
323
324
325
        allowed_param = ['id', 'page']
    )

326
    """ favorites/create """
327
328
329
    create_favorite = bind_api(
        path = '/favorites/create/{id}.json',
        method = 'POST',
330
        payload_type = 'status',
331
332
333
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
334

335
    """ favorites/destroy """
336
337
338
    destroy_favorite = bind_api(
        path = '/favorites/destroy/{id}.json',
        method = 'DELETE',
339
        payload_type = 'status',
340
341
342
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
343

344
    """ notifications/follow """
Josh Roesslein's avatar
Josh Roesslein committed
345
346
347
    enable_notifications = bind_api(
        path = '/notifications/follow.json',
        method = 'POST',
348
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
349
350
351
352
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

353
    """ notifications/leave """
Josh Roesslein's avatar
Josh Roesslein committed
354
355
356
    disable_notifications = bind_api(
        path = '/notifications/leave.json',
        method = 'POST',
357
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
358
359
360
361
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

362
    """ blocks/create """
Josh Roesslein's avatar
Josh Roesslein committed
363
364
365
    create_block = bind_api(
        path = '/blocks/create.json',
        method = 'POST',
366
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
367
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
368
369
370
        require_auth = True
    )

371
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
372
373
374
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
375
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
376
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
377
378
379
        require_auth = True
    )

380
    """ blocks/exists """
Josh Roesslein's avatar
Josh Roesslein committed
381
    def exists_block(self, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
382
383
384
385
386
        try:
            bind_api(
                path = '/blocks/exists.json',
                allowed_param = ['id', 'user_id', 'screen_name'],
                require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
387
            )(self, *args, **kargs)
Josh Roesslein's avatar
Josh Roesslein committed
388
389
390
391
        except TweepError:
            return False
        return True

392
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
393
394
    blocks = bind_api(
        path = '/blocks/blocking.json',
395
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
396
397
398
399
        allowed_param = ['page'],
        require_auth = True
    )

400
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
401
402
    blocks_ids = bind_api(
        path = '/blocks/blocking/ids.json',
403
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
404
405
406
        require_auth = True
    )

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

416
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
417
418
    saved_searches = bind_api(
        path = '/saved_searches.json',
419
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
420
421
422
        require_auth = True
    )

423
    """ saved_searches/show """
424
425
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
426
        payload_type = 'saved_search',
427
428
429
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
430

431
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
432
433
434
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
435
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
436
437
438
439
        allowed_param = ['query'],
        require_auth = True
    )

440
    """ saved_searches/destroy """
441
442
443
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
444
        payload_type = 'saved_search',
445
446
447
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
448

449
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
450
    def test(self):
451
        try:
452
            bind_api(
453
454
455
456
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
457
        return True
458

Josh Roesslein's avatar
Josh Roesslein committed
459
460
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
461
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
462
            method = 'POST',
463
            payload_type = 'list',
464
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
465
466
467
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
468
469
470
471
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
472
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
473
474
475
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
476
477
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
478
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
479
            method = 'POST',
480
            payload_type = 'list',
481
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
482
483
484
            require_auth = True
        )(self, *args, **kargs)

485
486
    lists = bind_api(
        path = '/{user}/lists.json',
487
        payload_type = 'list', payload_list = True,
488
489
490
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
491

492
493
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
494
        payload_type = 'list', payload_list = True,
495
496
497
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
498

499
500
    lists_subscriptions = bind_api(
        path = '/{user}/lists/subscriptions.json',
501
        payload_type = 'list', payload_list = True,
502
503
504
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
505

506
507
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
508
        payload_type = 'status', payload_list = True,
509
510
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'count', 'page']
    )
Josh Roesslein's avatar
Josh Roesslein committed
511

512
513
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
514
        payload_type = 'list',
515
516
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
517
518
519
520
521

    def add_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'POST',
522
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
523
524
525
526
527
528
529
530
            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',
531
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
532
533
534
535
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

536
537
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
538
        payload_type = 'user', payload_list = True,
539
540
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
541
542
543
544
545

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
546
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
547
548
549
550
            )(self)
        except TweepError:
            return False

551
552
553
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
554
        payload_type = 'list',
555
556
557
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
558

559
560
561
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
562
        payload_type = 'list',
563
564
565
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
566

567
568
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
569
        payload_type = 'user', payload_list = True,
570
571
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
572
573
574
575
576

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
577
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
578
579
580
581
            )(self)
        except TweepError:
            return False

582
    """ trends/available """
583
584
    trends_available = bind_api(
        path = '/trends/available.json',
585
        payload_type = 'json',
586
587
588
        allowed_param = ['lat', 'long']
    )

589
    """ trends/location """
590
591
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
592
        payload_type = 'json',
593
594
        allowed_param = ['woeid']
    )
595

596
    """ search """
597
598
599
    search = bind_api(
        search_api = True,
        path = '/search.json',
600
        payload_type = 'search_result', payload_list = True,
601
602
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user']
    )
603
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
604

605
    """ trends """
606
607
608
    trends = bind_api(
        search_api = True,
        path = '/trends.json',
609
        payload_type = 'json'
610
    )
Josh Roesslein's avatar
Josh Roesslein committed
611

612
    """ trends/current """
613
614
615
    trends_current = bind_api(
        search_api = True,
        path = '/trends/current.json',
616
        payload_type = 'json',
617
618
        allowed_param = ['exclude']
    )
619

620
    """ trends/daily """
621
622
623
    trends_daily = bind_api(
        search_api = True,
        path = '/trends/daily.json',
624
        payload_type = 'json',
625
626
        allowed_param = ['date', 'exclude']
    )
627

628
    """ trends/weekly """
629
630
631
    trends_weekly = bind_api(
        search_api = True,
        path = '/trends/weekly.json',
632
        payload_type = 'json',
633
634
        allowed_param = ['date', 'exclude']
    )
635

636
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
637
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
    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',
            'Content-Length': len(body)
        }

        return headers, body
676