tweepy-self 1.11.0__tar.gz → 1.11.1__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/PKG-INFO +1 -1
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/pyproject.toml +1 -1
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/account.py +1 -1
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/base/session.py +4 -3
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/client.py +39 -36
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/README.md +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/__init__.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/_capsolver/__init__.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/_capsolver/core/__init__.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/_capsolver/core/base.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/_capsolver/core/config.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/_capsolver/core/enum.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/_capsolver/core/serializer.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/_capsolver/fun_captcha.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/base/__init__.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/base/client.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/enums.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/errors.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/models.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/utils/__init__.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/utils/file.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/utils/html.py +0 -0
- {tweepy_self-1.11.0 → tweepy_self-1.11.1}/twitter/utils/other.py +0 -0
@@ -14,13 +14,14 @@ class BaseAsyncSession(requests.AsyncSession):
|
|
14
14
|
DEFAULT_HEADERS = {
|
15
15
|
"accept": "*/*",
|
16
16
|
"accept-language": "en-US,en",
|
17
|
-
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
18
|
-
|
17
|
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
|
18
|
+
'Priority': 'u=1, i',
|
19
|
+
"sec-ch-ua": '"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"',
|
19
20
|
"sec-ch-ua-platform": '"Windows"',
|
20
21
|
"sec-ch-ua-mobile": "?0",
|
21
22
|
"sec-fetch-dest": "empty",
|
22
23
|
"sec-fetch-mode": "cors",
|
23
|
-
"sec-fetch-site": "
|
24
|
+
"sec-fetch-site": "ssame-site",
|
24
25
|
"connection": "keep-alive",
|
25
26
|
}
|
26
27
|
DEFAULT_IMPERSONATE = requests.BrowserType.chrome120
|
@@ -41,17 +41,17 @@ from .utils import (
|
|
41
41
|
class Client(BaseHTTPClient):
|
42
42
|
_BEARER_TOKEN = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA"
|
43
43
|
_DEFAULT_HEADERS = {
|
44
|
-
"authority": "
|
45
|
-
"origin": "https://
|
44
|
+
"authority": "x.com",
|
45
|
+
"origin": "https://x.com",
|
46
46
|
"x-twitter-active-user": "yes",
|
47
47
|
"x-twitter-client-language": "en",
|
48
48
|
}
|
49
|
-
_GRAPHQL_URL = "https://
|
49
|
+
_GRAPHQL_URL = "https://x.com/i/api/graphql"
|
50
50
|
_ACTION_TO_QUERY_ID = {
|
51
51
|
"CreateRetweet": "ojPdsZsimiJrUGLR1sjUtA",
|
52
52
|
"FavoriteTweet": "lI07N6Otwv1PhnEgXILM7A",
|
53
53
|
"UnfavoriteTweet": "ZYKSe-w7KEslx3JhSIk5LA",
|
54
|
-
"CreateTweet": "
|
54
|
+
"CreateTweet": "oB-5XsHNAbjvARJEc8CZFw",
|
55
55
|
"TweetResultByRestId": "V3vfsYzNEyD9tsf4xoFRgw",
|
56
56
|
"ModerateTweet": "p'jF:GVqCjTcZol0xcBJjw",
|
57
57
|
"DeleteTweet": "VaenaVgh5q5ih7kvyVjgtg",
|
@@ -62,9 +62,9 @@ class Client(BaseHTTPClient):
|
|
62
62
|
"Followers": "3yX7xr2hKjcZYnXt6cU6lQ",
|
63
63
|
"UserByScreenName": "G3KGOASz96M-Qu0nwmGXNg",
|
64
64
|
"UsersByRestIds": "itEhGywpgX9b3GJCzOtSrA",
|
65
|
-
"Viewer": "
|
65
|
+
"Viewer": "-876iyxD1O_0X0BqeykjZA",
|
66
66
|
}
|
67
|
-
_CAPTCHA_URL = "https://
|
67
|
+
_CAPTCHA_URL = "https://x.com/account/access"
|
68
68
|
_CAPTCHA_SITE_KEY = "0152B4EB-D2DC-460A-89A1-629838B529C9"
|
69
69
|
|
70
70
|
@classmethod
|
@@ -111,9 +111,8 @@ class Client(BaseHTTPClient):
|
|
111
111
|
wait_on_rate_limit: bool = None,
|
112
112
|
**kwargs,
|
113
113
|
) -> tuple[requests.Response, Any]:
|
114
|
-
cookies = kwargs["cookies"] = kwargs.get("cookies"
|
115
|
-
headers = kwargs["headers"] = kwargs.get("headers"
|
116
|
-
|
114
|
+
cookies = kwargs["cookies"] = kwargs.get("cookies", {})
|
115
|
+
headers = kwargs["headers"] = kwargs.get("headers", {})
|
117
116
|
if bearer:
|
118
117
|
headers["authorization"] = f"Bearer {self._BEARER_TOKEN}"
|
119
118
|
|
@@ -159,7 +158,7 @@ class Client(BaseHTTPClient):
|
|
159
158
|
f"\nResponse data: {data}")
|
160
159
|
# fmt: on
|
161
160
|
|
162
|
-
if ct0 := self._session.cookies.get("ct0", domain=".
|
161
|
+
if ct0 := self._session.cookies.get("ct0", domain=".x.com"):
|
163
162
|
self.account.ct0 = ct0
|
164
163
|
|
165
164
|
auth_token = self._session.cookies.get("auth_token")
|
@@ -327,7 +326,7 @@ class Client(BaseHTTPClient):
|
|
327
326
|
scope: str,
|
328
327
|
response_type: str,
|
329
328
|
) -> str:
|
330
|
-
url = "https://
|
329
|
+
url = "https://x.com/i/api/2/oauth2/authorize"
|
331
330
|
querystring = {
|
332
331
|
"client_id": client_id,
|
333
332
|
"code_challenge": code_challenge,
|
@@ -349,7 +348,7 @@ class Client(BaseHTTPClient):
|
|
349
348
|
headers = {"content-type": "application/x-www-form-urlencoded"}
|
350
349
|
await self.request(
|
351
350
|
"POST",
|
352
|
-
"https://
|
351
|
+
"https://x.com/i/api/2/oauth2/authorize",
|
353
352
|
headers=headers,
|
354
353
|
data=data,
|
355
354
|
)
|
@@ -393,7 +392,7 @@ class Client(BaseHTTPClient):
|
|
393
392
|
|
394
393
|
:return: Response: html страница привязки приложения (аутентификации) старого типа.
|
395
394
|
"""
|
396
|
-
url = "https://api.
|
395
|
+
url = "https://api.x.com/oauth/authenticate"
|
397
396
|
oauth_params["oauth_token"] = oauth_token
|
398
397
|
response, _ = await self.request("GET", url, params=oauth_params)
|
399
398
|
|
@@ -411,7 +410,7 @@ class Client(BaseHTTPClient):
|
|
411
410
|
authenticity_token: str,
|
412
411
|
redirect_after_login_url: str,
|
413
412
|
) -> requests.Response:
|
414
|
-
url = "https://api.
|
413
|
+
url = "https://api.x.com/oauth/authorize"
|
415
414
|
params = {
|
416
415
|
"redirect_after_login": redirect_after_login_url,
|
417
416
|
"authenticity_token": authenticity_token,
|
@@ -441,7 +440,7 @@ class Client(BaseHTTPClient):
|
|
441
440
|
return authenticity_token, redirect_url
|
442
441
|
|
443
442
|
async def _update_account_username(self):
|
444
|
-
url = "https://
|
443
|
+
url = "https://x.com/i/api/1.1/account/settings.json"
|
445
444
|
response, response_json = await self.request("POST", url)
|
446
445
|
self.account.username = response_json["screen_name"]
|
447
446
|
|
@@ -556,7 +555,7 @@ class Client(BaseHTTPClient):
|
|
556
555
|
|
557
556
|
:return: Media
|
558
557
|
"""
|
559
|
-
url = "https://upload.
|
558
|
+
url = "https://upload.x.com/1.1/media/upload.json"
|
560
559
|
payload = {"media_data": base64.b64encode(image)}
|
561
560
|
for attempt in range(attempts):
|
562
561
|
try:
|
@@ -581,7 +580,7 @@ class Client(BaseHTTPClient):
|
|
581
580
|
raise
|
582
581
|
|
583
582
|
async def _follow_action(self, action: str, user_id: int | str) -> bool:
|
584
|
-
url = f"https://
|
583
|
+
url = f"https://x.com/i/api/1.1/friendships/{action}.json"
|
585
584
|
params = {
|
586
585
|
"include_profile_interstitial_type": "1",
|
587
586
|
"include_blocking": "1",
|
@@ -711,7 +710,7 @@ class Client(BaseHTTPClient):
|
|
711
710
|
return is_deleted
|
712
711
|
|
713
712
|
async def pin_tweet(self, tweet_id: str | int) -> bool:
|
714
|
-
url = "https://api.
|
713
|
+
url = "https://api.x.com/1.1/account/pin_tweet.json"
|
715
714
|
data = {
|
716
715
|
"tweet_mode": "extended",
|
717
716
|
"id": str(tweet_id),
|
@@ -761,9 +760,12 @@ class Client(BaseHTTPClient):
|
|
761
760
|
"longform_notetweets_consumption_enabled": True,
|
762
761
|
"responsive_web_twitter_article_tweet_consumption_enabled": True,
|
763
762
|
"tweet_awards_web_tipping_enabled": False,
|
763
|
+
"creator_subscriptions_quote_tweet_preview_enabled": False,
|
764
764
|
"longform_notetweets_rich_text_read_enabled": True,
|
765
765
|
"longform_notetweets_inline_media_enabled": True,
|
766
|
+
"articles_preview_enabled": True,
|
766
767
|
"rweb_video_timestamps_enabled": True,
|
768
|
+
"rweb_tipjar_consumption_enabled": True,
|
767
769
|
"responsive_web_graphql_exclude_directive_enabled": True,
|
768
770
|
"verified_phone_label_enabled": False,
|
769
771
|
"freedom_of_speech_not_reach_fetch_enabled": True,
|
@@ -886,7 +888,7 @@ class Client(BaseHTTPClient):
|
|
886
888
|
"""
|
887
889
|
:return: Raw vote information
|
888
890
|
"""
|
889
|
-
url = "https://caps.
|
891
|
+
url = "https://caps.x.com/v2/capi/passthrough/1"
|
890
892
|
params = {
|
891
893
|
"twitter:string:card_uri": f"card://{card_id}",
|
892
894
|
"twitter:long:original_tweet_id": str(tweet_id),
|
@@ -1101,7 +1103,7 @@ class Client(BaseHTTPClient):
|
|
1101
1103
|
"""
|
1102
1104
|
:return: Image URL
|
1103
1105
|
"""
|
1104
|
-
url = f"https://api.
|
1106
|
+
url = f"https://api.x.com/1.1/account/update_profile_{type}.json"
|
1105
1107
|
params = {
|
1106
1108
|
"media_id": str(media_id),
|
1107
1109
|
"include_profile_interstitial_type": "1",
|
@@ -1136,7 +1138,7 @@ class Client(BaseHTTPClient):
|
|
1136
1138
|
return await self._update_profile_image("banner", media_id)
|
1137
1139
|
|
1138
1140
|
async def change_username(self, username: str) -> bool:
|
1139
|
-
url = "https://
|
1141
|
+
url = "https://x.com/i/api/1.1/account/settings.json"
|
1140
1142
|
payload = {"screen_name": username}
|
1141
1143
|
response, data = await self.request("POST", url, data=payload)
|
1142
1144
|
new_username = data["screen_name"]
|
@@ -1151,7 +1153,7 @@ class Client(BaseHTTPClient):
|
|
1151
1153
|
if not self.account.password:
|
1152
1154
|
raise ValueError(f"Specify the current password before changing it")
|
1153
1155
|
|
1154
|
-
url = "https://
|
1156
|
+
url = "https://x.com/i/api/i/account/change_password.json"
|
1155
1157
|
payload = {
|
1156
1158
|
"current_password": self.account.password,
|
1157
1159
|
"password": password,
|
@@ -1175,7 +1177,7 @@ class Client(BaseHTTPClient):
|
|
1175
1177
|
if name is None and description is None:
|
1176
1178
|
raise ValueError("Specify at least one param")
|
1177
1179
|
|
1178
|
-
url = "https://
|
1180
|
+
url = "https://x.com/i/api/1.1/account/update_profile.json"
|
1179
1181
|
# Создаем словарь data, включая в него только те ключи, для которых значения не равны None
|
1180
1182
|
payload = {
|
1181
1183
|
k: v
|
@@ -1200,7 +1202,7 @@ class Client(BaseHTTPClient):
|
|
1200
1202
|
return updated
|
1201
1203
|
|
1202
1204
|
async def establish_status(self):
|
1203
|
-
url = "https://
|
1205
|
+
url = "https://x.com/i/api/1.1/account/update_profile.json"
|
1204
1206
|
try:
|
1205
1207
|
await self.request("POST", url, auto_unlock=False, auto_relogin=False)
|
1206
1208
|
self.account.status = AccountStatus.GOOD
|
@@ -1215,7 +1217,7 @@ class Client(BaseHTTPClient):
|
|
1215
1217
|
visibility: Literal["self", "mutualfollow"] = "self",
|
1216
1218
|
year_visibility: Literal["self"] = "self",
|
1217
1219
|
) -> bool:
|
1218
|
-
url = "https://
|
1220
|
+
url = "https://x.com/i/api/1.1/account/update_profile.json"
|
1219
1221
|
payload = {
|
1220
1222
|
"birthdate_day": day,
|
1221
1223
|
"birthdate_month": month,
|
@@ -1240,7 +1242,7 @@ class Client(BaseHTTPClient):
|
|
1240
1242
|
"""
|
1241
1243
|
:return: Event data
|
1242
1244
|
"""
|
1243
|
-
url = "https://api.
|
1245
|
+
url = "https://api.x.com/1.1/direct_messages/events/new.json"
|
1244
1246
|
payload = {
|
1245
1247
|
"event": {
|
1246
1248
|
"type": "message_create",
|
@@ -1262,7 +1264,7 @@ class Client(BaseHTTPClient):
|
|
1262
1264
|
|
1263
1265
|
:return: Event data
|
1264
1266
|
"""
|
1265
|
-
url = f"https://api.
|
1267
|
+
url = f"https://api.x.com/2/dm_conversations/{conversation_id}/messages"
|
1266
1268
|
payload = {"text": text}
|
1267
1269
|
response, response_json = await self.request("POST", url, json=payload)
|
1268
1270
|
event_data = response_json["event"]
|
@@ -1272,7 +1274,7 @@ class Client(BaseHTTPClient):
|
|
1272
1274
|
"""
|
1273
1275
|
:return: Messages data
|
1274
1276
|
"""
|
1275
|
-
url = "https://
|
1277
|
+
url = "https://x.com/i/api/1.1/dm/inbox_initial_state.json"
|
1276
1278
|
params = {
|
1277
1279
|
"nsfw_filtering_enabled": "false",
|
1278
1280
|
"filter_low_quality": "false",
|
@@ -1414,7 +1416,7 @@ class Client(BaseHTTPClient):
|
|
1414
1416
|
verification_string=token,
|
1415
1417
|
)
|
1416
1418
|
|
1417
|
-
if response.url == "https://
|
1419
|
+
if response.url == "https://x.com/?lang=en":
|
1418
1420
|
break
|
1419
1421
|
|
1420
1422
|
(
|
@@ -1444,7 +1446,7 @@ class Client(BaseHTTPClient):
|
|
1444
1446
|
await self.establish_status()
|
1445
1447
|
|
1446
1448
|
async def update_backup_code(self):
|
1447
|
-
url = "https://api.
|
1449
|
+
url = "https://api.x.com/1.1/account/backup_code.json"
|
1448
1450
|
response, response_json = await self.request("GET", url)
|
1449
1451
|
self.account.backup_code = response_json["codes"][0]
|
1450
1452
|
|
@@ -1452,7 +1454,7 @@ class Client(BaseHTTPClient):
|
|
1452
1454
|
"""
|
1453
1455
|
:return: flow_token and subtasks
|
1454
1456
|
"""
|
1455
|
-
url = "https://api.
|
1457
|
+
url = "https://api.x.com/1.1/onboarding/task.json"
|
1456
1458
|
response, data = await self.request("POST", url, **request_kwargs)
|
1457
1459
|
subtasks = [
|
1458
1460
|
Subtask.from_raw_data(subtask_data) for subtask_data in data["subtasks"]
|
@@ -1629,6 +1631,7 @@ class Client(BaseHTTPClient):
|
|
1629
1631
|
async def _viewer(self):
|
1630
1632
|
url, query_id = self._action_to_url("Viewer")
|
1631
1633
|
features = {
|
1634
|
+
"rweb_tipjar_consumption_enabled": True,
|
1632
1635
|
"responsive_web_graphql_exclude_directive_enabled": True,
|
1633
1636
|
"verified_phone_label_enabled": False,
|
1634
1637
|
"creator_subscriptions_tweet_preview_api_enabled": True,
|
@@ -1655,7 +1658,7 @@ class Client(BaseHTTPClient):
|
|
1655
1658
|
"""
|
1656
1659
|
response, data = await self._request(
|
1657
1660
|
"POST",
|
1658
|
-
"https://api.
|
1661
|
+
"https://api.x.com/1.1/guest/activate.json",
|
1659
1662
|
auth=False,
|
1660
1663
|
)
|
1661
1664
|
return data["guest_token"]
|
@@ -1753,6 +1756,7 @@ class Client(BaseHTTPClient):
|
|
1753
1756
|
else:
|
1754
1757
|
raise
|
1755
1758
|
|
1759
|
+
await self._viewer()
|
1756
1760
|
await self._complete_subtask(flow_token, [])
|
1757
1761
|
return update_backup_code
|
1758
1762
|
|
@@ -1770,7 +1774,6 @@ class Client(BaseHTTPClient):
|
|
1770
1774
|
raise ValueError("No password")
|
1771
1775
|
|
1772
1776
|
update_backup_code = await self._login()
|
1773
|
-
await self._viewer()
|
1774
1777
|
|
1775
1778
|
if update_backup_code:
|
1776
1779
|
await self.update_backup_code()
|
@@ -1794,7 +1797,7 @@ class Client(BaseHTTPClient):
|
|
1794
1797
|
if not self.account.id:
|
1795
1798
|
await self.update_account_info()
|
1796
1799
|
|
1797
|
-
url = f"https://
|
1800
|
+
url = f"https://x.com/i/api/1.1/strato/column/User/{self.account.id}/account-security/twoFactorAuthSettings2"
|
1798
1801
|
response, data = await self.request("GET", url)
|
1799
1802
|
# fmt: off
|
1800
1803
|
return "Totp" in [method_data["twoFactorType"] for method_data in data["methods"]]
|
@@ -1949,7 +1952,7 @@ class Client(BaseHTTPClient):
|
|
1949
1952
|
|
1950
1953
|
|
1951
1954
|
class GQLClient:
|
1952
|
-
_GRAPHQL_URL = "https://
|
1955
|
+
_GRAPHQL_URL = "https://x.com/i/api/graphql"
|
1953
1956
|
_OPERATION_TO_QUERY_ID = {
|
1954
1957
|
"CreateRetweet": "ojPdsZsimiJrUGLR1sjUtA",
|
1955
1958
|
"FavoriteTweet": "lI07N6Otwv1PhnEgXILM7A",
|
@@ -1965,7 +1968,7 @@ class GQLClient:
|
|
1965
1968
|
"Followers": "3yX7xr2hKjcZYnXt6cU6lQ",
|
1966
1969
|
"UserByScreenName": "G3KGOASz96M-Qu0nwmGXNg",
|
1967
1970
|
"UsersByRestIds": "itEhGywpgX9b3GJCzOtSrA",
|
1968
|
-
"Viewer": "
|
1971
|
+
"Viewer": "-876iyxD1O_0X0BqeykjZA",
|
1969
1972
|
}
|
1970
1973
|
_DEFAULT_VARIABLES = {
|
1971
1974
|
"count": 1000,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|