api.py 22.2 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
    """ direct_messages/sent """
Josh Roesslein's avatar
Josh Roesslein committed
216
217
    sent_direct_messages = bind_api(
        path = '/direct_messages/sent.json',
218
        payload_type = 'direct_message', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
219
220
221
        allowed_param = ['since_id', 'max_id', 'count', 'page'],
        require_auth = True
    )
222

223
    """ direct_messages/new """
Josh Roesslein's avatar
Josh Roesslein committed
224
225
    send_direct_message = bind_api(
        path = '/direct_messages/new.json',
226
        method = 'POST',
227
        payload_type = 'direct_message',
228
        allowed_param = ['user', 'screen_name', 'user_id', 'text'],
229
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
230
    )
231

232
    """ direct_messages/destroy """
Josh Roesslein's avatar
Josh Roesslein committed
233
234
235
    destroy_direct_message = bind_api(
        path = '/direct_messages/destroy.json',
        method = 'DELETE',
236
        payload_type = 'direct_message',
Josh Roesslein's avatar
Josh Roesslein committed
237
238
239
240
        allowed_param = ['id'],
        require_auth = True
    )

241
    """ friendships/create """
Josh Roesslein's avatar
Josh Roesslein committed
242
243
    create_friendship = bind_api(
        path = '/friendships/create.json',
244
        method = 'POST',
245
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
246
        allowed_param = ['id', 'user_id', 'screen_name', 'follow'],
247
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
248
249
    )

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

259
    """ friendships/exists """
Josh Roesslein's avatar
Josh Roesslein committed
260
261
    exists_friendship = bind_api(
        path = '/friendships/exists.json',
262
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
263
264
265
        allowed_param = ['user_a', 'user_b']
    )

266
    """ friendships/show """
Josh Roesslein's avatar
Josh Roesslein committed
267
268
    show_friendship = bind_api(
        path = '/friendships/show.json',
269
        payload_type = 'friendship',
Josh Roesslein's avatar
Josh Roesslein committed
270
271
272
273
        allowed_param = ['source_id', 'source_screen_name',
                          'target_id', 'target_screen_name']
    )

274
    """ friends/ids """
Josh Roesslein's avatar
Josh Roesslein committed
275
276
    friends_ids = bind_api(
        path = '/friends/ids.json',
277
        payload_type = 'ids',
278
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
279
280
    )

281
282
283
284
285
286
287
288
289
290
291
292
293
294
    """ 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']
    )

295
    """ followers/ids """
Josh Roesslein's avatar
Josh Roesslein committed
296
297
    followers_ids = bind_api(
        path = '/followers/ids.json',
298
        payload_type = 'ids',
299
        allowed_param = ['id', 'user_id', 'screen_name', 'cursor']
Josh Roesslein's avatar
Josh Roesslein committed
300
301
    )

302
    """ account/verify_credentials """
Josh Roesslein's avatar
Josh Roesslein committed
303
304
305
306
    def verify_credentials(self):
        try:
            return bind_api(
                path = '/account/verify_credentials.json',
307
                payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
308
309
                require_auth = True
            )(self)
310
311
312
313
        except TweepError, e:
            if e.response and e.response.status == 401:
                return False
            raise
Josh Roesslein's avatar
Josh Roesslein committed
314

315
    """ account/rate_limit_status """
Josh Roesslein's avatar
Josh Roesslein committed
316
317
    rate_limit_status = bind_api(
        path = '/account/rate_limit_status.json',
318
        payload_type = 'json'
Josh Roesslein's avatar
Josh Roesslein committed
319
320
    )

321
    """ account/update_delivery_device """
Josh Roesslein's avatar
Josh Roesslein committed
322
323
324
325
    set_delivery_device = bind_api(
        path = '/account/update_delivery_device.json',
        method = 'POST',
        allowed_param = ['device'],
326
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
327
328
329
        require_auth = True
    )

330
    """ account/update_profile_colors """
Josh Roesslein's avatar
Josh Roesslein committed
331
332
333
    update_profile_colors = bind_api(
        path = '/account/update_profile_colors.json',
        method = 'POST',
334
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
335
336
337
338
339
340
        allowed_param = ['profile_background_color', 'profile_text_color',
                          'profile_link_color', 'profile_sidebar_fill_color',
                          'profile_sidebar_border_color'],
        require_auth = True
    )

341
    """ account/update_profile_image """
Josh Roesslein's avatar
Josh Roesslein committed
342
    def update_profile_image(self, filename):
Josh Roesslein's avatar
Josh Roesslein committed
343
        headers, post_data = API._pack_image(filename, 700)
Josh Roesslein's avatar
Josh Roesslein committed
344
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
345
346
            path = '/account/update_profile_image.json',
            method = 'POST',
347
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
348
349
350
            require_auth = True
        )(self, post_data=post_data, headers=headers)

351
    """ account/update_profile_background_image """
Josh Roesslein's avatar
Josh Roesslein committed
352
    def update_profile_background_image(self, filename, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
353
        headers, post_data = API._pack_image(filename, 800)
Josh Roesslein's avatar
Josh Roesslein committed
354
355
356
        bind_api(
            path = '/account/update_profile_background_image.json',
            method = 'POST',
357
            payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
358
359
360
361
            allowed_param = ['tile'],
            require_auth = True
        )(self, post_data=post_data, headers=headers)

362
    """ account/update_profile """
Josh Roesslein's avatar
Josh Roesslein committed
363
364
365
    update_profile = bind_api(
        path = '/account/update_profile.json',
        method = 'POST',
366
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
367
        allowed_param = ['name', 'url', 'location', 'description'],
368
        require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
369
370
    )

371
    """ favorites """
Josh Roesslein's avatar
Josh Roesslein committed
372
373
    favorites = bind_api(
        path = '/favorites.json',
374
        payload_type = 'status', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
375
376
377
        allowed_param = ['id', 'page']
    )

378
    """ favorites/create """
379
380
381
    create_favorite = bind_api(
        path = '/favorites/create/{id}.json',
        method = 'POST',
382
        payload_type = 'status',
383
384
385
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
386

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

396
    """ notifications/follow """
Josh Roesslein's avatar
Josh Roesslein committed
397
398
399
    enable_notifications = bind_api(
        path = '/notifications/follow.json',
        method = 'POST',
400
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
401
402
403
404
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

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

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

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

432
    """ blocks/exists """
Josh Roesslein's avatar
Josh Roesslein committed
433
    def exists_block(self, *args, **kargs):
Josh Roesslein's avatar
Josh Roesslein committed
434
435
436
437
438
        try:
            bind_api(
                path = '/blocks/exists.json',
                allowed_param = ['id', 'user_id', 'screen_name'],
                require_auth = True
Josh Roesslein's avatar
Josh Roesslein committed
439
            )(self, *args, **kargs)
Josh Roesslein's avatar
Josh Roesslein committed
440
441
442
443
        except TweepError:
            return False
        return True

444
    """ blocks/blocking """
Josh Roesslein's avatar
Josh Roesslein committed
445
446
    blocks = bind_api(
        path = '/blocks/blocking.json',
447
        payload_type = 'user', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
448
449
450
451
        allowed_param = ['page'],
        require_auth = True
    )

452
    """ blocks/blocking/ids """
Josh Roesslein's avatar
Josh Roesslein committed
453
454
    blocks_ids = bind_api(
        path = '/blocks/blocking/ids.json',
455
        payload_type = 'json',
Josh Roesslein's avatar
Josh Roesslein committed
456
457
458
        require_auth = True
    )

459
    """ report_spam """
Josh Roesslein's avatar
Josh Roesslein committed
460
461
462
    report_spam = bind_api(
        path = '/report_spam.json',
        method = 'POST',
463
        payload_type = 'user',
Josh Roesslein's avatar
Josh Roesslein committed
464
465
466
467
        allowed_param = ['id', 'user_id', 'screen_name'],
        require_auth = True
    )

468
    """ saved_searches """
Josh Roesslein's avatar
Josh Roesslein committed
469
470
    saved_searches = bind_api(
        path = '/saved_searches.json',
471
        payload_type = 'saved_search', payload_list = True,
Josh Roesslein's avatar
Josh Roesslein committed
472
473
474
        require_auth = True
    )

475
    """ saved_searches/show """
476
477
    get_saved_search = bind_api(
        path = '/saved_searches/show/{id}.json',
478
        payload_type = 'saved_search',
479
480
481
        allowed_param = ['id'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
482

483
    """ saved_searches/create """
Josh Roesslein's avatar
Josh Roesslein committed
484
485
486
    create_saved_search = bind_api(
        path = '/saved_searches/create.json',
        method = 'POST',
487
        payload_type = 'saved_search',
Josh Roesslein's avatar
Josh Roesslein committed
488
489
490
491
        allowed_param = ['query'],
        require_auth = True
    )

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

501
    """ help/test """
Josh Roesslein's avatar
Josh Roesslein committed
502
    def test(self):
503
        try:
504
            bind_api(
505
506
507
508
                path = '/help/test.json',
            )(self)
        except TweepError:
            return False
509
        return True
510

Josh Roesslein's avatar
Josh Roesslein committed
511
512
    def create_list(self, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
513
            path = '/%s/lists.json' % self.auth.get_username(),
Josh Roesslein's avatar
Josh Roesslein committed
514
            method = 'POST',
515
            payload_type = 'list',
516
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
517
518
519
            require_auth = True
        )(self, *args, **kargs)

Josh Roesslein's avatar
Josh Roesslein committed
520
521
522
523
    def destroy_list(self, slug):
        return bind_api(
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
            method = 'DELETE',
524
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
525
526
527
            require_auth = True
        )(self)

Josh Roesslein's avatar
Josh Roesslein committed
528
529
    def update_list(self, slug, *args, **kargs):
        return bind_api(
Josh Roesslein's avatar
Josh Roesslein committed
530
            path = '/%s/lists/%s.json' % (self.auth.get_username(), slug),
Josh Roesslein's avatar
Josh Roesslein committed
531
            method = 'POST',
532
            payload_type = 'list',
533
            allowed_param = ['name', 'mode', 'description'],
Josh Roesslein's avatar
Josh Roesslein committed
534
535
536
            require_auth = True
        )(self, *args, **kargs)

537
538
    lists = bind_api(
        path = '/{user}/lists.json',
539
        payload_type = 'list', payload_list = True,
540
541
542
        allowed_param = ['user', 'cursor'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
543

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

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

558
559
    list_timeline = bind_api(
        path = '/{owner}/lists/{slug}/statuses.json',
560
        payload_type = 'status', payload_list = True,
561
        allowed_param = ['owner', 'slug', 'since_id', 'max_id', 'per_page', 'page']
562
    )
Josh Roesslein's avatar
Josh Roesslein committed
563

564
565
    get_list = bind_api(
        path = '/{owner}/lists/{slug}.json',
566
        payload_type = 'list',
567
568
        allowed_param = ['owner', 'slug']
    )
Josh Roesslein's avatar
Josh Roesslein committed
569
570
571
572
573

    def add_list_member(self, slug, *args, **kargs):
        return bind_api(
            path = '/%s/%s/members.json' % (self.auth.get_username(), slug),
            method = 'POST',
574
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
575
576
577
578
579
580
581
582
            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',
583
            payload_type = 'list',
Josh Roesslein's avatar
Josh Roesslein committed
584
585
586
587
            allowed_param = ['id'],
            require_auth = True
        )(self, *args, **kargs)

588
589
    list_members = bind_api(
        path = '/{owner}/{slug}/members.json',
590
        payload_type = 'user', payload_list = True,
591
592
        allowed_param = ['owner', 'slug', 'cursor']
    )
Josh Roesslein's avatar
Josh Roesslein committed
593
594
595
596
597

    def is_list_member(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/members/%s.json' % (owner, slug, user_id),
598
                payload_type = 'user'
Josh Roesslein's avatar
Josh Roesslein committed
599
600
601
602
            )(self)
        except TweepError:
            return False

603
604
605
    subscribe_list = bind_api(
        path = '/{owner}/{slug}/subscribers.json',
        method = 'POST',
606
        payload_type = 'list',
607
608
609
        allowed_param = ['owner', 'slug'],
        require_auth = True
    )
Josh Roesslein's avatar
Josh Roesslein committed
610

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

619
620
    list_subscribers = bind_api(
        path = '/{owner}/{slug}/subscribers.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_subscribed_list(self, owner, slug, user_id):
        try:
            return bind_api(
                path = '/%s/%s/subscribers/%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
    """ trends/available """
635
636
    trends_available = bind_api(
        path = '/trends/available.json',
637
        payload_type = 'json',
638
639
640
        allowed_param = ['lat', 'long']
    )

641
    """ trends/location """
642
643
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
644
        payload_type = 'json',
645
646
        allowed_param = ['woeid']
    )
647

648
    """ search """
649
650
651
    search = bind_api(
        search_api = True,
        path = '/search.json',
652
        payload_type = 'search_result', payload_list = True,
653
        allowed_param = ['q', 'lang', 'locale', 'rpp', 'page', 'since_id', 'geocode', 'show_user', 'max_id', 'since', 'until', 'result_type']
654
    )
655
    search.pagination_mode = 'page'
Josh Roesslein's avatar
Josh Roesslein committed
656

657
    """ trends """
658
659
    trends = bind_api(
        path = '/trends.json',
660
        payload_type = 'json'
661
    )
Josh Roesslein's avatar
Josh Roesslein committed
662

663
    """ trends/current """
664
665
    trends_current = bind_api(
        path = '/trends/current.json',
666
        payload_type = 'json',
667
668
        allowed_param = ['exclude']
    )
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
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
    """ 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']
    )

705
    """ Internal use only """
Josh Roesslein's avatar
Josh Roesslein committed
706
    @staticmethod
Josh Roesslein's avatar
Josh Roesslein committed
707
708
709
710
711
712
713
714
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
    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
745