tweepy-self 1.10.0b1__tar.gz → 1.10.0b3__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/PKG-INFO +2 -2
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/pyproject.toml +2 -2
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/client.py +89 -47
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/README.md +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/__init__.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/_capsolver/__init__.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/_capsolver/core/__init__.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/_capsolver/core/base.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/_capsolver/core/config.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/_capsolver/core/enum.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/_capsolver/core/serializer.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/_capsolver/fun_captcha.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/account.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/base/__init__.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/base/client.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/base/session.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/enums.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/errors.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/models.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/utils/__init__.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/utils/file.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/utils/html.py +0 -0
- {tweepy_self-1.10.0b1 → tweepy_self-1.10.0b3}/twitter/utils/other.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: tweepy-self
|
3
|
-
Version: 1.10.
|
3
|
+
Version: 1.10.0b3
|
4
4
|
Summary: Twitter (selfbot) for Python!
|
5
5
|
Home-page: https://github.com/alenkimov/tweepy-self
|
6
6
|
Author: Alen
|
@@ -15,7 +15,7 @@ Requires-Dist: better-proxy (>=1.1,<2.0)
|
|
15
15
|
Requires-Dist: curl_cffi (==0.6.2)
|
16
16
|
Requires-Dist: loguru (>=0.7,<0.8)
|
17
17
|
Requires-Dist: lxml (>=5,<6)
|
18
|
-
Requires-Dist: pydantic (>=
|
18
|
+
Requires-Dist: pydantic (>=2)
|
19
19
|
Requires-Dist: pyotp (>=2,<3)
|
20
20
|
Requires-Dist: requests (>=2,<3)
|
21
21
|
Requires-Dist: tenacity (>=8,<9)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "tweepy-self"
|
3
|
-
version = "1.10.0.
|
3
|
+
version = "1.10.0.b3"
|
4
4
|
description = "Twitter (selfbot) for Python!"
|
5
5
|
authors = ["Alen <alen.kimov@gmail.com>"]
|
6
6
|
readme = "README.md"
|
@@ -15,7 +15,7 @@ python = "^3.11"
|
|
15
15
|
curl_cffi = "0.6.2"
|
16
16
|
better-proxy = "^1.1"
|
17
17
|
beautifulsoup4 = "^4"
|
18
|
-
pydantic = ">=
|
18
|
+
pydantic = ">=2"
|
19
19
|
lxml = "^5"
|
20
20
|
pyotp = "^2"
|
21
21
|
yarl = "^1"
|
@@ -52,7 +52,7 @@ class Client(BaseHTTPClient):
|
|
52
52
|
"CreateRetweet": "ojPdsZsimiJrUGLR1sjUtA",
|
53
53
|
"FavoriteTweet": "lI07N6Otwv1PhnEgXILM7A",
|
54
54
|
"UnfavoriteTweet": "ZYKSe-w7KEslx3JhSIk5LA",
|
55
|
-
"CreateTweet": "
|
55
|
+
"CreateTweet": "v0en1yVV-Ybeek8ClmXwYw",
|
56
56
|
"TweetResultByRestId": "V3vfsYzNEyD9tsf4xoFRgw",
|
57
57
|
"ModerateTweet": "p'jF:GVqCjTcZol0xcBJjw",
|
58
58
|
"DeleteTweet": "VaenaVgh5q5ih7kvyVjgtg",
|
@@ -159,7 +159,7 @@ class Client(BaseHTTPClient):
|
|
159
159
|
auth_token = self._session.cookies.get("auth_token")
|
160
160
|
if auth_token and auth_token != self.account.auth_token:
|
161
161
|
self.account.auth_token = auth_token
|
162
|
-
logger.
|
162
|
+
logger.warning(
|
163
163
|
f"(auth_token={self.account.hidden_auth_token}, id={self.account.id}, username={self.account.username})"
|
164
164
|
f" Requested new auth_token!"
|
165
165
|
)
|
@@ -239,7 +239,7 @@ class Client(BaseHTTPClient):
|
|
239
239
|
reset_time = int(response.headers["x-rate-limit-reset"])
|
240
240
|
sleep_time = reset_time - int(time()) + 1
|
241
241
|
if sleep_time > 0:
|
242
|
-
logger.
|
242
|
+
logger.warning(
|
243
243
|
f"(auth_token={self.account.hidden_auth_token}, id={self.account.id}, username={self.account.username})"
|
244
244
|
f"Rate limited! Sleep time: {sleep_time} sec."
|
245
245
|
)
|
@@ -290,7 +290,7 @@ class Client(BaseHTTPClient):
|
|
290
290
|
|
291
291
|
except Forbidden as exc:
|
292
292
|
if 353 in exc.api_codes and "ct0" in exc.response.cookies:
|
293
|
-
return await self.
|
293
|
+
return await self.request(method, url, **kwargs)
|
294
294
|
else:
|
295
295
|
raise
|
296
296
|
|
@@ -426,7 +426,7 @@ class Client(BaseHTTPClient):
|
|
426
426
|
response, response_json = await self.request("POST", url)
|
427
427
|
self.account.username = response_json["screen_name"]
|
428
428
|
|
429
|
-
async def _request_user(self, username: str) -> User:
|
429
|
+
async def _request_user(self, username: str) -> User | None:
|
430
430
|
url, query_id = self._action_to_url("UserByScreenName")
|
431
431
|
username = remove_at_sign(username)
|
432
432
|
variables = {
|
@@ -454,26 +454,39 @@ class Client(BaseHTTPClient):
|
|
454
454
|
"fieldToggles": to_json(field_toggles),
|
455
455
|
}
|
456
456
|
response, data = await self.request("GET", url, params=params)
|
457
|
+
if not data["data"]:
|
458
|
+
return None
|
457
459
|
return User.from_raw_data(data["data"]["user"]["result"])
|
458
460
|
|
459
461
|
async def request_user(
|
460
462
|
self, *, username: str = None, user_id: int | str = None
|
461
|
-
) -> User | Account:
|
463
|
+
) -> User | Account | None:
|
464
|
+
"""
|
465
|
+
Возвращает None, если задано несуществующее имя пользователя
|
466
|
+
"""
|
462
467
|
if username and user_id:
|
463
468
|
raise ValueError("Specify username or user_id, not both.")
|
464
469
|
|
465
470
|
if user_id:
|
466
471
|
users = await self.request_users((user_id,))
|
467
472
|
user = users[user_id]
|
473
|
+
elif username:
|
474
|
+
user = await self._request_user(username)
|
468
475
|
else:
|
469
|
-
if not username:
|
470
|
-
|
471
|
-
await self.request_and_set_username()
|
472
|
-
username = self.account.username
|
476
|
+
if not self.account.username:
|
477
|
+
await self.request_and_set_username()
|
473
478
|
|
474
|
-
user = await self._request_user(username)
|
479
|
+
user = await self._request_user(self.account.username)
|
480
|
+
|
481
|
+
if not user:
|
482
|
+
bad_username = self.account.username
|
483
|
+
await self.request_and_set_username()
|
484
|
+
user = await self._request_user(self.account.username)
|
485
|
+
logger.warning(
|
486
|
+
f"(auth_token={self.account.hidden_auth_token}, id={self.account.id}, username={self.account.username})"
|
487
|
+
f" Bad username: {bad_username}. Requested a real username."
|
488
|
+
)
|
475
489
|
|
476
|
-
if self.account.username == user.username:
|
477
490
|
self.account.update(**user.model_dump())
|
478
491
|
user = self.account
|
479
492
|
|
@@ -606,6 +619,8 @@ class Client(BaseHTTPClient):
|
|
606
619
|
"""
|
607
620
|
Repost (retweet)
|
608
621
|
|
622
|
+
Иногда может вернуть ошибку 404 (Not Found), если плохой прокси или по другим неизвестным причинам
|
623
|
+
|
609
624
|
:return: Tweet
|
610
625
|
"""
|
611
626
|
return await self._repost_or_search_duplicate(
|
@@ -613,9 +628,18 @@ class Client(BaseHTTPClient):
|
|
613
628
|
)
|
614
629
|
|
615
630
|
async def like(self, tweet_id: int) -> bool:
|
616
|
-
|
617
|
-
|
618
|
-
|
631
|
+
"""
|
632
|
+
:return: Liked or not
|
633
|
+
"""
|
634
|
+
try:
|
635
|
+
response_json = await self._interact_with_tweet("FavoriteTweet", tweet_id)
|
636
|
+
except HTTPException as exc:
|
637
|
+
if 139 in exc.api_codes:
|
638
|
+
# Already liked
|
639
|
+
return True
|
640
|
+
else:
|
641
|
+
raise
|
642
|
+
return response_json["data"]["favorite_tweet"] == "Done"
|
619
643
|
|
620
644
|
async def unlike(self, tweet_id: int) -> dict:
|
621
645
|
response_json = await self._interact_with_tweet("UnfavoriteTweet", tweet_id)
|
@@ -662,47 +686,50 @@ class Client(BaseHTTPClient):
|
|
662
686
|
attachment_url: str = None,
|
663
687
|
) -> Tweet:
|
664
688
|
url, query_id = self._action_to_url("CreateTweet")
|
665
|
-
|
666
|
-
"
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
"semantic_annotation_ids": [],
|
671
|
-
},
|
672
|
-
"features": {
|
673
|
-
"tweetypie_unmention_optimization_enabled": True,
|
674
|
-
"responsive_web_edit_tweet_api_enabled": True,
|
675
|
-
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": True,
|
676
|
-
"view_counts_everywhere_api_enabled": True,
|
677
|
-
"longform_notetweets_consumption_enabled": True,
|
678
|
-
"tweet_awards_web_tipping_enabled": False,
|
679
|
-
"longform_notetweets_rich_text_read_enabled": True,
|
680
|
-
"longform_notetweets_inline_media_enabled": True,
|
681
|
-
"responsive_web_graphql_exclude_directive_enabled": True,
|
682
|
-
"verified_phone_label_enabled": False,
|
683
|
-
"freedom_of_speech_not_reach_fetch_enabled": True,
|
684
|
-
"standardized_nudges_misinfo": True,
|
685
|
-
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": False,
|
686
|
-
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": False,
|
687
|
-
"responsive_web_graphql_timeline_navigation_enabled": True,
|
688
|
-
"responsive_web_enhance_cards_enabled": False,
|
689
|
-
"responsive_web_twitter_article_tweet_consumption_enabled": False,
|
690
|
-
"responsive_web_media_download_video_enabled": False,
|
691
|
-
},
|
692
|
-
"queryId": query_id,
|
689
|
+
variables = {
|
690
|
+
"tweet_text": text if text is not None else "",
|
691
|
+
"dark_request": False,
|
692
|
+
"media": {"media_entities": [], "possibly_sensitive": False},
|
693
|
+
"semantic_annotation_ids": [],
|
693
694
|
}
|
694
695
|
if attachment_url:
|
695
|
-
|
696
|
+
variables["attachment_url"] = attachment_url
|
696
697
|
if tweet_id_to_reply:
|
697
|
-
|
698
|
+
variables["reply"] = {
|
698
699
|
"in_reply_to_tweet_id": str(tweet_id_to_reply),
|
699
700
|
"exclude_reply_user_ids": [],
|
700
701
|
}
|
701
702
|
if media_id:
|
702
|
-
|
703
|
+
variables["media"]["media_entities"].append(
|
703
704
|
{"media_id": str(media_id), "tagged_users": []}
|
704
705
|
)
|
705
|
-
|
706
|
+
features = {
|
707
|
+
"communities_web_enable_tweet_community_results_fetch": True,
|
708
|
+
"c9s_tweet_anatomy_moderator_badge_enabled": True,
|
709
|
+
"tweetypie_unmention_optimization_enabled": True,
|
710
|
+
"responsive_web_edit_tweet_api_enabled": True,
|
711
|
+
"graphql_is_translatable_rweb_tweet_is_translatable_enabled": True,
|
712
|
+
"view_counts_everywhere_api_enabled": True,
|
713
|
+
"longform_notetweets_consumption_enabled": True,
|
714
|
+
"responsive_web_twitter_article_tweet_consumption_enabled": True,
|
715
|
+
"tweet_awards_web_tipping_enabled": False,
|
716
|
+
"longform_notetweets_rich_text_read_enabled": True,
|
717
|
+
"longform_notetweets_inline_media_enabled": True,
|
718
|
+
"rweb_video_timestamps_enabled": True,
|
719
|
+
"responsive_web_graphql_exclude_directive_enabled": True,
|
720
|
+
"verified_phone_label_enabled": False,
|
721
|
+
"freedom_of_speech_not_reach_fetch_enabled": True,
|
722
|
+
"standardized_nudges_misinfo": True,
|
723
|
+
"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": True,
|
724
|
+
"responsive_web_graphql_skip_user_profile_image_extensions_enabled": False,
|
725
|
+
"responsive_web_graphql_timeline_navigation_enabled": True,
|
726
|
+
"responsive_web_enhance_cards_enabled": False,
|
727
|
+
}
|
728
|
+
payload = {
|
729
|
+
"variables": variables,
|
730
|
+
"features": features,
|
731
|
+
"queryId": query_id,
|
732
|
+
}
|
706
733
|
response, response_json = await self.request("POST", url, json=payload)
|
707
734
|
tweet = Tweet.from_raw_data(
|
708
735
|
response_json["data"]["create_tweet"]["tweet_results"]["result"]
|
@@ -754,6 +781,11 @@ class Client(BaseHTTPClient):
|
|
754
781
|
media_id: int | str = None,
|
755
782
|
search_duplicate: bool = True,
|
756
783
|
) -> Tweet:
|
784
|
+
"""
|
785
|
+
Иногда может вернуть ошибку 404 (Not Found), если плохой прокси или по другим неизвестным причинам
|
786
|
+
|
787
|
+
:return: Tweet
|
788
|
+
"""
|
757
789
|
return await self._tweet_or_search_duplicate(
|
758
790
|
text,
|
759
791
|
media_id=media_id,
|
@@ -768,6 +800,11 @@ class Client(BaseHTTPClient):
|
|
768
800
|
media_id: int | str = None,
|
769
801
|
search_duplicate: bool = True,
|
770
802
|
) -> Tweet:
|
803
|
+
"""
|
804
|
+
Иногда может вернуть ошибку 404 (Not Found), если плохой прокси или по другим неизвестным причинам
|
805
|
+
|
806
|
+
:return: Tweet
|
807
|
+
"""
|
771
808
|
return await self._tweet_or_search_duplicate(
|
772
809
|
text,
|
773
810
|
media_id=media_id,
|
@@ -783,6 +820,11 @@ class Client(BaseHTTPClient):
|
|
783
820
|
media_id: int | str = None,
|
784
821
|
search_duplicate: bool = True,
|
785
822
|
) -> Tweet:
|
823
|
+
"""
|
824
|
+
Иногда может вернуть ошибку 404 (Not Found), если плохой прокси или по другим неизвестным причинам
|
825
|
+
|
826
|
+
:return: Tweet
|
827
|
+
"""
|
786
828
|
return await self._tweet_or_search_duplicate(
|
787
829
|
text,
|
788
830
|
media_id=media_id,
|
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
|
File without changes
|
File without changes
|