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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

252
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
253
254
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
255
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
256
257
258
        allowed_param = ['user_a', 'user_b']
    )

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

267
268
269
270
271
272
273
274
275
276
277
278
279

    """ Perform bulk look up of friendships from user ID or screenname """
    def lookup_friendships(self, user_ids=None, screen_names=None):
	    return self._lookup_friendships(list_to_csv(user_ids), list_to_csv(screen_names))

    _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
291
292
293
    """ friends/list """
    friends = bind_api(
        path = '/friends/list.json',
        payload_type = 'user', payload_list = True,
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
    )

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
319
320
321
    """ followers/list """
    followers = bind_api(
        path = '/followers/list.json',
        payload_type = 'user', payload_list = True,
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
    )

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

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

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

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

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

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

385
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
386
387
388
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
389
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
390
        allowed_param = ['name', 'url', 'location', 'description'],
391
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
392
393
    )

394
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
395
    favorites = bind_api(
396
        path = '/favorites/list.json',
397
        payload_type = 'status', payload_list = True,
398
        allowed_param = ['screen_name', 'user_id', 'max_id', 'count', 'since_id', 'max_id']
Josh Roesslein's avatar
Josh Roesslein committed
399
400
    )

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

410
    """ favorites/destroy """
411
    destroy_favorite = bind_api(
412
413
        path = '/favorites/destroy.json',
        method = 'POST',
414
        payload_type = 'status',
415
416
417
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
418

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

428
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
429
430
431
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
432
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
433
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
434
435
436
        require_auth = True
    )

437
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
438
    blocks = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
439
        path = '/blocks/list.json',
440
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
441
442
443
444
        allowed_param = ['page'],
        require_auth = True
    )

445
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
446
    blocks_ids = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
447
        path = '/blocks/ids.json',
448
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
449
450
451
        require_auth = True
    )

452
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
453
    report_spam = bind_api(
454
        path = '/users/report_spam.json',
Josh Roesslein's avatar
Josh Roesslein committed
455
        method = 'POST',
456
        payload_type = 'user',
457
        allowed_param = ['user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
458
459
460
        require_auth = True
    )

461
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
462
    saved_searches = bind_api(
463
        path = '/saved_searches/list.json',
464
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
465
466
467
        require_auth = True
    )

468
    """ saved_searches/show """
469
470
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
471
        payload_type = 'saved_search',
472
473
474
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
475

476
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
477
478
479
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
480
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
481
482
483
484
        allowed_param = ['query'],
        require_auth = True
    )

485
    """ saved_searches/destroy """
486
487
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
488
        method = 'POST',
489
        payload_type = 'saved_search',
490
491
492
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
493

494
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
495
    def test(self):
496
        try:
497
            bind_api(
498
499
500
501
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
502
        return True
503

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

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

520
521
522
523
524
525
526
    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
527

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

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

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

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

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

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

569
570
571
572
573
574
575
    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
576

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

583
584
585
586
587
    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
588

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

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

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

611
612
613
614
615
    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
616

617
    """ trends/available """
618
619
    trends_available = bind_api(
        path = '/trends/available.json',
620
621
622
623
624
        payload_type = 'json'
    )

    trends_place = bind_api(
        path = '/trends/place.json',
625
        payload_type = 'json',
626
        allowed_param = ['id', 'exclude']
627
628
    )

629
630
    trends_closest = bind_api(
        path = '/trends/closest.json',
631
        payload_type = 'json',
632
        allowed_param = ['lat', 'long']
633
    )
634

635
    """ search """
636
637
638
    search = bind_api(
        search_api = True,
        path = '/search.json',
639
        payload_type = 'search_result', payload_list = True,
640
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
641
    )
642
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
643

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

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

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

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

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

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

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

        return headers, body
726