api.py 24 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/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/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
488
    blocks = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
489
        path = '/blocks/list.json',
490
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
491
492
493
494
        allowed_param = ['page'],
        require_auth = True
    )

495
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
496
    blocks_ids = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
497
        path = '/blocks/ids.json',
498
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
499
500
501
        require_auth = True
    )

502
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
503
504
505
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
506
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
507
508
509
510
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

511
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
512
513
    saved_searches = bind_api(
        path = '/saved_searches.json',
514
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
515
516
517
        require_auth = True
    )

518
    """ saved_searches/show """
519
520
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
521
        payload_type = 'saved_search',
522
523
524
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
525

526
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
527
528
529
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
530
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
531
532
533
534
        allowed_param = ['query'],
        require_auth = True
    )

535
    """ saved_searches/destroy """
536
537
538
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
539
        payload_type = 'saved_search',
540
541
542
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
543

544
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
545
    def test(self):
546
        try:
547
            bind_api(
548
549
550
551
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
552
        return True
553

Josh Roesslein's avatar
Josh Roesslein committed
554
555
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
556
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
557
            method = 'POST',
558
            payload_type = 'list',
559
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
560
561
562
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
563
564
565
566
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
567
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
568
569
570
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
571
572
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
573
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
574
            method = 'POST',
575
            payload_type = 'list',
576
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
577
578
579
            require_auth = True
        )(self, *args, **kargs)

580
581
    lists = bind_api(
        path = '/{user}/lists.json',
582
        payload_type = 'list', payload_list = True,
583
584
585
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
586

587
588
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
589
        payload_type = 'list', payload_list = True,
590
591
592
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
593

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

601
602
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
603
        payload_type = 'status', payload_list = True,
604
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
605
    )
Josh Roesslein's avatar
Josh Roesslein committed
606

607
608
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
609
        payload_type = 'list',
610
611
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
612

613
614
615
616
617
618
619
    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
620

621
622
623
624
625
626
627
    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
628

629
630
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
631
        payload_type = 'user', payload_list = True,
632
633
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
634
635
636
637
638

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
639
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
640
641
642
643
            )(self)
        except TweepError:
            return False

644
645
646
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
647
        payload_type = 'list',
648
649
650
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
651

652
653
654
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
655
        payload_type = 'list',
656
657
658
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
659

660
661
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
662
        payload_type = 'user', payload_list = True,
663
664
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
665
666
667
668
669

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
670
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
671
672
673
674
            )(self)
        except TweepError:
            return False

675
    """ trends/available """
676
677
    trends_available = bind_api(
        path = '/trends/available.json',
678
        payload_type = 'json',
679
680
681
        allowed_param = ['lat', 'long']
    )

682
    """ trends/location """
683
684
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
685
        payload_type = 'json',
686
687
        allowed_param = ['woeid']
    )
688

689
    """ search """
690
691
692
    search = bind_api(
        search_api = True,
        path = '/search.json',
693
        payload_type = 'search_result', payload_list = True,
694
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
695
    )
696
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
697

698
    """ trends/daily """
699
700
    trends_daily = bind_api(
        path = '/trends/daily.json',
701
        payload_type = 'json',
702
703
        allowed_param = ['date', 'exclude']
    )
704

705
    """ trends/weekly """
706
707
    trends_weekly = bind_api(
        path = '/trends/weekly.json',
708
        payload_type = 'json',
709
710
        allowed_param = ['date', 'exclude']
    )
711

712
713
714
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
715
        payload_type = 'place', payload_list = True,
716
717
718
719
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/nearby_places """
720
    # listed as deprecated on twitter's API documents
721
722
    nearby_places = bind_api(
        path = '/geo/nearby_places.json',
723
        payload_type = 'place', payload_list = True,
724
725
726
727
728
729
        allowed_param = ['lat', 'long', 'ip', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/id """
    geo_id = bind_api(
        path = '/geo/id/{id}.json',
730
        payload_type = 'place',
731
732
733
        allowed_param = ['id']
    )

734
735
736
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
737
        payload_type = 'place', payload_list = True,
738
739
740
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

741
742
743
744
745
746
747
    """ 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']
    )

748
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
749
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
750
751
752
753
754
755
    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.')
756
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
            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',
784
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
785
786
787
        }

        return headers, body
788