api.py 24.4 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
19
    def __init__(self, auth_handler=None,
            host='api.twitter.com', search_host='search.twitter.com',
             cache=None, secure=False, api_root='/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/friends_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
43
44
    friends_timeline = bind_api(
        path = '/statuses/friends_timeline.json',
45
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
46
47
48
49
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

50
    """ statuses/user_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
51
52
    user_timeline = bind_api(
        path = '/statuses/user_timeline.json',
53
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
54
        allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
55
                          'max_id', 'count', 'page', 'include_rts']
Josh Roesslein's avatar
Josh Roesslein committed
56
57
    )

58
    """ statuses/mentions """
Josh Roesslein's avatar
Josh Roesslein committed
59
60
    mentions = bind_api(
        path = '/statuses/mentions.json',
61
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
62
63
64
65
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

66
67
68
69
70
71
72
73
    """/statuses/retweeted_by_user.format"""
    retweeted_by_user = bind_api(
        path = '/statuses/retweeted_by_user.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['screen_name', 'id', 'count', 'since_id',
                            'max_id', 'page', 'include_entities']
    )

74
75
76
77
78
79
80
    """/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
    )
81

Aaron Swartz's avatar
Aaron Swartz committed
82
83
84
85
86
87
88
    """/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
	)
89
90
91
92
93
94
95
96
97

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

Ferenc Szalai's avatar
Ferenc Szalai committed
98
    """ statuses/retweeted_by_me """
Josh Roesslein's avatar
Josh Roesslein committed
99
100
    retweeted_by_me = bind_api(
        path = '/statuses/retweeted_by_me.json',
101
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
102
103
104
105
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

106
    """ statuses/retweeted_to_me """
Josh Roesslein's avatar
Josh Roesslein committed
107
108
    retweeted_to_me = bind_api(
        path = '/statuses/retweeted_to_me.json',
109
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
110
111
112
113
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

Alejandro Gómez's avatar
Alejandro Gómez committed
114
115
116
117
118
119
120
121
    """ statuses/retweeted_by_user """
    retweeted_by_user = bind_api(
        path = '/statuses/retweeted_by_user.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['screen_name', 'id', 'since_id', 'max_id', 'count', 'page', 'trim_user', 'include_entities'],
        require_auth = False
    )

122
    """ statuses/retweets_of_me """
Josh Roesslein's avatar
Josh Roesslein committed
123
124
    retweets_of_me = bind_api(
        path = '/statuses/retweets_of_me.json',
125
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
126
127
128
129
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

130
    """ statuses/show """
Josh Roesslein's avatar
Josh Roesslein committed
131
132
    get_status = bind_api(
        path = '/statuses/show.json',
133
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
134
135
136
        allowed_param = ['id']
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
137
    """ statuses/update """
Josh Roesslein's avatar
Josh Roesslein committed
138
139
140
    update_status = bind_api(
        path = '/statuses/update.json',
        method = 'POST',
141
        payload_type = 'status',
142
        allowed_param = ['status', 'in_reply_to_status_id', 'lat', 'long', 'source', 'place_id'],
Josh Roesslein's avatar
Josh Roesslein committed
143
144
145
        require_auth = True
    )

146
    """ statuses/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
147
148
149
    destroy_status = bind_api(
        path = '/statuses/destroy.json',
        method = 'DELETE',
150
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
151
152
153
154
        allowed_param = ['id'],
        require_auth = True
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
155
    """ statuses/retweet """
156
157
158
    retweet = bind_api(
        path = '/statuses/retweet/{id}.json',
        method = 'POST',
159
        payload_type = 'status',
160
161
162
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
163

Ferenc Szalai's avatar
Ferenc Szalai committed
164
    """ statuses/retweets """
165
166
    retweets = bind_api(
        path = '/statuses/retweets/{id}.json',
167
        payload_type = 'status', payload_list = True,
168
169
170
        allowed_param = ['id', 'count'],
        require_auth = True
    )
171

172
    """ users/show """
Josh Roesslein's avatar
Josh Roesslein committed
173
174
    get_user = bind_api(
        path = '/users/show.json',
175
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
176
177
178
        allowed_param = ['id', 'user_id', 'screen_name']
    )

179
180
181
182
183
184
185
186
187
188
    """ 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'],
    )

189
    """ Get the authenticated user """
Josh Roesslein's avatar
Josh Roesslein committed
190
    def me(self):
Josh Roesslein's avatar
Josh Roesslein committed
191
        return self.get_user(screen_name=self.auth.get_username())
Josh Roesslein's avatar
Josh Roesslein committed
192

193
194
195
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
196
        payload_type = 'user', payload_list = True,
197
198
199
200
        require_auth = True,
        allowed_param = ['q', 'per_page', 'page']
    )

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    """ 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
    )

225
    """ statuses/friends """
Josh Roesslein's avatar
Josh Roesslein committed
226
227
    friends = bind_api(
        path = '/statuses/friends.json',
228
        payload_type = 'user', payload_list = True,
229
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
230
231
    )

232
    """ statuses/followers """
Josh Roesslein's avatar
Josh Roesslein committed
233
234
    followers = bind_api(
        path = '/statuses/followers.json',
235
        payload_type = 'user', payload_list = True,
236
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
237
238
    )

239
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
240
241
    direct_messages = bind_api(
        path = '/direct_messages.json',
242
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
243
244
245
246
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

247
248
249
250
251
252
253
254
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

255
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
256
257
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
258
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
259
260
261
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
262

263
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
264
265
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
266
        method = 'POST',
267
        payload_type = 'direct_message',
268
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
269
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
270
    )
271

272
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
273
274
275
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
276
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
277
278
279
280
        allowed_param = ['id'],
        require_auth = True
    )

281
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
282
283
    create_friendship = bind_api(
        path = '/friendships/create.json',
284
        method = 'POST',
285
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
286
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
287
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
288
289
    )

290
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
291
292
293
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
294
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
295
296
297
298
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

299
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
300
301
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
302
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
303
304
305
        allowed_param = ['user_a', 'user_b']
    )

306
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
307
308
    show_friendship = bind_api(
        path = '/friendships/show.json',
309
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
310
311
312
313
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

314
315
316
317
318
319
320
321
322
323
324
325
326

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


327
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
328
329
    friends_ids = bind_api(
        path = '/friends/ids.json',
330
        payload_type = 'ids',
331
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
332
333
    )

334
335
336
337
338
339
340
341
342
343
344
345
346
347
    """ 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']
    )

348
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
349
350
    followers_ids = bind_api(
        path = '/followers/ids.json',
351
        payload_type = 'ids',
352
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
353
354
    )

355
    """ account/verify_credentials """
356
    def verify_credentials(self, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
357
358
359
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
360
                payload_type = 'user',
361
362
363
                require_auth = True,
                allowed_param = ['include_entities', 'skip_status'],
            )(self, **kargs)
364
365
366
367
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
368

369
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
370
371
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
372
373
        payload_type = 'json',
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
374
375
    )

376
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
377
378
379
380
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
381
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
382
383
384
        require_auth = True
    )

385
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
386
387
388
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
389
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
390
391
392
393
394
395
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

396
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
397
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
398
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
399
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
400
401
            path = '/account/update_profile_image.json',
            method = 'POST',
402
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
403
404
405
            require_auth = True
        )(self, post_data=post_data, headers=headers)

406
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
407
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
408
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
409
410
411
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
412
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
413
414
415
416
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

417
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
418
419
420
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
421
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
422
        allowed_param = ['name', 'url', 'location', 'description'],
423
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
424
425
    )

426
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
427
428
    favorites = bind_api(
        path = '/favorites.json',
429
        payload_type = 'status', payload_list = True,
430
        allowed_param = ['id', 'max_id', 'page']
Josh Roesslein's avatar
Josh Roesslein committed
431
432
    )

433
    """ favorites/create """
434
435
436
    create_favorite = bind_api(
        path = '/favorites/create/{id}.json',
        method = 'POST',
437
        payload_type = 'status',
438
439
440
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
441

442
    """ favorites/destroy """
443
444
445
    destroy_favorite = bind_api(
        path = '/favorites/destroy/{id}.json',
        method = 'DELETE',
446
        payload_type = 'status',
447
448
449
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
450

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

460
    """ notifications/leave """
Josh Roesslein's avatar
Josh Roesslein committed
461
462
463
    disable_notifications = bind_api(
        path = '/notifications/leave.json',
        method = 'POST',
464
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
465
466
467
468
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

469
    """ blocks/create """
Josh Roesslein's avatar
Josh Roesslein committed
470
471
472
    create_block = bind_api(
        path = '/blocks/create.json',
        method = 'POST',
473
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
474
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
475
476
477
        require_auth = True
    )

478
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
479
480
481
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
482
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
483
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
484
485
486
        require_auth = True
    )

487
    """ blocks/exists """
Josh Roesslein's avatar
Josh Roesslein committed
488
    def exists_block(self, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
489
490
491
492
493
        try:
            bind_api(
                path = '/blocks/exists.json',
                allowed_param = ['id', 'user_id', 'screen_name'],
                require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
494
            )(self, *args, **kargs)
Josh Roesslein's avatar
Josh Roesslein committed
495
496
497
498
        except TweepError:
            return False
        return True

499
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
500
501
    blocks = bind_api(
        path = '/blocks/blocking.json',
502
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
503
504
505
506
        allowed_param = ['page'],
        require_auth = True
    )

507
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
508
509
    blocks_ids = bind_api(
        path = '/blocks/blocking/ids.json',
510
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
511
512
513
        require_auth = True
    )

514
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
515
516
517
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
518
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
519
520
521
522
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

523
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
524
525
    saved_searches = bind_api(
        path = '/saved_searches.json',
526
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
527
528
529
        require_auth = True
    )

530
    """ saved_searches/show """
531
532
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
533
        payload_type = 'saved_search',
534
535
536
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
537

538
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
539
540
541
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
542
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
543
544
545
546
        allowed_param = ['query'],
        require_auth = True
    )

547
    """ saved_searches/destroy """
548
549
550
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
551
        payload_type = 'saved_search',
552
553
554
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
555

556
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
557
    def test(self):
558
        try:
559
            bind_api(
560
561
562
563
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
564
        return True
565

Josh Roesslein's avatar
Josh Roesslein committed
566
567
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
568
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
569
            method = 'POST',
570
            payload_type = 'list',
571
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
572
573
574
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
575
576
577
578
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
579
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
580
581
582
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
583
584
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
585
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
586
            method = 'POST',
587
            payload_type = 'list',
588
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
589
590
591
            require_auth = True
        )(self, *args, **kargs)

592
593
    lists = bind_api(
        path = '/{user}/lists.json',
594
        payload_type = 'list', payload_list = True,
595
596
597
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
598

599
600
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
601
        payload_type = 'list', payload_list = True,
602
603
604
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
605

606
607
    lists_subscriptions = bind_api(
        path = '/{user}/lists/subscriptions.json',
608
        payload_type = 'list', payload_list = True,
609
610
611
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
612

613
614
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
615
        payload_type = 'status', payload_list = True,
616
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
617
    )
Josh Roesslein's avatar
Josh Roesslein committed
618

619
620
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
621
        payload_type = 'list',
622
623
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
624
625
626
627
628

    def add_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'POST',
629
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
630
631
632
633
634
635
636
637
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

    def remove_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
638
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
639
640
641
642
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

643
644
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
645
        payload_type = 'user', payload_list = True,
646
647
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
648
649
650
651
652

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
653
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
654
655
656
657
            )(self)
        except TweepError:
            return False

658
659
660
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
661
        payload_type = 'list',
662
663
664
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
665

666
667
668
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
669
        payload_type = 'list',
670
671
672
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
673

674
675
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
676
        payload_type = 'user', payload_list = True,
677
678
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
679
680
681
682
683

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
684
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
685
686
687
688
            )(self)
        except TweepError:
            return False

689
    """ trends/available """
690
691
    trends_available = bind_api(
        path = '/trends/available.json',
692
        payload_type = 'json',
693
694
695
        allowed_param = ['lat', 'long']
    )

696
    """ trends/location """
697
698
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
699
        payload_type = 'json',
700
701
        allowed_param = ['woeid']
    )
702

703
    """ search """
704
705
706
    search = bind_api(
        search_api = True,
        path = '/search.json',
707
        payload_type = 'search_result', payload_list = True,
708
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
709
    )
710
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
711

712
    """ trends/daily """
713
714
    trends_daily = bind_api(
        path = '/trends/daily.json',
715
        payload_type = 'json',
716
717
        allowed_param = ['date', 'exclude']
    )
718

719
    """ trends/weekly """
720
721
    trends_weekly = bind_api(
        path = '/trends/weekly.json',
722
        payload_type = 'json',
723
724
        allowed_param = ['date', 'exclude']
    )
725

726
727
728
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
729
        payload_type = 'place', payload_list = True,
730
731
732
733
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/nearby_places """
734
    # listed as deprecated on twitter's API documents
735
736
    nearby_places = bind_api(
        path = '/geo/nearby_places.json',
737
        payload_type = 'place', payload_list = True,
738
739
740
741
742
743
        allowed_param = ['lat', 'long', 'ip', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/id """
    geo_id = bind_api(
        path = '/geo/id/{id}.json',
744
        payload_type = 'place',
745
746
747
        allowed_param = ['id']
    )

748
749
750
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
751
        payload_type = 'place', payload_list = True,
752
753
754
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

755
756
757
758
759
760
761
    """ 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']
    )

762
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
763
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
764
765
766
767
768
769
    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.')
770
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
            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',
798
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
799
800
801
        }

        return headers, body
802