api.py 24.3 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,
Mike's avatar
Mike committed
21
            parser=None, compression=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.parser = parser or ModelParser()
Josh Roesslein's avatar
Josh Roesslein committed
35

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

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

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

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

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

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

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

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    """ 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)

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

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

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

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

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

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

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

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

168
169
170
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
171
        payload_type = 'user', payload_list = True,
172
        require_auth = True,
173
        allowed_param = ['q', 'count', 'page']
174
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
    """ 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
    )

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

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

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

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

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

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

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

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

268
269
    """ 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
270
        return self._lookup_friendships(list_to_csv(user_ids), list_to_csv(screen_names))
271
272
273
274
275
276
277
278
279

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


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

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

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

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

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

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

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

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

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

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

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

386
387
388
389
390
391
392
393
394
395
396
    """ 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)


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

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

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

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

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

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

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

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

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

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

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

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

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

506
507
508
509
510
511
512
    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
513

514
515
516
517
518
519
520
    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
521

522
523
524
525
526
527
528
    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
529

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

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

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

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

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

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

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

579
580
581
582
583
584
585
586
587
    """ Perform bulk add of list members from user ID or screenname """
    def add_list_members(self, screen_names=None, user_ids=None, slug=None,
                         list_id=None, owner_id=None, owner_screen_name=None):
        return self._add_list_members(list_to_csv(screen_names),
                                      list_to_csv(user_ids),
                                      slug, list_id, owner_id,
                                      owner_screen_name)

    _add_list_members = bind_api(
588
589
590
        path = '/lists/members/create_all.json',
        method = 'POST',
        payload_type = 'list',
591
        allowed_param = ['screen_name', 'user_id', 'slug', 'lit_id', 'owner_id', 'owner_screen_name'],
592
593
594
        require_auth = True
    )

595
596
597
598
599
600
601
602
603
    """ Perform bulk remove of list members from user ID or screenname """
    def remove_list_members(self, screen_names=None, user_ids=None, slug=None,
                         list_id=None, owner_id=None, owner_screen_name=None):
        return self._remove_list_members(list_to_csv(screen_names),
                                      list_to_csv(user_ids),
                                      slug, list_id, owner_id,
                                      owner_screen_name)

    _remove_list_members = bind_api(
604
605
606
        path = '/lists/members/destroy_all.json',
        method = 'POST',
        payload_type = 'list',
607
        allowed_param = ['screen_name', 'user_id', 'slug', 'lit_id', 'owner_id', 'owner_screen_name'],
608
609
610
        require_auth = True
    )

611
    list_members = bind_api(
612
        path = '/lists/members.json',
613
        payload_type = 'user', payload_list = True,
614
        allowed_param = ['owner_screen_name', 'slug', 'list_id', 'owner_id', 'cursor']
615
    )
Josh Roesslein's avatar
Josh Roesslein committed
616

617
618
619
620
621
    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
622

623
    subscribe_list = bind_api(
624
        path = '/lists/subscribers/create.json',
625
        method = 'POST',
626
        payload_type = 'list',
627
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id'],
628
629
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
630

631
    unsubscribe_list = bind_api(
632
633
        path = '/lists/subscribers/destroy.json',
        method = 'POST',
634
        payload_type = 'list',
635
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id'],
636
637
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
638

639
    list_subscribers = bind_api(
640
        path = '/lists/subscribers.json',
641
        payload_type = 'user', payload_list = True,
642
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id', 'cursor']
643
    )
Josh Roesslein's avatar
Josh Roesslein committed
644

645
646
647
648
649
    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
650

651
    """ trends/available """
652
653
    trends_available = bind_api(
        path = '/trends/available.json',
654
655
656
657
658
        payload_type = 'json'
    )

    trends_place = bind_api(
        path = '/trends/place.json',
659
        payload_type = 'json',
660
        allowed_param = ['id', 'exclude']
661
662
    )

663
664
    trends_closest = bind_api(
        path = '/trends/closest.json',
665
        payload_type = 'json',
666
        allowed_param = ['lat', 'long']
667
    )
668

669
    """ search """
670
    search = bind_api(
671
672
        path = '/search/tweets.json',
        payload_type = 'search_results',
673
        allowed_param = ['q', 'lang', 'locale', 'since_id', 'geocode', 'max_id', 'since', 'until', 'result_type', 'count', 'include_entities', 'from', 'to', 'source']
674
    )
Josh Roesslein's avatar
Josh Roesslein committed
675

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

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

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

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

704
705
706
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
707
        payload_type = 'place', payload_list = True,
708
709
710
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

711
712
713
714
715
716
717
    """ 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']
    )

718
719
720
721
722
    """ help/languages.json """
    supported_languages = bind_api(
        path = '/help/languages.json',
        payload_type = 'json',
        require_auth = True
723
    )
Joshua Roesslein's avatar
Joshua Roesslein committed
724

725
    """ help/configuration """
726
727
728
    configuration = bind_api(
        path = '/help/configuration.json',
        payload_type = 'json',
729
        require_auth = True
730
731
    )

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

        return headers, body
772