api.py 21.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):
Josh Roesslein's avatar
Josh Roesslein committed
22
        self.auth = auth_handler
Josh Roesslein's avatar
Josh Roesslein committed
23
        self.host = host
24
        self.search_host = search_host
Josh Roesslein's avatar
Josh Roesslein committed
25
        self.api_root = api_root
26
        self.search_root = search_root
Josh Roesslein's avatar
Josh Roesslein committed
27
28
        self.cache = cache
        self.secure = secure
29
30
        self.retry_count = retry_count
        self.retry_delay = retry_delay
31
        self.retry_errors = retry_errors
32
        self.timeout = timeout
33
        self.parser = parser or ModelParser()
Josh Roesslein's avatar
Josh Roesslein committed
34

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

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

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

59
60
61
62
63
64
65
    """/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
    )
66

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

    """/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
    )

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

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

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

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

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

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

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

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

147
148
149
150
151
152
153
154
155
156
    """ Perform bulk look up of users from user ID or screenname """
    def lookup_users(self, user_ids=None, screen_names=None):
        return self._lookup_users(list_to_csv(user_ids), list_to_csv(screen_names))

    _lookup_users = bind_api(
        path = '/users/lookup.json',
        payload_type = 'user', payload_list = True,
        allowed_param = ['user_id', 'screen_name'],
    )

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

628
    """ search """
629
630
631
    search = bind_api(
        search_api = True,
        path = '/search.json',
632
        payload_type = 'search_result', payload_list = True,
633
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
634
    )
635
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
636

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

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

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

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

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

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

679
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
680
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
681
682
683
684
685
686
    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.')
687
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
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
714
            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',
715
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
716
717
718
        }

        return headers, body
719