api.py 20.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
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
62
63
64
        allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
                          'max_id', 'count', 'page']
    )

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
    )

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

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

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

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

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

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

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

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

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

146
147
148
149
150
151
152
153
154
155
156
    """ 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
    )

157
    """ Get the authenticated user """
Josh Roesslein's avatar
Josh Roesslein committed
158
    def me(self):
Josh Roesslein's avatar
Josh Roesslein committed
159
        return self.get_user(screen_name=self.auth.get_username())
Josh Roesslein's avatar
Josh Roesslein committed
160

161
162
163
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
164
        payload_type = 'user', payload_list = True,
165
166
167
168
        require_auth = True,
        allowed_param = ['q', 'per_page', 'page']
    )

169
    """ statuses/friends """
Josh Roesslein's avatar
Josh Roesslein committed
170
171
    friends = bind_api(
        path = '/statuses/friends.json',
172
        payload_type = 'user', payload_list = True,
173
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
174
175
    )

176
    """ statuses/followers """
Josh Roesslein's avatar
Josh Roesslein committed
177
178
    followers = bind_api(
        path = '/statuses/followers.json',
179
        payload_type = 'user', payload_list = True,
180
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
181
182
    )

183
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
184
185
    direct_messages = bind_api(
        path = '/direct_messages.json',
186
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
187
188
189
190
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

191
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
192
193
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
194
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
195
196
197
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
198

199
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
200
201
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
202
        method = 'POST',
203
        payload_type = 'direct_message',
204
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
205
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
206
    )
207

208
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
209
210
211
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
212
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
213
214
215
216
        allowed_param = ['id'],
        require_auth = True
    )

217
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
218
219
    create_friendship = bind_api(
        path = '/friendships/create.json',
220
        method = 'POST',
221
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
222
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
223
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
224
225
    )

226
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
227
228
229
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
230
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
231
232
233
234
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

235
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
236
237
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
238
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
239
240
241
        allowed_param = ['user_a', 'user_b']
    )

242
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
243
244
    show_friendship = bind_api(
        path = '/friendships/show.json',
245
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
246
247
248
249
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

250
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
251
252
    friends_ids = bind_api(
        path = '/friends/ids.json',
253
        payload_type = 'ids',
254
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
255
256
    )

257
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
258
259
    followers_ids = bind_api(
        path = '/followers/ids.json',
260
        payload_type = 'ids',
261
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
262
263
    )

264
    """ account/verify_credentials """
Josh Roesslein's avatar
Josh Roesslein committed
265
266
267
268
    def verify_credentials(self):
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
269
                payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
270
271
272
273
274
                require_auth = True
            )(self)
        except TweepError:
            return False

275
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
276
277
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
278
        payload_type = 'json'
Josh Roesslein's avatar
Josh Roesslein committed
279
280
    )

281
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
282
283
284
285
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
286
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
287
288
289
        require_auth = True
    )

290
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
291
292
293
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
294
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
295
296
297
298
299
300
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

301
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
302
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
303
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
304
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
305
306
            path = '/account/update_profile_image.json',
            method = 'POST',
307
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
308
309
310
            require_auth = True
        )(self, post_data=post_data, headers=headers)

311
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
312
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
313
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
314
315
316
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
317
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
318
319
320
321
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

322
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
323
324
325
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
326
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
327
        allowed_param = ['name', 'url', 'location', 'description'],
328
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
329
330
    )

331
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
332
333
    favorites = bind_api(
        path = '/favorites.json',
334
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
335
336
337
        allowed_param = ['id', 'page']
    )

338
    """ favorites/create """
339
340
341
    create_favorite = bind_api(
        path = '/favorites/create/{id}.json',
        method = 'POST',
342
        payload_type = 'status',
343
344
345
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
346

347
    """ favorites/destroy """
348
349
350
    destroy_favorite = bind_api(
        path = '/favorites/destroy/{id}.json',
        method = 'DELETE',
351
        payload_type = 'status',
352
353
354
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
355

356
    """ notifications/follow """
Josh Roesslein's avatar
Josh Roesslein committed
357
358
359
    enable_notifications = bind_api(
        path = '/notifications/follow.json',
        method = 'POST',
360
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
361
362
363
364
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

365
    """ notifications/leave """
Josh Roesslein's avatar
Josh Roesslein committed
366
367
368
    disable_notifications = bind_api(
        path = '/notifications/leave.json',
        method = 'POST',
369
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
370
371
372
373
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

374
    """ blocks/create """
Josh Roesslein's avatar
Josh Roesslein committed
375
376
377
    create_block = bind_api(
        path = '/blocks/create.json',
        method = 'POST',
378
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
379
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
380
381
382
        require_auth = True
    )

383
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
384
385
386
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
387
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
388
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
389
390
391
        require_auth = True
    )

392
    """ blocks/exists """
Josh Roesslein's avatar
Josh Roesslein committed
393
    def exists_block(self, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
394
395
396
397
398
        try:
            bind_api(
                path = '/blocks/exists.json',
                allowed_param = ['id', 'user_id', 'screen_name'],
                require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
399
            )(self, *args, **kargs)
Josh Roesslein's avatar
Josh Roesslein committed
400
401
402
403
        except TweepError:
            return False
        return True

404
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
405
406
    blocks = bind_api(
        path = '/blocks/blocking.json',
407
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
408
409
410
411
        allowed_param = ['page'],
        require_auth = True
    )

412
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
413
414
    blocks_ids = bind_api(
        path = '/blocks/blocking/ids.json',
415
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
416
417
418
        require_auth = True
    )

419
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
420
421
422
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
423
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
424
425
426
427
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

428
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
429
430
    saved_searches = bind_api(
        path = '/saved_searches.json',
431
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
432
433
434
        require_auth = True
    )

435
    """ saved_searches/show """
436
437
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
438
        payload_type = 'saved_search',
439
440
441
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
442

443
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
444
445
446
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
447
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
448
449
450
451
        allowed_param = ['query'],
        require_auth = True
    )

452
    """ saved_searches/destroy """
453
454
455
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
456
        payload_type = 'saved_search',
457
458
459
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
460

461
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
462
    def test(self):
463
        try:
464
            bind_api(
465
466
467
468
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
469
        return True
470

Josh Roesslein's avatar
Josh Roesslein committed
471
472
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
473
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
474
            method = 'POST',
475
            payload_type = 'list',
476
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
477
478
479
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
480
481
482
483
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
484
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
485
486
487
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
488
489
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
490
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
491
            method = 'POST',
492
            payload_type = 'list',
493
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
494
495
496
            require_auth = True
        )(self, *args, **kargs)

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

504
505
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
506
        payload_type = 'list', payload_list = True,
507
508
509
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
510

511
512
    lists_subscriptions = bind_api(
        path = '/{user}/lists/subscriptions.json',
513
        payload_type = 'list', payload_list = True,
514
515
516
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
517

518
519
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
520
        payload_type = 'status', payload_list = True,
521
522
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'count', 'page']
    )
Josh Roesslein's avatar
Josh Roesslein committed
523

524
525
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
526
        payload_type = 'list',
527
528
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
529
530
531
532
533

    def add_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'POST',
534
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
535
536
537
538
539
540
541
542
            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',
543
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
544
545
546
547
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

548
549
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
550
        payload_type = 'user', payload_list = True,
551
552
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
553
554
555
556
557

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
558
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
559
560
561
562
            )(self)
        except TweepError:
            return False

563
564
565
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
566
        payload_type = 'list',
567
568
569
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
570

571
572
573
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
574
        payload_type = 'list',
575
576
577
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
578

579
580
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
581
        payload_type = 'user', payload_list = True,
582
583
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
584
585
586
587
588

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
589
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
590
591
592
593
            )(self)
        except TweepError:
            return False

594
    """ trends/available """
595
596
    trends_available = bind_api(
        path = '/trends/available.json',
597
        payload_type = 'json',
598
599
600
        allowed_param = ['lat', 'long']
    )

601
    """ trends/location """
602
603
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
604
        payload_type = 'json',
605
606
        allowed_param = ['woeid']
    )
607

608
    """ search """
609
610
611
    search = bind_api(
        search_api = True,
        path = '/search.json',
612
        payload_type = 'search_result', payload_list = True,
613
614
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user']
    )
615
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
616

617
    """ trends """
618
619
620
    trends = bind_api(
        search_api = True,
        path = '/trends.json',
621
        payload_type = 'json'
622
    )
Josh Roesslein's avatar
Josh Roesslein committed
623

624
    """ trends/current """
625
626
627
    trends_current = bind_api(
        search_api = True,
        path = '/trends/current.json',
628
        payload_type = 'json',
629
630
        allowed_param = ['exclude']
    )
631

632
    """ trends/daily """
633
634
635
    trends_daily = bind_api(
        search_api = True,
        path = '/trends/daily.json',
636
        payload_type = 'json',
637
638
        allowed_param = ['date', 'exclude']
    )
639

640
    """ trends/weekly """
641
642
643
    trends_weekly = bind_api(
        search_api = True,
        path = '/trends/weekly.json',
644
        payload_type = 'json',
645
646
        allowed_param = ['date', 'exclude']
    )
647

648
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
649
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
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
676
677
678
679
680
681
682
683
684
685
686
687
    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
688