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

5
6
7
import os
import mimetypes

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

Josh Roesslein's avatar
Josh Roesslein committed
13

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

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

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

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

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

58
59
60
61
62
63
64
65
    """/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']
    )

66
67
68
69
70
71
72
    """/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
    )
73

Aaron Swartz's avatar
Aaron Swartz committed
74
75
76
77
78
79
80
    """/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
	)
81
82
83
84
85
86
87
88
89

    """/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
90
    """ statuses/retweeted_by_me """
Josh Roesslein's avatar
Josh Roesslein committed
91
92
    retweeted_by_me = bind_api(
        path = '/statuses/retweeted_by_me.json',
93
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
94
95
96
97
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )

98
    """ statuses/retweeted_to_me """
Josh Roesslein's avatar
Josh Roesslein committed
99
100
    retweeted_to_me = bind_api(
        path = '/statuses/retweeted_to_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
    )

Alejandro Gómez's avatar
Alejandro Gómez committed
106
107
108
109
110
111
112
113
    """ 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
    )

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

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

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

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

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

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

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

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'],
    )

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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    """ users/suggestions/:slug """
    suggested_users = bind_api(
        path = '/users/suggestions/{slug}.json',
        payload_type = 'user', payload_list = True,
        require_auth = True,
        allowed_param = ['slug', 'lang']
    )

    """ users/suggestions """
    suggested_categories = bind_api(
        path = '/users/suggestions.json',
        payload_type = 'category', payload_list = True,
        allowed_param = ['lang'],
        require_auth = True
    )

    """ users/suggestions/:slug/members """
    suggested_users_tweets = bind_api(
        path = '/users/suggestions/{slug}/members.json',
        payload_type = 'status', payload_list = True,
        allowed_param = ['slug'],
        require_auth = True
    )

217
    """ statuses/friends """
Josh Roesslein's avatar
Josh Roesslein committed
218
219
    friends = bind_api(
        path = '/statuses/friends.json',
220
        payload_type = 'user', payload_list = True,
221
        allowed_param = ['id', 'user_id', 'screen_name', 'page', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
222
223
    )

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

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

239
240
241
242
243
244
245
246
    """ direct_messages/show """
    get_direct_message = bind_api(
        path = '/direct_messages/show/{id}.json',
        payload_type = 'direct_message',
        allowed_param = ['id'],
        require_auth = True
    )

247
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
248
249
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
250
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
251
252
253
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
254

255
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
256
257
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
258
        method = 'POST',
259
        payload_type = 'direct_message',
260
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
261
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
262
    )
263

264
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
265
266
267
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
268
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
269
270
271
272
        allowed_param = ['id'],
        require_auth = True
    )

273
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
274
275
    create_friendship = bind_api(
        path = '/friendships/create.json',
276
        method = 'POST',
277
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
278
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
279
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
280
281
    )

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

291
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
292
293
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
294
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
295
296
297
        allowed_param = ['user_a', 'user_b']
    )

298
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
299
300
    show_friendship = bind_api(
        path = '/friendships/show.json',
301
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
302
303
304
305
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

306
307
308
309
310
311
312
313
314
315
316
317
318

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


319
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
320
321
    friends_ids = bind_api(
        path = '/friends/ids.json',
322
        payload_type = 'ids',
323
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
324
325
    )

326
327
328
329
330
331
332
333
334
335
336
337
338
339
    """ 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']
    )

340
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
341
342
    followers_ids = bind_api(
        path = '/followers/ids.json',
343
        payload_type = 'ids',
344
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
345
346
    )

347
    """ account/verify_credentials """
348
    def verify_credentials(self, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
349
350
351
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
352
                payload_type = 'user',
353
354
355
                require_auth = True,
                allowed_param = ['include_entities', 'skip_status'],
            )(self, **kargs)
356
357
358
359
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
360

361
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
362
363
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
364
365
        payload_type = 'json',
        use_cache = False
Josh Roesslein's avatar
Josh Roesslein committed
366
367
    )

368
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
369
370
371
372
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
373
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
374
375
376
        require_auth = True
    )

377
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
378
379
380
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
381
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
382
383
384
385
386
387
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

388
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
389
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
390
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
391
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
392
393
            path = '/account/update_profile_image.json',
            method = 'POST',
394
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
395
396
397
            require_auth = True
        )(self, post_data=post_data, headers=headers)

398
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
399
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
400
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
401
402
403
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
404
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
405
406
407
408
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

409
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
410
411
412
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
413
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
414
        allowed_param = ['name', 'url', 'location', 'description'],
415
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
416
417
    )

418
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
419
420
    favorites = bind_api(
        path = '/favorites.json',
421
        payload_type = 'status', payload_list = True,
422
        allowed_param = ['id', 'max_id', 'page']
Josh Roesslein's avatar
Josh Roesslein committed
423
424
    )

425
    """ favorites/create """
426
    create_favorite = bind_api(
427
        path = '/favorites/create.json',
428
        method = 'POST',
429
        payload_type = 'status',
430
431
432
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
433

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

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

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

461
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
462
    blocks = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
463
        path = '/blocks/list.json',
464
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
465
466
467
468
        allowed_param = ['page'],
        require_auth = True
    )

469
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
470
    blocks_ids = bind_api(
Joshua Roesslein's avatar
Joshua Roesslein committed
471
        path = '/blocks/ids.json',
472
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
473
474
475
        require_auth = True
    )

476
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
477
478
479
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
480
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
481
482
483
484
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

485
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
486
487
    saved_searches = bind_api(
        path = '/saved_searches.json',
488
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
489
490
491
        require_auth = True
    )

492
    """ saved_searches/show """
493
494
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
495
        payload_type = 'saved_search',
496
497
498
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
499

500
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
501
502
503
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
504
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
505
506
507
508
        allowed_param = ['query'],
        require_auth = True
    )

509
    """ saved_searches/destroy """
510
511
512
    destroy_saved_search = bind_api(
        path = '/saved_searches/destroy/{id}.json',
        method = 'DELETE',
513
        payload_type = 'saved_search',
514
515
516
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
517

518
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
519
    def test(self):
520
        try:
521
            bind_api(
522
523
524
525
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
526
        return True
527

528
529
530
531
532
533
534
    create_list = bind_api(
        path = '/lists/create.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['name', 'mode', 'description'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
535

536
537
538
539
540
541
542
    destroy_list = bind_api(
        path = '/lists/destroy.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['owner_screen_name', 'owner_id', 'list_id', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
543

544
545
546
547
548
549
550
    update_list = bind_api(
        path = '/lists/update.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['list_id', 'slug', 'name', 'mode', 'description', 'owner_screen_name', 'owner_id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
551

552
553
    lists = bind_api(
        path = '/{user}/lists.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_memberships = bind_api(
        path = '/{user}/lists/memberships.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
    lists_subscriptions = bind_api(
        path = '/{user}/lists/subscriptions.json',
568
        payload_type = 'list', payload_list = True,
569
570
571
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
572

573
574
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
575
        payload_type = 'status', payload_list = True,
576
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
577
    )
Josh Roesslein's avatar
Josh Roesslein committed
578

579
580
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
581
        payload_type = 'list',
582
583
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
584

585
586
587
588
589
590
591
    add_list_member = bind_api(
        path = '/lists/members/create.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['screen_name', 'user_id', 'owner_screen_name', 'owner_id', 'slug', 'list_id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
592

593
594
595
596
597
598
599
    remove_list_member = bind_api(
        path = '/lists/members/destroy.json',
        method = 'POST',
        payload_type = 'list',
        allowed_param = ['screen_name', 'user_id', 'owner_screen_name', 'owner_id', 'slug', 'list_id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
600

601
602
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
603
        payload_type = 'user', payload_list = True,
604
605
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
606
607
608
609
610

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
611
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
612
613
614
615
            )(self)
        except TweepError:
            return False

616
617
618
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
619
        payload_type = 'list',
620
621
622
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
623

624
625
626
    unsubscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'DELETE',
627
        payload_type = 'list',
628
629
630
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
631

632
633
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
634
        payload_type = 'user', payload_list = True,
635
636
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
637
638
639
640
641

    def is_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%s.json' % (owner, slug, user_id),
642
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
643
644
645
646
            )(self)
        except TweepError:
            return False

647
    """ trends/available """
648
649
    trends_available = bind_api(
        path = '/trends/available.json',
650
        payload_type = 'json',
651
652
653
        allowed_param = ['lat', 'long']
    )

654
    """ trends/location """
655
656
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
657
        payload_type = 'json',
658
659
        allowed_param = ['woeid']
    )
660

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

670
    """ trends/daily """
671
672
    trends_daily = bind_api(
        path = '/trends/daily.json',
673
        payload_type = 'json',
674
675
        allowed_param = ['date', 'exclude']
    )
676

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

684
685
686
    """ geo/reverse_geocode """
    reverse_geocode = bind_api(
        path = '/geo/reverse_geocode.json',
687
        payload_type = 'place', payload_list = True,
688
689
690
691
        allowed_param = ['lat', 'long', 'accuracy', 'granularity', 'max_results']
    )

    """ geo/nearby_places """
692
    # listed as deprecated on twitter's API documents
693
694
    nearby_places = bind_api(
        path = '/geo/nearby_places.json',
695
        payload_type = 'place', payload_list = True,
696
697
698
699
700
701
        allowed_param = ['lat', 'long', 'ip', 'accuracy', 'granularity', 'max_results']
    )

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

706
707
708
    """ geo/search """
    geo_search = bind_api(
        path = '/geo/search.json',
709
        payload_type = 'place', payload_list = True,
710
711
712
        allowed_param = ['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within']
    )

713
714
715
716
717
718
719
    """ geo/similar_places """
    geo_similar_places = bind_api(
        path = '/geo/similar_places.json',
        payload_type = 'place', payload_list = True,
        allowed_param = ['lat', 'long', 'name', 'contained_within']
    )

720
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
721
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
722
723
724
725
726
727
    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.')
728
        except os.error:
Josh Roesslein's avatar
Josh Roesslein committed
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
            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',
756
            'Content-Length': str(len(body))
Josh Roesslein's avatar
Josh Roesslein committed
757
758
759
        }

        return headers, body
760