-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
/
api.py
3957 lines (3350 loc) · 129 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
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
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Tweepy
# Copyright 2009-2023 Joshua Roesslein
# See LICENSE for details.
import contextlib
import functools
import imghdr
import logging
import mimetypes
from platform import python_version
import sys
import time
from urllib.parse import urlencode
import requests
import tweepy
from tweepy.errors import (
BadRequest, Forbidden, HTTPException, NotFound, TooManyRequests,
TweepyException, TwitterServerError, Unauthorized
)
from tweepy.models import Model
from tweepy.parsers import ModelParser, Parser
from tweepy.utils import list_to_csv
log = logging.getLogger(__name__)
def pagination(mode):
def decorator(method):
@functools.wraps(method)
def wrapper(*args, **kwargs):
return method(*args, **kwargs)
wrapper.pagination_mode = mode
return wrapper
return decorator
def payload(payload_type, **payload_kwargs):
payload_list = payload_kwargs.get('list', False)
def decorator(method):
@functools.wraps(method)
def wrapper(*args, **kwargs):
kwargs['payload_list'] = payload_list
kwargs['payload_type'] = payload_type
return method(*args, **kwargs)
wrapper.payload_list = payload_list
wrapper.payload_type = payload_type
return wrapper
return decorator
class API:
"""Twitter API v1.1 Interface
.. versionchanged:: 4.11
Added support for ``include_ext_edit_control`` endpoint/method
parameter
.. versionchanged:: 4.14
Removed ``search_30_day`` and ``search_full_archive`` methods, as
`the Premium v1.1 API has been deprecated`_
Parameters
----------
auth
The authentication handler to be used
cache
The cache to query if a GET method is used
host
The general REST API host server URL
parser
The Parser instance to use for parsing the response from Twitter;
defaults to an instance of ModelParser
proxy
The full url to an HTTPS proxy to use for connecting to Twitter
retry_count
Number of retries to attempt when an error occurs
retry_delay
Number of seconds to wait between retries
retry_errors
Which HTTP status codes to retry
timeout
The maximum amount of time to wait for a response from Twitter
upload_host
The URL of the upload server
wait_on_rate_limit
Whether or not to automatically wait for rate limits to replenish
Raises
------
TypeError
If the given parser is not a Parser instance
References
----------
https://developer.twitter.com/en/docs/api-reference-index
.. _the Premium v1.1 API has been deprecated: https://twittercommunity.com/t/deprecating-the-premium-v1-1-api/191092
"""
def __init__(
self, auth=None, *, cache=None, host='api.twitter.com', parser=None,
proxy=None, retry_count=0, retry_delay=0, retry_errors=None,
timeout=60, upload_host='upload.twitter.com', user_agent=None,
wait_on_rate_limit=False
):
self.auth = auth
self.cache = cache
self.host = host
if parser is None:
parser = ModelParser()
self.parser = parser
self.proxy = {}
if proxy is not None:
self.proxy['https'] = proxy
self.retry_count = retry_count
self.retry_delay = retry_delay
self.retry_errors = retry_errors
self.timeout = timeout
self.upload_host = upload_host
if user_agent is None:
user_agent = (
f"Python/{python_version()} "
f"Requests/{requests.__version__} "
f"Tweepy/{tweepy.__version__}"
)
self.user_agent = user_agent
self.wait_on_rate_limit = wait_on_rate_limit
# Attempt to explain more clearly the parser argument requirements
# https://github.com/tweepy/tweepy/issues/421
if not isinstance(self.parser, Parser):
raise TypeError(
"parser should be an instance of Parser, not " +
str(type(self.parser))
)
self.session = requests.Session()
def request(
self, method, endpoint, *, endpoint_parameters=(), params=None,
headers=None, json_payload=None, parser=None, payload_list=False,
payload_type=None, post_data=None, files=None, require_auth=True,
return_cursors=False, upload_api=False, use_cache=True, **kwargs
):
# If authentication is required and no credentials
# are provided, throw an error.
if require_auth and not self.auth:
raise TweepyException('Authentication required!')
self.cached_result = False
if headers is None:
headers = {}
headers["User-Agent"] = self.user_agent
# Build the request URL
path = f'/1.1/{endpoint}.json'
if upload_api:
url = 'https://' + self.upload_host + path
else:
url = 'https://' + self.host + path
if params is None:
params = {}
for k, arg in kwargs.items():
if arg is None:
continue
if k not in endpoint_parameters + (
"include_ext_edit_control", "tweet_mode"
):
log.warning(f'Unexpected parameter: {k}')
params[k] = str(arg)
log.debug("PARAMS: %r", params)
# Query the cache if one is available
# and this request uses a GET method.
if use_cache and self.cache and method == 'GET':
cache_result = self.cache.get(f'{path}?{urlencode(params)}')
# if cache result found and not expired, return it
if cache_result:
# must restore api reference
if isinstance(cache_result, list):
for result in cache_result:
if isinstance(result, Model):
result._api = self
else:
if isinstance(cache_result, Model):
cache_result._api = self
self.cached_result = True
return cache_result
# Monitoring rate limits
remaining_calls = None
reset_time = None
if parser is None:
parser = self.parser
try:
# Continue attempting request until successful
# or maximum number of retries is reached.
retries_performed = 0
while retries_performed <= self.retry_count:
if (self.wait_on_rate_limit and reset_time is not None
and remaining_calls is not None
and remaining_calls < 1):
# Handle running out of API calls
sleep_time = reset_time - int(time.time())
if sleep_time > 0:
log.warning(f"Rate limit reached. Sleeping for: {sleep_time}")
time.sleep(sleep_time + 1) # Sleep for extra sec
# Apply authentication
auth = None
if self.auth:
auth = self.auth.apply_auth()
# Execute request
try:
resp = self.session.request(
method, url, params=params, headers=headers,
data=post_data, files=files, json=json_payload,
timeout=self.timeout, auth=auth, proxies=self.proxy
)
except Exception as e:
raise TweepyException(f'Failed to send request: {e}').with_traceback(sys.exc_info()[2])
if 200 <= resp.status_code < 300:
break
rem_calls = resp.headers.get('x-rate-limit-remaining')
if rem_calls is not None:
remaining_calls = int(rem_calls)
elif remaining_calls is not None:
remaining_calls -= 1
reset_time = resp.headers.get('x-rate-limit-reset')
if reset_time is not None:
reset_time = int(reset_time)
retry_delay = self.retry_delay
if resp.status_code in (420, 429) and self.wait_on_rate_limit:
if remaining_calls == 0:
# If ran out of calls before waiting switching retry last call
continue
if 'retry-after' in resp.headers:
retry_delay = float(resp.headers['retry-after'])
elif self.retry_errors and resp.status_code not in self.retry_errors:
# Exit request loop if non-retry error code
break
# Sleep before retrying request again
time.sleep(retry_delay)
retries_performed += 1
# If an error was returned, throw an exception
self.last_response = resp
if resp.status_code == 400:
raise BadRequest(resp)
if resp.status_code == 401:
raise Unauthorized(resp)
if resp.status_code == 403:
raise Forbidden(resp)
if resp.status_code == 404:
raise NotFound(resp)
if resp.status_code == 429:
raise TooManyRequests(resp)
if resp.status_code >= 500:
raise TwitterServerError(resp)
if resp.status_code and not 200 <= resp.status_code < 300:
raise HTTPException(resp)
# Parse the response payload
return_cursors = return_cursors or 'cursor' in params or 'next' in params
result = parser.parse(
resp.text, api=self, payload_list=payload_list,
payload_type=payload_type, return_cursors=return_cursors
)
# Store result into cache if one is available.
if use_cache and self.cache and method == 'GET' and result:
self.cache.store(f'{path}?{urlencode(params)}', result)
return result
finally:
self.session.close()
# Get Tweet timelines
@pagination(mode='id')
@payload('status', list=True)
def home_timeline(self, **kwargs):
"""home_timeline(*, count, since_id, max_id, trim_user, \
exclude_replies, include_entities)
Returns the 20 most recent statuses, including retweets, posted by
the authenticating user and that user's friends. This is the equivalent
of /timeline/home on the Web.
Parameters
----------
count
|count|
since_id
|since_id|
max_id
|max_id|
trim_user
|trim_user|
exclude_replies
|exclude_replies|
include_entities
|include_entities|
Returns
-------
:py:class:`List`\[:class:`~tweepy.models.Status`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/timelines/api-reference/get-statuses-home_timeline
"""
return self.request(
'GET', 'statuses/home_timeline', endpoint_parameters=(
'count', 'since_id', 'max_id', 'trim_user', 'exclude_replies',
'include_entities'
), **kwargs
)
@pagination(mode='id')
@payload('status', list=True)
def mentions_timeline(self, **kwargs):
"""mentions_timeline(*, count, since_id, max_id, trim_user, \
include_entities)
Returns the 20 most recent mentions, including retweets.
Parameters
----------
count
|count|
since_id
|since_id|
max_id
|max_id|
trim_user
|trim_user|
include_entities
|include_entities|
Returns
-------
:py:class:`List`\[:class:`~tweepy.models.Status`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/timelines/api-reference/get-statuses-mentions_timeline
"""
return self.request(
'GET', 'statuses/mentions_timeline', endpoint_parameters=(
'count', 'since_id', 'max_id', 'trim_user', 'include_entities'
), **kwargs
)
@pagination(mode='id')
@payload('status', list=True)
def user_timeline(self, **kwargs):
"""user_timeline(*, user_id, screen_name, since_id, count, max_id, \
trim_user, exclude_replies, include_rts)
Returns the 20 most recent statuses posted from the authenticating user
or the user specified. It's also possible to request another user's
timeline via the id parameter.
Parameters
----------
user_id
|user_id|
screen_name
|screen_name|
since_id
|since_id|
count
|count|
max_id
|max_id|
trim_user
|trim_user|
exclude_replies
|exclude_replies|
include_rts
When set to ``false``, the timeline will strip any native retweets
(though they will still count toward both the maximal length of the
timeline and the slice selected by the count parameter). Note: If
you're using the trim_user parameter in conjunction with
include_rts, the retweets will still contain a full user object.
Returns
-------
:py:class:`List`\[:class:`~tweepy.models.Status`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/timelines/api-reference/get-statuses-user_timeline
"""
return self.request(
'GET', 'statuses/user_timeline', endpoint_parameters=(
'user_id', 'screen_name', 'since_id', 'count', 'max_id',
'trim_user', 'exclude_replies', 'include_rts'
), **kwargs
)
# Post, retrieve, and engage with Tweets
@pagination(mode='id')
@payload('status', list=True)
def get_favorites(self, **kwargs):
"""get_favorites(*, user_id, screen_name, count, since_id, max_id, \
include_entities)
Returns the favorite statuses for the authenticating user or user
specified by the ID parameter.
.. versionchanged:: 4.0
Renamed from ``API.favorites``
Parameters
----------
user_id
|user_id|
screen_name
|screen_name|
count
|count|
since_id
|since_id|
max_id
|max_id|
include_entities
|include_entities|
Returns
-------
:py:class:`List`\[:class:`~tweepy.models.Status`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-favorites-list
"""
return self.request(
'GET', 'favorites/list', endpoint_parameters=(
'user_id', 'screen_name', 'count', 'since_id', 'max_id',
'include_entities'
), **kwargs
)
@payload('status', list=True)
def lookup_statuses(self, id, **kwargs):
"""lookup_statuses(id, *, include_entities, trim_user, map, \
include_ext_alt_text, include_card_uri)
Returns full Tweet objects for up to 100 Tweets per request, specified
by the ``id`` parameter.
.. versionchanged:: 4.0
Renamed from ``API.statuses_lookup``
Parameters
----------
id
A list of Tweet IDs to lookup, up to 100
include_entities
|include_entities|
trim_user
|trim_user|
map
A boolean indicating whether or not to include Tweets that cannot
be shown. Defaults to False.
include_ext_alt_text
|include_ext_alt_text|
include_card_uri
|include_card_uri|
Returns
-------
:py:class:`List`\[:class:`~tweepy.models.Status`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-statuses-lookup
"""
return self.request(
'GET', 'statuses/lookup', endpoint_parameters=(
'id', 'include_entities', 'trim_user', 'map',
'include_ext_alt_text', 'include_card_uri'
), id=list_to_csv(id), **kwargs
)
@payload('json')
def get_oembed(self, url, **kwargs):
"""get_oembed( \
url, *, maxwidth, hide_media, hide_thread, omit_script, align, \
related, lang, theme, link_color, widget_type, dnt \
)
Returns a single Tweet, specified by either a Tweet web URL or the
Tweet ID, in an oEmbed-compatible format. The returned HTML snippet will
be automatically recognized as an Embedded Tweet when Twitter's widget
JavaScript is included on the page.
The oEmbed endpoint allows customization of the final appearance of an
Embedded Tweet by setting the corresponding properties in HTML markup
to be interpreted by Twitter's JavaScript bundled with the HTML
response by default. The format of the returned markup may change over
time as Twitter adds new features or adjusts its Tweet representation.
The Tweet fallback markup is meant to be cached on your servers for up
to the suggested cache lifetime specified in the ``cache_age``.
Parameters
----------
url
The URL of the Tweet to be embedded
maxwidth
The maximum width of a rendered Tweet in whole pixels. A supplied
value under or over the allowed range will be returned as the
minimum or maximum supported width respectively; the reset width
value will be reflected in the returned ``width`` property. Note
that Twitter does not support the oEmbed ``maxheight`` parameter.
Tweets are fundamentally text, and are therefore of unpredictable
height that cannot be scaled like an image or video. Relatedly, the
oEmbed response will not provide a value for ``height``.
Implementations that need consistent heights for Tweets should
refer to the ``hide_thread`` and ``hide_media`` parameters below.
hide_media
When set to ``true``, ``"t"``, or ``1``, links in a Tweet are not
expanded to photo, video, or link previews.
hide_thread
When set to ``true``, ``"t"``, or ``1``, a collapsed version of the
previous Tweet in a conversation thread will not be displayed when
the requested Tweet is in reply to another Tweet.
omit_script
When set to ``true``, ``"t"``, or ``1``, the ``<script>``
responsible for loading ``widgets.js`` will not be returned. Your
webpages should include their own reference to ``widgets.js`` for
use across all Twitter widgets including Embedded Tweets.
align
Specifies whether the embedded Tweet should be floated left, right,
or center in the page relative to the parent element.
related
A comma-separated list of Twitter usernames related to your
content. This value will be forwarded to Tweet action intents if a
viewer chooses to reply, like, or retweet the embedded Tweet.
lang
Request returned HTML and a rendered Tweet in the specified Twitter
language supported by embedded Tweets.
theme
When set to ``dark``, the Tweet is displayed with light text over a
dark background.
link_color
Adjust the color of Tweet text links with a hexadecimal color
value.
widget_type
Set to ``video`` to return a Twitter Video embed for the given
Tweet.
dnt
When set to ``true``, the Tweet and its embedded page on your site
are not used for purposes that include personalized suggestions and
personalized ads.
Returns
-------
:class:`dict`
JSON
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-statuses-oembed
"""
return self.request(
'GET', 'statuses/oembed', endpoint_parameters=(
'url', 'maxwidth', 'hide_media', 'hide_thread', 'omit_script',
'align', 'related', 'lang', 'theme', 'link_color',
'widget_type', 'dnt'
), url=url, require_auth=False, **kwargs
)
@pagination(mode='cursor')
@payload('ids')
def get_retweeter_ids(self, id, **kwargs):
"""get_retweeter_ids(id, *, count, cursor, stringify_ids)
Returns up to 100 user IDs belonging to users who have retweeted the
Tweet specified by the ``id`` parameter.
.. versionchanged:: 4.0
Renamed from ``API.retweeters``
Parameters
----------
id
|sid|
count
|count|
cursor
|cursor|
stringify_ids
|stringify_ids|
Returns
-------
:py:class:`List`\[:class:`int`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-statuses-retweeters-ids
"""
return self.request(
'GET', 'statuses/retweeters/ids', endpoint_parameters=(
'id', 'count', 'cursor', 'stringify_ids'
), id=id, **kwargs
)
@payload('status', list=True)
def get_retweets(self, id, **kwargs):
"""get_retweets(id, *, count, trim_user)
Returns up to 100 of the first Retweets of the given Tweet.
.. versionchanged:: 4.0
Renamed from ``API.retweets``
Parameters
----------
id
|sid|
count
|count|
trim_user
|trim_user|
Returns
-------
:py:class:`List`\[:class:`~tweepy.models.Status`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-statuses-retweets-id
"""
return self.request(
'GET', f'statuses/retweets/{id}', endpoint_parameters=(
'count', 'trim_user'
), **kwargs
)
@pagination(mode='id')
@payload('status', list=True)
def get_retweets_of_me(self, **kwargs):
"""get_retweets_of_me(*, count, since_id, max_id, trim_user, \
include_entities, include_user_entities)
Returns the 20 most recent Tweets of the authenticated user that have
been retweeted by others.
.. versionchanged:: 4.0
Renamed from ``API.retweets_of_me``
Parameters
----------
count
|count|
since_id
|since_id|
max_id
|max_id|
trim_user
|trim_user|
include_entities
|include_entities|
include_user_entities
|include_user_entities|
Returns
-------
:py:class:`List`\[:class:`~tweepy.models.Status`]
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-statuses-retweets_of_me
"""
return self.request(
'GET', 'statuses/retweets_of_me', endpoint_parameters=(
'count', 'since_id', 'max_id', 'trim_user', 'include_entities',
'include_user_entities'
), **kwargs
)
@payload('status')
def get_status(self, id, **kwargs):
"""get_status(id, *, trim_user, include_my_retweet, include_entities, \
include_ext_alt_text, include_card_uri)
Returns a single status specified by the ID parameter.
Parameters
----------
id:
|sid|
trim_user
|trim_user|
include_my_retweet:
A boolean indicating if any Tweets returned that have been
retweeted by the authenticating user should include an additional
current_user_retweet node, containing the ID of the source status
for the retweet.
include_entities
|include_entities|
include_ext_alt_text
|include_ext_alt_text|
include_card_uri
|include_card_uri|
Returns
-------
:class:`~tweepy.models.Status`
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/get-statuses-show-id
"""
return self.request(
'GET', 'statuses/show', endpoint_parameters=(
'id', 'trim_user', 'include_my_retweet', 'include_entities',
'include_ext_alt_text', 'include_card_uri'
), id=id, **kwargs
)
@payload('status')
def create_favorite(self, id, **kwargs):
"""create_favorite(id, *, include_entities)
Favorites the status specified in the ``id`` parameter as the
authenticating user.
Parameters
----------
id
|sid|
include_entities
|include_entities|
Returns
-------
:class:`~tweepy.models.Status`
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-favorites-create
"""
return self.request(
'POST', 'favorites/create', endpoint_parameters=(
'id', 'include_entities'
), id=id, **kwargs
)
@payload('status')
def destroy_favorite(self, id, **kwargs):
"""destroy_favorite(id, *, include_entities)
Un-favorites the status specified in the ``id`` parameter as the
authenticating user.
Parameters
----------
id
|sid|
include_entities
|include_entities|
Returns
-------
:class:`~tweepy.models.Status`
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-favorites-destroy
"""
return self.request(
'POST', 'favorites/destroy', endpoint_parameters=(
'id', 'include_entities'
), id=id, **kwargs
)
@payload('status')
def destroy_status(self, id, **kwargs):
"""destroy_status(id, *, trim_user)
Destroy the status specified by the ``id`` parameter. The authenticated
user must be the author of the status to destroy.
Parameters
----------
id
|sid|
trim_user
|trim_user|
Returns
-------
:class:`~tweepy.models.Status`
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-destroy-id
"""
return self.request(
'POST', f'statuses/destroy/{id}', endpoint_parameters=(
'trim_user',
), **kwargs
)
@payload('status')
def retweet(self, id, **kwargs):
"""retweet(id, *, trim_user)
Retweets a Tweet. Requires the ID of the Tweet you are retweeting.
Parameters
----------
id
|sid|
trim_user
|trim_user|
Returns
-------
:class:`~tweepy.models.Status`
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-retweet-id
"""
return self.request(
'POST', f'statuses/retweet/{id}', endpoint_parameters=(
'trim_user',
), **kwargs
)
@payload('status')
def unretweet(self, id, **kwargs):
"""unretweet(id, *, trim_user)
Untweets a retweeted status. Requires the ID of the retweet to
unretweet.
Parameters
----------
id
|sid|
trim_user
|trim_user|
Returns
-------
:class:`~tweepy.models.Status`
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-unretweet-id
"""
return self.request(
'POST', f'statuses/unretweet/{id}', endpoint_parameters=(
'trim_user',
), **kwargs
)
@payload('status')
def update_status(self, status, **kwargs):
"""update_status( \
status, *, in_reply_to_status_id, auto_populate_reply_metadata, \
exclude_reply_user_ids, attachment_url, media_ids, \
possibly_sensitive, lat, long, place_id, display_coordinates, \
trim_user, card_uri \
)
Updates the authenticating user's current status, also known as
Tweeting.
For each update attempt, the update text is compared with the
authenticating user's recent Tweets. Any attempt that would result in
duplication will be blocked, resulting in a 403 error. A user cannot
submit the same status twice in a row.
While not rate limited by the API, a user is limited in the number of
Tweets they can create at a time. If the number of updates posted by
the user reaches the current allowed limit this method will return an
HTTP 403 error.
Parameters
----------
status
The text of your status update.
in_reply_to_status_id
The ID of an existing status that the update is in reply to. Note:
This parameter will be ignored unless the author of the Tweet this
parameter references is mentioned within the status text.
Therefore, you must include @username, where username is the author
of the referenced Tweet, within the update.
auto_populate_reply_metadata
If set to true and used with in_reply_to_status_id, leading
@mentions will be looked up from the original Tweet, and added to
the new Tweet from there. This wil append @mentions into the
metadata of an extended Tweet as a reply chain grows, until the
limit on @mentions is reached. In cases where the original Tweet
has been deleted, the reply will fail.
exclude_reply_user_ids
When used with auto_populate_reply_metadata, a comma-separated list
of user ids which will be removed from the server-generated
@mentions prefix on an extended Tweet. Note that the leading
@mention cannot be removed as it would break the
in-reply-to-status-id semantics. Attempting to remove it will be
silently ignored.
attachment_url
In order for a URL to not be counted in the status body of an
extended Tweet, provide a URL as a Tweet attachment. This URL must
be a Tweet permalink, or Direct Message deep link. Arbitrary,
non-Twitter URLs must remain in the status text. URLs passed to the
attachment_url parameter not matching either a Tweet permalink or
Direct Message deep link will fail at Tweet creation and cause an
exception.
media_ids
A list of media_ids to associate with the Tweet. You may include up
to 4 photos or 1 animated GIF or 1 video in a Tweet.
possibly_sensitive
If you upload Tweet media that might be considered sensitive
content such as nudity, or medical procedures, you must set this
value to true.
lat
The latitude of the location this Tweet refers to. This parameter
will be ignored unless it is inside the range -90.0 to +90.0 (North
is positive) inclusive. It will also be ignored if there is no
corresponding long parameter.
long
The longitude of the location this Tweet refers to. The valid
ranges for longitude are -180.0 to +180.0 (East is positive)
inclusive. This parameter will be ignored if outside that range, if
it is not a number, if geo_enabled is disabled, or if there no
corresponding lat parameter.
place_id
A place in the world.
display_coordinates
Whether or not to put a pin on the exact coordinates a Tweet has
been sent from.
trim_user
|trim_user|
card_uri
Associate an ads card with the Tweet using the card_uri value from
any ads card response.
Returns
-------
:class:`~tweepy.models.Status`
References
----------
https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-update
"""
if 'media_ids' in kwargs:
kwargs['media_ids'] = list_to_csv(kwargs['media_ids'])
return self.request(
'POST', 'statuses/update', endpoint_parameters=(
'status', 'in_reply_to_status_id',
'auto_populate_reply_metadata', 'exclude_reply_user_ids',
'attachment_url', 'media_ids', 'possibly_sensitive', 'lat',
'long', 'place_id', 'display_coordinates', 'trim_user',
'card_uri'
), status=status, **kwargs
)
@payload('status')
def update_status_with_media(self, status, filename, *, file=None,
**kwargs):
"""update_status_with_media( \
status, filename, *, file, possibly_sensitive, \
in_reply_to_status_id, lat, long, place_id, display_coordinates \
)
Update the authenticated user's status. Statuses that are duplicates or
too long will be silently ignored.
.. deprecated:: 3.7.0