api.py 22.9 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, timeout=60,
21
            parser=None, compression=False, wait_on_rate_limit=False):
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
Mike's avatar
Mike committed
29
        self.compression = compression
30
31
        self.retry_count = retry_count
        self.retry_delay = retry_delay
32
        self.retry_errors = retry_errors
33
        self.timeout = timeout
34
        self.wait_on_rate_limit = wait_on_rate_limit
35
        self.parser = parser or ModelParser()
Josh Roesslein's avatar
Josh Roesslein committed
36

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

45
    """ statuses/user_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
46
47
    user_timeline = bind_api(
        path = '/statuses/user_timeline.json',
48
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
49
        allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
50
                          'max_id', 'count', 'include_rts']
Josh Roesslein's avatar
Josh Roesslein committed
51
52
    )

53
    """ statuses/mentions """
54
55
    mentions_timeline = bind_api(
        path = '/statuses/mentions_timeline.json',
56
        payload_type = 'status', payload_list = True,
57
        allowed_param = ['since_id', 'max_id', 'count'],
Josh Roesslein's avatar
Josh Roesslein committed
58
59
60
        require_auth = True
    )

Aaron Swartz's avatar
Aaron Swartz committed
61
62
63
64
65
66
    """/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
67
    )
68

69
    """ statuses/retweets_of_me """
Josh Roesslein's avatar
Josh Roesslein committed
70
71
    retweets_of_me = bind_api(
        path = '/statuses/retweets_of_me.json',
72
        payload_type = 'status', payload_list = True,
73
        allowed_param = ['since_id', 'max_id', 'count'],
Josh Roesslein's avatar
Josh Roesslein committed
74
75
76
        require_auth = True
    )

77
    """ statuses/show """
Josh Roesslein's avatar
Josh Roesslein committed
78
79
    get_status = bind_api(
        path = '/statuses/show.json',
80
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
81
82
83
        allowed_param = ['id']
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
84
    """ statuses/update """
Josh Roesslein's avatar
Josh Roesslein committed
85
86
87
    update_status = bind_api(
        path = '/statuses/update.json',
        method = 'POST',
88
        payload_type = 'status',
89
        allowed_param = ['status', 'in_reply_to_status_id', 'lat', 'long', 'source', 'place_id'],
Josh Roesslein's avatar
Josh Roesslein committed
90
91
92
        require_auth = True
    )

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    """ statuses/update_with_media """
    def update_with_media(self, filename, *args, **kwargs):
        headers, post_data = API._pack_image(filename, 3072, form_field='media[]')
        kwargs.update({'headers': headers, 'post_data': post_data})

        return bind_api(
            path='/statuses/update_with_media.json',
            method = 'POST',
            payload_type='status',
            allowed_param = [
                'status', 'possibly_sensitive', 'in_reply_to_status_id', 'lat', 'long',
                'place_id', 'display_coordinates'
            ],
            require_auth=True
        )(self, *args, **kwargs)

109
    """ statuses/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
110
    destroy_status = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
111
112
        path = '/statuses/destroy/{id}.json',
        method = 'POST',
113
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
114
115
116
117
        allowed_param = ['id'],
        require_auth = True
    )

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

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

Joshua Roesslein's avatar
Joshua Roesslein committed
135
136
137
138
139
140
    retweeters = bind_api(
        path = '/statuses/retweeters/ids.json',
        payload_type = 'ids',
        allowed_param = ['id', 'cursor', 'stringify_ids']
    )

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

Miriam Sexton's avatar
Miriam Sexton committed
148
149
    ''' statuses/oembed '''
    get_oembed = bind_api(
Miriam Sexton's avatar
Miriam Sexton committed
150
        path = '/statuses/oembed.json',
Miriam Sexton's avatar
Miriam Sexton committed
151
152
153
154
        payload_type = 'json',
        allowed_param = ['id', 'url', 'maxwidth', 'hide_media', 'omit_script', 'align', 'related', 'lang']
    )

155
156
157
158
159
160
161
162
163
164
    """ 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'],
    )

165
    """ Get the authenticated user """
Josh Roesslein's avatar
Josh Roesslein committed
166
    def me(self):
Josh Roesslein's avatar
Josh Roesslein committed
167
        return self.get_user(screen_name=self.auth.get_username())
Josh Roesslein's avatar
Josh Roesslein committed
168

169
170
171
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
172
        payload_type = 'user', payload_list = True,
173
        require_auth = True,
174
        allowed_param = ['q', 'count', 'page']
175
176
    )

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
    """ 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
    )

201
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
202
203
    direct_messages = bind_api(
        path = '/direct_messages.json',
204
        payload_type = 'direct_message', payload_list = True,
205
        allowed_param = ['since_id', 'max_id', 'count'],
Josh Roesslein's avatar
Josh Roesslein committed
206
207
208
        require_auth = True
    )

209
210
211
212
213
214
215
216
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

217
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
218
219
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
220
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
221
222
223
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
224

225
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
226
227
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
228
        method = 'POST',
229
        payload_type = 'direct_message',
230
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
231
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
232
    )
233

234
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
235
236
237
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
238
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
239
240
241
242
        allowed_param = ['id'],
        require_auth = True
    )

243
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
244
245
    create_friendship = bind_api(
        path = '/friendships/create.json',
246
        method = 'POST',
247
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
248
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
249
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
250
251
    )

252
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
253
254
255
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
256
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
257
258
259
260
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

261
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
262
263
    show_friendship = bind_api(
        path = '/friendships/show.json',
264
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
265
266
267
268
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

269
270
    """ Perform bulk look up of friendships from user ID or screenname """
    def lookup_friendships(self, user_ids=None, screen_names=None):
Santosh Kumar's avatar
Santosh Kumar committed
271
        return self._lookup_friendships(list_to_csv(user_ids), list_to_csv(screen_names))
272
273
274
275
276
277
278
279
280

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


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

288
289
290
291
    """ friends/list """
    friends = bind_api(
        path = '/friends/list.json',
        payload_type = 'user', payload_list = True,
292
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
293
294
    )

295
296
297
298
299
300
301
302
303
304
305
306
307
308
    """ 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']
    )

309
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
310
311
    followers_ids = bind_api(
        path = '/followers/ids.json',
312
        payload_type = 'ids',
313
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
314
315
    )

316
317
318
319
    """ followers/list """
    followers = bind_api(
        path = '/followers/list.json',
        payload_type = 'user', payload_list = True,
320
321
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor', 'count',
            'skip_status', 'include_user_entities']
322
323
    )

324
    """ account/verify_credentials """
325
    def verify_credentials(self, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
326
327
328
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
329
                payload_type = 'user',
330
331
332
                require_auth = True,
                allowed_param = ['include_entities', 'skip_status'],
            )(self, **kargs)
333
        except TweepError as e:
334
335
336
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
337

338
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
339
    rate_limit_status = bind_api(
340
        path = '/application/rate_limit_status.json',
341
        payload_type = 'json',
342
        allowed_param = ['resources'],
343
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
344
345
    )

346
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
347
348
349
350
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
351
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
352
353
354
        require_auth = True
    )

355
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
356
357
358
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
359
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
360
361
362
363
364
365
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

366
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
367
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
368
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
369
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
370
371
            path = '/account/update_profile_image.json',
            method = 'POST',
372
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
373
374
375
            require_auth = True
        )(self, post_data=post_data, headers=headers)

376
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
377
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
378
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
379
380
381
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
382
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
383
384
385
386
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

387
388
389
390
391
392
393
394
395
396
397
    """ account/update_profile_banner """
    def update_profile_banner(self, filename, *args, **kargs):
        headers, post_data = API._pack_image(filename, 700, form_field="banner")
        bind_api(
            path = '/account/update_profile_banner.json',
            method = 'POST',
            allowed_param = ['width', 'height', 'offset_left', 'offset_right'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)


398
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
399
400
401
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
402
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
403
        allowed_param = ['name', 'url', 'location', 'description'],
404
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
405
406
    )

407
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
408
    favorites = bind_api(
409
        path = '/favorites/list.json',
410
        payload_type = 'status', payload_list = True,
411
        allowed_param = ['screen_name', 'user_id', 'max_id', 'count', 'since_id', 'max_id']
Josh Roesslein's avatar
Josh Roesslein committed
412
413
    )

414
    """ favorites/create """
415
    create_favorite = bind_api(
416
        path = '/favorites/create.json',
417
        method = 'POST',
418
        payload_type = 'status',
419
420
421
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
422

423
    """ favorites/destroy """
424
    destroy_favorite = bind_api(
425
426
        path = '/favorites/destroy.json',
        method = 'POST',
427
        payload_type = 'status',
428
429
430
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
431

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

441
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
442
443
444
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
445
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
446
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
447
448
449
        require_auth = True
    )

450
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
451
    blocks = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
452
        path = '/blocks/list.json',
453
        payload_type = 'user', payload_list = True,
454
        allowed_param = ['cursor'],
Josh Roesslein's avatar
Josh Roesslein committed
455
456
457
        require_auth = True
    )

458
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
459
    blocks_ids = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
460
        path = '/blocks/ids.json',
461
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
462
463
464
        require_auth = True
    )

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

474
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
475
    saved_searches = bind_api(
476
        path = '/saved_searches/list.json',
477
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
478
479
480
        require_auth = True
    )

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

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

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

507
508
509
510
511
512
513
    create_list = bind_api(
        path = '/lists/create.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['name', 'mode', 'description'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
514

515
516
517
518
519
520
521
    destroy_list = bind_api(
        path = '/lists/destroy.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['owner_screen_name', 'owner_id', 'list_id', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
522

523
524
525
526
527
528
529
    update_list = bind_api(
        path = '/lists/update.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['list_id', 'slug', 'name', 'mode', 'description', 'owner_screen_name', 'owner_id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
530

531
532
    lists_all = bind_api(
        path = '/lists/list.json',
533
        payload_type = 'list', payload_list = True,
534
        allowed_param = ['screen_name', 'user_id'],
535
536
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
537

538
    lists_memberships = bind_api(
539
        path = '/lists/memberships.json',
540
        payload_type = 'list', payload_list = True,
541
        allowed_param = ['screen_name', 'user_id', 'filter_to_owned_lists', 'cursor'],
542
543
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
544

545
    lists_subscriptions = bind_api(
546
        path = '/lists/subscriptions.json',
547
        payload_type = 'list', payload_list = True,
548
        allowed_param = ['screen_name', 'user_id', 'cursor'],
549
550
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
551

552
    list_timeline = bind_api(
553
        path = '/lists/statuses.json',
554
        payload_type = 'status', payload_list = True,
555
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id', 'since_id', 'max_id', 'count', 'include_rts']
556
    )
Josh Roesslein's avatar
Josh Roesslein committed
557

558
    get_list = bind_api(
559
        path = '/lists/show.json',
560
        payload_type = 'list',
561
        allowed_param = ['owner_screen_name', 'owner_id', 'slug', 'list_id']
562
    )
Josh Roesslein's avatar
Josh Roesslein committed
563

564
565
566
567
568
569
570
    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
571

572
573
574
575
576
577
578
    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
579

580
    list_members = bind_api(
581
        path = '/lists/members.json',
582
        payload_type = 'user', payload_list = True,
583
        allowed_param = ['owner_screen_name', 'slug', 'list_id', 'owner_id', 'cursor']
584
    )
Josh Roesslein's avatar
Josh Roesslein committed
585

586
587
588
589
590
    show_list_member = bind_api(
        path = '/lists/members/show.json',
        payload_type = 'user',
        allowed_param = ['list_id', 'slug', 'user_id', 'screen_name', 'owner_screen_name', 'owner_id']
    )
Josh Roesslein's avatar
Josh Roesslein committed
591

592
    subscribe_list = bind_api(
593
        path = '/lists/subscribers/create.json',
594
        method = 'POST',
595
        payload_type = 'list',
596
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id'],
597
598
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
599

600
    unsubscribe_list = bind_api(
601
602
        path = '/lists/subscribers/destroy.json',
        method = 'POST',
603
        payload_type = 'list',
604
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id'],
605
606
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
607

608
    list_subscribers = bind_api(
609
        path = '/lists/subscribers.json',
610
        payload_type = 'user', payload_list = True,
611
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id', 'cursor']
612
    )
Josh Roesslein's avatar
Josh Roesslein committed
613

614
615
616
617
618
    show_list_subscriber = bind_api(
        path = '/lists/subscribers/show.json',
        payload_type = 'user',
        allowed_param = ['owner_screen_name', 'slug', 'screen_name', 'owner_id', 'list_id', 'user_id']
    )
Josh Roesslein's avatar
Josh Roesslein committed
619

620
    """ trends/available """
621
622
    trends_available = bind_api(
        path = '/trends/available.json',
623
624
625
626
627
        payload_type = 'json'
    )

    trends_place = bind_api(
        path = '/trends/place.json',
628
        payload_type = 'json',
629
        allowed_param = ['id', 'exclude']
630
631
    )

632
633
    trends_closest = bind_api(
        path = '/trends/closest.json',
634
        payload_type = 'json',
635
        allowed_param = ['lat', 'long']
636
    )
637

638
    """ search """
639
    search = bind_api(
640
641
        path = '/search/tweets.json',
        payload_type = 'search_results',
642
        allowed_param = ['q', 'lang', 'locale', 'since_id', 'geocode', 'max_id', 'since', 'until', 'result_type', 'count', 'include_entities', 'from', 'to', 'source']
643
    )
Josh Roesslein's avatar
Josh Roesslein committed
644

645
    """ trends/daily """
646
647
    trends_daily = bind_api(
        path = '/trends/daily.json',
648
        payload_type = 'json',
649
650
        allowed_param = ['date', 'exclude']
    )
651

652
    """ trends/weekly """
653
654
    trends_weekly = bind_api(
        path = '/trends/weekly.json',
655
        payload_type = 'json',
656
657
        allowed_param = ['date', 'exclude']
    )
658

659
660
661
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
662
        payload_type = 'place', payload_list = True,
663
664
665
666
667
668
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

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

673
674
675
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
676
        payload_type = 'place', payload_list = True,
677
678
679
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

680
681
682
683
684
685
686
    """ 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']
    )

687
688
689
690
691
    """ help/languages.json """
    supported_languages = bind_api(
        path = '/help/languages.json',
        payload_type = 'json',
        require_auth = True
692
    )
Joshua Roesslein's avatar
Joshua Roesslein committed
693

694
    """ help/configuration """
695
696
697
    configuration = bind_api(
        path = '/help/configuration.json',
        payload_type = 'json',
698
        require_auth = True
699
700
    )

701
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
702
    @staticmethod
703
    def _pack_image(filename, max_size, form_field="image"):
Josh Roesslein's avatar
Josh Roesslein committed
704
705
706
707
708
        """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.')
709
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
            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)
725
        body.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (form_field, filename))
Josh Roesslein's avatar
Josh Roesslein committed
726
727
728
729
730
731
732
733
734
735
736
        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',
737
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
738
739
740
        }

        return headers, body
741