api.py 22.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

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
    )
Aaron Swartz's avatar
Aaron Swartz committed
80
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
180
    """ 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'],
        require_auth = True
    )

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

323
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
324
325
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
326
        payload_type = 'json'
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
700
701
702
703
704
705
706
707
708
709
710
711
712
    """ 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 """
    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']
    )

713
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
714
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
715
716
717
718
719
720
721
722
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
    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',
            'Content-Length': len(body)
        }

        return headers, body
753