api.py 21.8 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
    )

60
61
62
63
64
65
66
    """/statuses/:id/retweeted_by.format"""
    retweeted_by = bind_api(
        path = '/statuses/{id}/retweeted_by.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['id', 'count', 'page'],
        require_auth = True
    )
67

Aaron Swartz's avatar
Aaron Swartz committed
68
69
70
71
72
73
    """/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
74
    )
75
76
77
78
79
80
81
82
83

    """/statuses/:id/retweeted_by/ids.format"""
    retweeted_by_ids = bind_api(
        path = '/statuses/{id}/retweeted_by/ids.json',
        payload_type = 'ids',
        allowed_param = ['id', 'count', 'page'],
        require_auth = True
    )

84
    """ statuses/retweets_of_me """
Josh Roesslein's avatar
Josh Roesslein committed
85
86
    retweets_of_me = bind_api(
        path = '/statuses/retweets_of_me.json',
87
        payload_type = 'status', payload_list = True,
88
        allowed_param = ['since_id', 'max_id', 'count'],
Josh Roesslein's avatar
Josh Roesslein committed
89
90
91
        require_auth = True
    )

92
    """ statuses/show """
Josh Roesslein's avatar
Josh Roesslein committed
93
94
    get_status = bind_api(
        path = '/statuses/show.json',
95
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
96
97
98
        allowed_param = ['id']
    )

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

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

134
    """ users/show """
Josh Roesslein's avatar
Josh Roesslein committed
135
136
    get_user = bind_api(
        path = '/users/show.json',
137
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
138
139
140
        allowed_param = ['id', 'user_id', 'screen_name']
    )

Miriam Sexton's avatar
Miriam Sexton committed
141
142
    ''' statuses/oembed '''
    get_oembed = bind_api(
Miriam Sexton's avatar
Miriam Sexton committed
143
        path = '/statuses/oembed.json',
Miriam Sexton's avatar
Miriam Sexton committed
144
145
146
147
        payload_type = 'json',
        allowed_param = ['id', 'url', 'maxwidth', 'hide_media', 'omit_script', 'align', 'related', 'lang']
    )

148
149
150
151
152
153
154
155
156
157
    """ 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'],
    )

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

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

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
    """ 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
    )

194
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
195
196
    direct_messages = bind_api(
        path = '/direct_messages.json',
197
        payload_type = 'direct_message', payload_list = True,
198
        allowed_param = ['since_id', 'max_id', 'count'],
Josh Roesslein's avatar
Josh Roesslein committed
199
200
201
        require_auth = True
    )

202
203
204
205
206
207
208
209
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

210
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
211
212
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
213
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
214
215
216
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
217

218
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
219
220
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
221
        method = 'POST',
222
        payload_type = 'direct_message',
223
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
224
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
225
    )
226

227
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
228
229
230
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
231
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
232
233
234
235
        allowed_param = ['id'],
        require_auth = True
    )

236
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
237
238
    create_friendship = bind_api(
        path = '/friendships/create.json',
239
        method = 'POST',
240
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
241
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
242
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
243
244
    )

245
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
246
247
248
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
249
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
250
251
252
253
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

254
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
255
256
    show_friendship = bind_api(
        path = '/friendships/show.json',
257
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
258
259
260
261
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

262
263
    """ 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
264
        return self._lookup_friendships(list_to_csv(user_ids), list_to_csv(screen_names))
265
266
267
268
269
270
271
272
273

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


274
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
275
276
    friends_ids = bind_api(
        path = '/friends/ids.json',
277
        payload_type = 'ids',
278
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
279
280
    )

281
282
283
284
    """ friends/list """
    friends = bind_api(
        path = '/friends/list.json',
        payload_type = 'user', payload_list = True,
285
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
286
287
    )

288
289
290
291
292
293
294
295
296
297
298
299
300
301
    """ 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']
    )

302
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
303
304
    followers_ids = bind_api(
        path = '/followers/ids.json',
305
        payload_type = 'ids',
306
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
307
308
    )

309
310
311
312
    """ followers/list """
    followers = bind_api(
        path = '/followers/list.json',
        payload_type = 'user', payload_list = True,
313
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
314
315
    )

316
    """ account/verify_credentials """
317
    def verify_credentials(self, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
318
319
320
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
321
                payload_type = 'user',
322
323
324
                require_auth = True,
                allowed_param = ['include_entities', 'skip_status'],
            )(self, **kargs)
325
326
327
328
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
329

330
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
331
    rate_limit_status = bind_api(
332
        path = '/application/rate_limit_status.json',
333
        payload_type = 'json',
334
        allowed_param = ['resources'],
335
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
336
337
    )

338
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
339
340
341
342
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
343
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
344
345
346
        require_auth = True
    )

347
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
348
349
350
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
351
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
352
353
354
355
356
357
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

358
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
359
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
360
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
361
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
362
363
            path = '/account/update_profile_image.json',
            method = 'POST',
364
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
365
366
367
            require_auth = True
        )(self, post_data=post_data, headers=headers)

368
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
369
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
370
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
371
372
373
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
374
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
375
376
377
378
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

379
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
380
381
382
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
383
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
384
        allowed_param = ['name', 'url', 'location', 'description'],
385
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
386
387
    )

388
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
389
    favorites = bind_api(
390
        path = '/favorites/list.json',
391
        payload_type = 'status', payload_list = True,
392
        allowed_param = ['screen_name', 'user_id', 'max_id', 'count', 'since_id', 'max_id']
Josh Roesslein's avatar
Josh Roesslein committed
393
394
    )

395
    """ favorites/create """
396
    create_favorite = bind_api(
397
        path = '/favorites/create.json',
398
        method = 'POST',
399
        payload_type = 'status',
400
401
402
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
403

404
    """ favorites/destroy """
405
    destroy_favorite = bind_api(
406
407
        path = '/favorites/destroy.json',
        method = 'POST',
408
        payload_type = 'status',
409
410
411
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
412

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

422
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
423
424
425
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
426
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
427
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
428
429
430
        require_auth = True
    )

431
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
432
    blocks = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
433
        path = '/blocks/list.json',
434
        payload_type = 'user', payload_list = True,
435
        allowed_param = ['cursor'],
Josh Roesslein's avatar
Josh Roesslein committed
436
437
438
        require_auth = True
    )

439
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
440
    blocks_ids = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
441
        path = '/blocks/ids.json',
442
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
443
444
445
        require_auth = True
    )

446
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
447
    report_spam = bind_api(
448
        path = '/users/report_spam.json',
Josh Roesslein's avatar
Josh Roesslein committed
449
        method = 'POST',
450
        payload_type = 'user',
451
        allowed_param = ['user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
452
453
454
        require_auth = True
    )

455
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
456
    saved_searches = bind_api(
457
        path = '/saved_searches/list.json',
458
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
459
460
461
        require_auth = True
    )

462
    """ saved_searches/show """
463
464
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
465
        payload_type = 'saved_search',
466
467
468
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
469

470
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
471
472
473
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
474
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
475
476
477
478
        allowed_param = ['query'],
        require_auth = True
    )

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

488
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
489
    def test(self):
490
        try:
491
            bind_api(
492
493
494
495
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
496
        return True
497

498
499
500
501
502
503
504
    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
505

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

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

522
523
    lists_all = bind_api(
        path = '/lists/list.json',
524
        payload_type = 'list', payload_list = True,
525
        allowed_param = ['screen_name', 'user_id'],
526
527
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
528

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

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

543
    list_timeline = bind_api(
544
        path = '/lists/statuses.json',
545
        payload_type = 'status', payload_list = True,
546
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id', 'since_id', 'max_id', 'count']
547
    )
Josh Roesslein's avatar
Josh Roesslein committed
548

549
    get_list = bind_api(
550
        path = '/lists/show.json',
551
        payload_type = 'list',
552
        allowed_param = ['owner_screen_name', 'owner_id', 'slug', 'list_id']
553
    )
Josh Roesslein's avatar
Josh Roesslein committed
554

555
556
557
558
559
560
561
    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
562

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

571
    list_members = bind_api(
572
        path = '/lists/members.json',
573
        payload_type = 'user', payload_list = True,
574
        allowed_param = ['owner_screen_name', 'slug', 'list_id', 'owner_id', 'cursor']
575
    )
Josh Roesslein's avatar
Josh Roesslein committed
576

577
578
579
580
581
    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
582

583
    subscribe_list = bind_api(
584
        path = '/lists/subscribers/create.json',
585
        method = 'POST',
586
        payload_type = 'list',
587
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id'],
588
589
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
590

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

599
    list_subscribers = bind_api(
600
        path = '/lists/subscribers.json',
601
        payload_type = 'user', payload_list = True,
602
        allowed_param = ['owner_screen_name', 'slug', 'owner_id', 'list_id', 'cursor']
603
    )
Josh Roesslein's avatar
Josh Roesslein committed
604

605
606
607
608
609
    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
610

611
    """ trends/available """
612
613
    trends_available = bind_api(
        path = '/trends/available.json',
614
615
616
617
618
        payload_type = 'json'
    )

    trends_place = bind_api(
        path = '/trends/place.json',
619
        payload_type = 'json',
620
        allowed_param = ['id', 'exclude']
621
622
    )

623
624
    trends_closest = bind_api(
        path = '/trends/closest.json',
625
        payload_type = 'json',
626
        allowed_param = ['lat', 'long']
627
    )
628

629
    """ search """
630
    search = bind_api(
631
632
633
        path = '/search/tweets.json',
        payload_type = 'search_results',
        allowed_param = ['q', 'lang', 'locale', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
634
    )
Josh Roesslein's avatar
Josh Roesslein committed
635

636
    """ trends/daily """
637
638
    trends_daily = bind_api(
        path = '/trends/daily.json',
639
        payload_type = 'json',
640
641
        allowed_param = ['date', 'exclude']
    )
642

643
    """ trends/weekly """
644
645
    trends_weekly = bind_api(
        path = '/trends/weekly.json',
646
        payload_type = 'json',
647
648
        allowed_param = ['date', 'exclude']
    )
649

650
651
652
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
653
        payload_type = 'place', payload_list = True,
654
655
656
657
658
659
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/id """
    geo_id = bind_api(
        path = '/geo/id/{id}.json',
660
        payload_type = 'place',
661
662
663
        allowed_param = ['id']
    )

664
665
666
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
667
        payload_type = 'place', payload_list = True,
668
669
670
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

671
672
673
674
675
676
677
    """ 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']
    )

678
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
679
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
680
681
682
683
684
685
    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.')
686
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
            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',
714
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
715
716
717
        }

        return headers, body
718