api.py 22.7 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, RawParser
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

34
    """ statuses/public_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
35
36
    public_timeline = bind_api(
        path = '/statuses/public_timeline.json',
37
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
38
39
40
        allowed_param = []
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
41
    """ statuses/home_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
42
43
    home_timeline = bind_api(
        path = '/statuses/home_timeline.json',
44
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
45
46
47
48
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

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

57
    """ statuses/user_timeline """
Josh Roesslein's avatar
Josh Roesslein committed
58
59
    user_timeline = bind_api(
        path = '/statuses/user_timeline.json',
60
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
61
        allowed_param = ['id', 'user_id', 'screen_name', 'since_id',
62
                          'max_id', 'count', 'page', 'include_rts']
Josh Roesslein's avatar
Josh Roesslein committed
63
64
    )

65
    """ statuses/mentions """
Josh Roesslein's avatar
Josh Roesslein committed
66
67
    mentions = bind_api(
        path = '/statuses/mentions.json',
68
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
69
70
71
72
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

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

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

    """/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
97
    """ statuses/retweeted_by_me """
Josh Roesslein's avatar
Josh Roesslein committed
98
99
    retweeted_by_me = bind_api(
        path = '/statuses/retweeted_by_me.json',
100
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
101
102
103
104
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

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

113
    """ statuses/retweets_of_me """
Josh Roesslein's avatar
Josh Roesslein committed
114
115
    retweets_of_me = bind_api(
        path = '/statuses/retweets_of_me.json',
116
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
117
118
119
120
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

121
    """ statuses/show """
Josh Roesslein's avatar
Josh Roesslein committed
122
123
    get_status = bind_api(
        path = '/statuses/show.json',
124
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
125
126
127
        allowed_param = ['id']
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
128
    """ statuses/update """
Josh Roesslein's avatar
Josh Roesslein committed
129
130
131
    update_status = bind_api(
        path = '/statuses/update.json',
        method = 'POST',
132
        payload_type = 'status',
133
        allowed_param = ['status', 'in_reply_to_status_id', 'lat', 'long', 'source', 'place_id'],
Josh Roesslein's avatar
Josh Roesslein committed
134
135
136
        require_auth = True
    )

137
    """ statuses/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
138
139
140
    destroy_status = bind_api(
        path = '/statuses/destroy.json',
        method = 'DELETE',
141
        payload_type = 'status',
Josh Roesslein's avatar
Josh Roesslein committed
142
143
144
145
        allowed_param = ['id'],
        require_auth = True
    )

Ferenc Szalai's avatar
Ferenc Szalai committed
146
    """ statuses/retweet """
147
148
149
    retweet = bind_api(
        path = '/statuses/retweet/{id}.json',
        method = 'POST',
150
        payload_type = 'status',
151
152
153
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
154

Ferenc Szalai's avatar
Ferenc Szalai committed
155
    """ statuses/retweets """
156
157
    retweets = bind_api(
        path = '/statuses/retweets/{id}.json',
158
        payload_type = 'status', payload_list = True,
159
160
161
        allowed_param = ['id', 'count'],
        require_auth = True
    )
162

163
    """ users/show """
Josh Roesslein's avatar
Josh Roesslein committed
164
165
    get_user = bind_api(
        path = '/users/show.json',
166
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
167
168
169
        allowed_param = ['id', 'user_id', 'screen_name']
    )

170
171
172
173
174
175
176
177
178
179
    """ 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'],
    )

180
    """ Get the authenticated user """
Josh Roesslein's avatar
Josh Roesslein committed
181
    def me(self):
Josh Roesslein's avatar
Josh Roesslein committed
182
        return self.get_user(screen_name=self.auth.get_username())
Josh Roesslein's avatar
Josh Roesslein committed
183

184
185
186
    """ users/search """
    search_users = bind_api(
        path = '/users/search.json',
187
        payload_type = 'user', payload_list = True,
188
189
190
191
        require_auth = True,
        allowed_param = ['q', 'per_page', 'page']
    )

192
    """ statuses/friends """
Josh Roesslein's avatar
Josh Roesslein committed
193
194
    friends = bind_api(
        path = '/statuses/friends.json',
195
        payload_type = 'user', payload_list = True,
196
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
197
198
    )

199
    """ statuses/followers """
Josh Roesslein's avatar
Josh Roesslein committed
200
201
    followers = bind_api(
        path = '/statuses/followers.json',
202
        payload_type = 'user', payload_list = True,
203
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
204
205
    )

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

214
215
216
217
218
219
220
221
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

222
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
223
224
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
225
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
226
227
228
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
229

230
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
231
232
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
233
        method = 'POST',
234
        payload_type = 'direct_message',
235
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
236
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
237
    )
238

239
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
240
241
242
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
243
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
244
245
246
247
        allowed_param = ['id'],
        require_auth = True
    )

248
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
249
250
    create_friendship = bind_api(
        path = '/friendships/create.json',
251
        method = 'POST',
252
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
253
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
254
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
255
256
    )

257
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
258
259
260
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
261
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
262
263
264
265
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

266
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
267
268
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
269
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
270
271
272
        allowed_param = ['user_a', 'user_b']
    )

273
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
274
275
    show_friendship = bind_api(
        path = '/friendships/show.json',
276
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
277
278
279
280
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

281
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
282
283
    friends_ids = bind_api(
        path = '/friends/ids.json',
284
        payload_type = 'ids',
285
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
286
287
    )

288
289
290
291
292
293
294
295
296
297
298
299
300
301
    """ friendships/incoming """
    friendships_incoming = bind_api(
        path = '/friendships/incoming.json',
        payload_type = 'ids',
        allowed_param = ['cursor']
    )

    """ friendships/outgoing"""
    friendships_outgoing = bind_api(
        path = '/friendships/outgoing.json',
        payload_type = 'ids',
        allowed_param = ['cursor']
    )

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

309
    """ account/verify_credentials """
Josh Roesslein's avatar
Josh Roesslein committed
310
311
312
313
    def verify_credentials(self):
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
314
                payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
315
316
                require_auth = True
            )(self)
317
318
319
320
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
321

322
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
323
324
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
325
326
        payload_type = 'json',
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
327
328
    )

329
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
330
331
332
333
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
334
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
335
336
337
        require_auth = True
    )

338
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
339
340
341
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
342
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
343
344
345
346
347
348
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

349
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
350
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
351
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
352
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
353
354
            path = '/account/update_profile_image.json',
            method = 'POST',
355
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
356
357
358
            require_auth = True
        )(self, post_data=post_data, headers=headers)

359
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
360
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
361
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
362
363
364
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
365
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
366
367
368
369
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

370
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
371
372
373
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
374
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
375
        allowed_param = ['name', 'url', 'location', 'description'],
376
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
377
378
    )

379
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
380
381
    favorites = bind_api(
        path = '/favorites.json',
382
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
383
384
385
        allowed_param = ['id', 'page']
    )

386
    """ favorites/create """
387
388
389
    create_favorite = bind_api(
        path = '/favorites/create/{id}.json',
        method = 'POST',
390
        payload_type = 'status',
391
392
393
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
394

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

404
    """ notifications/follow """
Josh Roesslein's avatar
Josh Roesslein committed
405
406
407
    enable_notifications = bind_api(
        path = '/notifications/follow.json',
        method = 'POST',
408
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
409
410
411
412
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

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

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

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

440
    """ blocks/exists """
Josh Roesslein's avatar
Josh Roesslein committed
441
    def exists_block(self, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
442
443
444
445
446
        try:
            bind_api(
                path = '/blocks/exists.json',
                allowed_param = ['id', 'user_id', 'screen_name'],
                require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
447
            )(self, *args, **kargs)
Josh Roesslein's avatar
Josh Roesslein committed
448
449
450
451
        except TweepError:
            return False
        return True

452
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
453
454
    blocks = bind_api(
        path = '/blocks/blocking.json',
455
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
456
457
458
459
        allowed_param = ['page'],
        require_auth = True
    )

460
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
461
462
    blocks_ids = bind_api(
        path = '/blocks/blocking/ids.json',
463
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
464
465
466
        require_auth = True
    )

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

476
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
477
478
    saved_searches = bind_api(
        path = '/saved_searches.json',
479
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
480
481
482
        require_auth = True
    )

483
    """ saved_searches/show """
484
485
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
486
        payload_type = 'saved_search',
487
488
489
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
490

491
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
492
493
494
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
495
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
496
497
498
499
        allowed_param = ['query'],
        require_auth = True
    )

500
    """ saved_searches/destroy """
501
502
503
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
504
        payload_type = 'saved_search',
505
506
507
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
508

509
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
510
    def test(self):
511
        try:
512
            bind_api(
513
514
515
516
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
517
        return True
518

Josh Roesslein's avatar
Josh Roesslein committed
519
520
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
521
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
522
            method = 'POST',
523
            payload_type = 'list',
524
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
525
526
527
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
528
529
530
531
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
532
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
533
534
535
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
536
537
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
538
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
539
            method = 'POST',
540
            payload_type = 'list',
541
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
542
543
544
            require_auth = True
        )(self, *args, **kargs)

545
546
    lists = bind_api(
        path = '/{user}/lists.json',
547
        payload_type = 'list', payload_list = True,
548
549
550
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
551

552
553
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
554
        payload_type = 'list', payload_list = True,
555
556
557
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
558

559
560
    lists_subscriptions = bind_api(
        path = '/{user}/lists/subscriptions.json',
561
        payload_type = 'list', payload_list = True,
562
563
564
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
565

566
567
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
568
        payload_type = 'status', payload_list = True,
569
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
570
    )
Josh Roesslein's avatar
Josh Roesslein committed
571

572
573
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
574
        payload_type = 'list',
575
576
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
577
578
579
580
581

    def add_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'POST',
582
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
583
584
585
586
587
588
589
590
            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',
591
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
592
593
594
595
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

596
597
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
598
        payload_type = 'user', payload_list = True,
599
600
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
601
602
603
604
605

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
606
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
607
608
609
610
            )(self)
        except TweepError:
            return False

611
612
613
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
614
        payload_type = 'list',
615
616
617
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
618

619
620
621
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
622
        payload_type = 'list',
623
624
625
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
626

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

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

642
    """ trends/available """
643
644
    trends_available = bind_api(
        path = '/trends/available.json',
645
        payload_type = 'json',
646
647
648
        allowed_param = ['lat', 'long']
    )

649
    """ trends/location """
650
651
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
652
        payload_type = 'json',
653
654
        allowed_param = ['woeid']
    )
655

656
    """ search """
657
658
659
    search = bind_api(
        search_api = True,
        path = '/search.json',
660
        payload_type = 'search_result', payload_list = True,
661
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
662
    )
663
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
664

665
    """ trends """
666
667
    trends = bind_api(
        path = '/trends.json',
668
        payload_type = 'json'
669
    )
Josh Roesslein's avatar
Josh Roesslein committed
670

671
    """ trends/current """
672
673
    trends_current = bind_api(
        path = '/trends/current.json',
674
        payload_type = 'json',
675
676
        allowed_param = ['exclude']
    )
677

678
    """ trends/daily """
679
680
    trends_daily = bind_api(
        path = '/trends/daily.json',
681
        payload_type = 'json',
682
683
        allowed_param = ['date', 'exclude']
    )
684

685
    """ trends/weekly """
686
687
    trends_weekly = bind_api(
        path = '/trends/weekly.json',
688
        payload_type = 'json',
689
690
        allowed_param = ['date', 'exclude']
    )
691

692
693
694
695
696
697
698
699
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
        payload_type = 'json',
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/nearby_places """
700
    # listed as deprecated on twitter's API documents
701
702
703
704
705
706
707
708
709
710
711
712
713
    nearby_places = bind_api(
        path = '/geo/nearby_places.json',
        payload_type = 'json',
        allowed_param = ['lat', 'long', 'ip', 'accuracy', 'granularity', 'max_results']
    )

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

714
715
716
717
718
719
720
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
        payload_type = 'json',
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

721
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
722
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
    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.')
        except os.error, e:
            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',
757
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
758
759
760
        }

        return headers, body
761