api.py 23.4 KB
Newer Older
1
# Tweepy
2
3
# Copyright 2009-2010 Joshua Roesslein
# See LICENSE for details.
4

5
6
7
import os
import mimetypes

Josh Roesslein's avatar
Josh Roesslein committed
8
9
from tweepy.binder import bind_api
from tweepy.error import TweepError
10
from tweepy.parsers import ModelParser
11
from tweepy.utils import list_to_csv
12

Josh Roesslein's avatar
Josh Roesslein committed
13

14
class API(object):
Josh Roesslein's avatar
Josh Roesslein committed
15
16
    """Twitter API"""

17
18
19
    def __init__(self, auth_handler=None,
            host='api.twitter.com', search_host='search.twitter.com',
             cache=None, secure=False, api_root='/1', search_root='',
20
            retry_count=0, retry_delay=0, retry_errors=None,
21
            parser=None):
Josh Roesslein's avatar
Josh Roesslein committed
22
        self.auth = auth_handler
Josh Roesslein's avatar
Josh Roesslein committed
23
        self.host = host
24
        self.search_host = search_host
Josh Roesslein's avatar
Josh Roesslein committed
25
        self.api_root = api_root
26
        self.search_root = search_root
Josh Roesslein's avatar
Josh Roesslein committed
27
28
        self.cache = cache
        self.secure = secure
29
30
        self.retry_count = retry_count
        self.retry_delay = retry_delay
31
        self.retry_errors = retry_errors
32
        self.parser = parser or ModelParser()
Josh Roesslein's avatar
Josh Roesslein committed
33

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

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

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

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

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

74
75
76
77
78
79
80
    """/statuses/:id/retweeted_by.format"""
    retweeted_by = bind_api(
        path = '/statuses/{id}/retweeted_by.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['id', 'count', 'page'],
        require_auth = True
    )
81

Aaron Swartz's avatar
Aaron Swartz committed
82
83
84
85
86
87
88
    """/related_results/show/:id.format"""
    related_results = bind_api(
        path = '/related_results/show/{id}.json',
        payload_type = 'relation', payload_list = True,
        allowed_param = ['id'],
        require_auth = False
	)
89
90
91
92
93
94
95
96
97

    """/statuses/:id/retweeted_by/ids.format"""
    retweeted_by_ids = bind_api(
        path = '/statuses/{id}/retweeted_by/ids.json',
        payload_type = 'ids',
        allowed_param = ['id', 'count', 'page'],
        require_auth = True
    )

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

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

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

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

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

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

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

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

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

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

179
180
181
182
183
184
185
186
187
188
    """ Perform bulk look up of users from user ID or screenname """
    def lookup_users(self, user_ids=None, screen_names=None):
        return self._lookup_users(list_to_csv(user_ids), list_to_csv(screen_names))

    _lookup_users = bind_api(
        path = '/users/lookup.json',
        payload_type = 'user', payload_list = True,
        allowed_param = ['user_id', 'screen_name'],
    )

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

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

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

208
    """ statuses/followers """
Josh Roesslein's avatar
Josh Roesslein committed
209
210
    followers = bind_api(
        path = '/statuses/followers.json',
211
        payload_type = 'user', payload_list = True,
212
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
213
214
    )

215
    """ direct_messages """
Josh Roesslein's avatar
Josh Roesslein committed
216
217
    direct_messages = bind_api(
        path = '/direct_messages.json',
218
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
219
220
221
222
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

223
224
225
226
227
228
229
230
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

231
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
232
233
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
234
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
235
236
237
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
238

239
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
240
241
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
242
        method = 'POST',
243
        payload_type = 'direct_message',
244
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
245
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
246
    )
247

248
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
249
250
251
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
252
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
253
254
255
256
        allowed_param = ['id'],
        require_auth = True
    )

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

266
    """ friendships/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
267
268
269
    destroy_friendship = bind_api(
        path = '/friendships/destroy.json',
        method = 'DELETE',
270
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
271
272
273
274
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

275
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
276
277
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
278
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
279
280
281
        allowed_param = ['user_a', 'user_b']
    )

282
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
283
284
    show_friendship = bind_api(
        path = '/friendships/show.json',
285
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
286
287
288
289
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

290
291
292
293
294
295
296
297
298
299
300
301
302

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


303
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
304
305
    friends_ids = bind_api(
        path = '/friends/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
311
312
313
314
315
316
317
318
319
320
321
322
323
    """ 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']
    )

324
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
325
326
    followers_ids = bind_api(
        path = '/followers/ids.json',
327
        payload_type = 'ids',
328
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
329
330
    )

331
    """ account/verify_credentials """
332
    def verify_credentials(self, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
333
334
335
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
336
                payload_type = 'user',
337
338
339
                require_auth = True,
                allowed_param = ['include_entities', 'skip_status'],
            )(self, **kargs)
340
341
342
343
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
344

345
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
346
347
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
348
349
        payload_type = 'json',
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
350
351
    )

352
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
353
354
355
356
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
357
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
358
359
360
        require_auth = True
    )

361
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
362
363
364
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
365
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
366
367
368
369
370
371
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

372
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
373
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
374
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
375
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
376
377
            path = '/account/update_profile_image.json',
            method = 'POST',
378
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
379
380
381
            require_auth = True
        )(self, post_data=post_data, headers=headers)

382
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
383
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
384
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
385
386
387
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
388
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
389
390
391
392
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

393
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
394
395
396
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
397
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
398
        allowed_param = ['name', 'url', 'location', 'description'],
399
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
400
401
    )

402
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
403
404
    favorites = bind_api(
        path = '/favorites.json',
405
        payload_type = 'status', payload_list = True,
406
        allowed_param = ['id', 'max_id', 'page']
Josh Roesslein's avatar
Josh Roesslein committed
407
408
    )

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

418
    """ favorites/destroy """
419
420
421
    destroy_favorite = bind_api(
        path = '/favorites/destroy/{id}.json',
        method = 'DELETE',
422
        payload_type = 'status',
423
424
425
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
426

427
    """ notifications/follow """
Josh Roesslein's avatar
Josh Roesslein committed
428
429
430
    enable_notifications = bind_api(
        path = '/notifications/follow.json',
        method = 'POST',
431
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
432
433
434
435
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

436
    """ notifications/leave """
Josh Roesslein's avatar
Josh Roesslein committed
437
438
439
    disable_notifications = bind_api(
        path = '/notifications/leave.json',
        method = 'POST',
440
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
441
442
443
444
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

445
    """ blocks/create """
Josh Roesslein's avatar
Josh Roesslein committed
446
447
448
    create_block = bind_api(
        path = '/blocks/create.json',
        method = 'POST',
449
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
450
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
451
452
453
        require_auth = True
    )

454
    """ blocks/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
455
456
457
    destroy_block = bind_api(
        path = '/blocks/destroy.json',
        method = 'DELETE',
458
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
459
        allowed_param = ['id', 'user_id', 'screen_name'],
Josh Roesslein's avatar
Josh Roesslein committed
460
461
462
        require_auth = True
    )

463
    """ blocks/exists """
Josh Roesslein's avatar
Josh Roesslein committed
464
    def exists_block(self, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
465
466
467
468
469
        try:
            bind_api(
                path = '/blocks/exists.json',
                allowed_param = ['id', 'user_id', 'screen_name'],
                require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
470
            )(self, *args, **kargs)
Josh Roesslein's avatar
Josh Roesslein committed
471
472
473
474
        except TweepError:
            return False
        return True

475
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
476
477
    blocks = bind_api(
        path = '/blocks/blocking.json',
478
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
479
480
481
482
        allowed_param = ['page'],
        require_auth = True
    )

483
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
484
485
    blocks_ids = bind_api(
        path = '/blocks/blocking/ids.json',
486
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
487
488
489
        require_auth = True
    )

490
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
491
492
493
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
494
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
495
496
497
498
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

499
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
500
501
    saved_searches = bind_api(
        path = '/saved_searches.json',
502
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
503
504
505
        require_auth = True
    )

506
    """ saved_searches/show """
507
508
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
509
        payload_type = 'saved_search',
510
511
512
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
513

514
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
515
516
517
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
518
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
519
520
521
522
        allowed_param = ['query'],
        require_auth = True
    )

523
    """ saved_searches/destroy """
524
525
526
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
527
        payload_type = 'saved_search',
528
529
530
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
531

532
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
533
    def test(self):
534
        try:
535
            bind_api(
536
537
538
539
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
540
        return True
541

Josh Roesslein's avatar
Josh Roesslein committed
542
543
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
544
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
545
            method = 'POST',
546
            payload_type = 'list',
547
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
548
549
550
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
551
552
553
554
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
555
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
556
557
558
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
559
560
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
561
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
562
            method = 'POST',
563
            payload_type = 'list',
564
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
565
566
567
            require_auth = True
        )(self, *args, **kargs)

568
569
    lists = bind_api(
        path = '/{user}/lists.json',
570
        payload_type = 'list', payload_list = True,
571
572
573
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
574

575
576
    lists_memberships = bind_api(
        path = '/{user}/lists/memberships.json',
577
        payload_type = 'list', payload_list = True,
578
579
580
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
581

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

589
590
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
591
        payload_type = 'status', payload_list = True,
592
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
593
    )
Josh Roesslein's avatar
Josh Roesslein committed
594

595
596
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
597
        payload_type = 'list',
598
599
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
600
601
602
603
604

    def add_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'POST',
605
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
606
607
608
609
610
611
612
613
            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',
614
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
615
616
617
618
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

619
620
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
621
        payload_type = 'user', payload_list = True,
622
623
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
624
625
626
627
628

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
629
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
630
631
632
633
            )(self)
        except TweepError:
            return False

634
635
636
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
637
        payload_type = 'list',
638
639
640
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
641

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

650
651
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
652
        payload_type = 'user', payload_list = True,
653
654
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
655
656
657
658
659

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
660
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
661
662
663
664
            )(self)
        except TweepError:
            return False

665
    """ trends/available """
666
667
    trends_available = bind_api(
        path = '/trends/available.json',
668
        payload_type = 'json',
669
670
671
        allowed_param = ['lat', 'long']
    )

672
    """ trends/location """
673
674
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
675
        payload_type = 'json',
676
677
        allowed_param = ['woeid']
    )
678

679
    """ search """
680
681
682
    search = bind_api(
        search_api = True,
        path = '/search.json',
683
        payload_type = 'search_result', payload_list = True,
684
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
685
    )
686
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
687

688
    """ trends/daily """
689
690
    trends_daily = bind_api(
        path = '/trends/daily.json',
691
        payload_type = 'json',
692
693
        allowed_param = ['date', 'exclude']
    )
694

695
    """ trends/weekly """
696
697
    trends_weekly = bind_api(
        path = '/trends/weekly.json',
698
        payload_type = 'json',
699
700
        allowed_param = ['date', 'exclude']
    )
701

702
703
704
705
706
707
708
709
    """ 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 """
710
    # listed as deprecated on twitter's API documents
711
712
713
714
715
716
717
718
719
720
721
722
723
    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']
    )

724
725
726
727
728
729
730
    """ 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']
    )

731
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
732
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
733
734
735
736
737
738
    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.')
739
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
            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',
767
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
768
769
770
        }

        return headers, body
771