tweepy-self 1.2.1__py3-none-any.whl → 1.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tweepy-self
3
- Version: 1.2.1
3
+ Version: 1.3.0
4
4
  Summary: Twitter (selfbot) for Python!
5
5
  Author: Alen
6
6
  Author-email: alen.kimov@gmail.com
@@ -1,15 +1,15 @@
1
1
  twitter/__init__.py,sha256=hdrsdbH_qFhx6ro1ct79qF9SpkgFhxgbYUw9A4RVuec,684
2
- twitter/account.py,sha256=5y19GkinhpUC319w5cpOMV1Y06afSObVQMURgaWjneA,3320
2
+ twitter/account.py,sha256=jneBaUSQ8dfHjOZFvs0qhVNg6EM6ChFIg6-Ee7DWXXM,3278
3
3
  twitter/base/__init__.py,sha256=x0EHKv4q_FI6xEq2nL4V9s8P6VWr6IaHTqdH9sXB5d8,133
4
4
  twitter/base/client.py,sha256=7byb0Psai-dvg_ww6Y7uyE2hV1pfTU653hFgVdRiqXo,478
5
5
  twitter/base/session.py,sha256=5aMjCytV_cu-uouccJzjMUPIgXZwMElPkqb7FCawmfg,2055
6
- twitter/client.py,sha256=1uhlNaB6_qKae0JyTvt_kWJQqHADzKSpKU7seiFsNsM,53016
7
- twitter/errors.py,sha256=U6kGyNp_5tEq-RwxLjm61muJLEp5BYBq9vrPBkCxr_g,4088
6
+ twitter/client.py,sha256=WvwxVd273LjPtuyMPX69j42fJNxsK5nVFI4W4YACE1s,53674
7
+ twitter/errors.py,sha256=2Co_XtXk9KwKVL89MyMIzRUT9Jaoy6hwzHxrokEOuAs,4122
8
8
  twitter/models.py,sha256=3-Lft160msCqOjRPubOmxMqWUkmjlTSzHSGsvZK91nU,1817
9
9
  twitter/utils/__init__.py,sha256=pyhQXwTdp0HFwV_UNF4dTyklLD9RtaefA16SrQXeNlg,589
10
10
  twitter/utils/file.py,sha256=-6n8I8KWDlntfciJJsfIeOi0gmqoHRIe1ldIx1ynGUE,1118
11
11
  twitter/utils/html.py,sha256=Cs55MxVyZLSKiCEj11ALUrnCW9ADZ4CEDCE0gKESzO0,1627
12
12
  twitter/utils/other.py,sha256=4NaGd2CIJVrDiW17shcrDlJRqFkQNbBSTiiH7kNWcww,559
13
- tweepy_self-1.2.1.dist-info/METADATA,sha256=IQTOzYa9xI3sozUwaM20A53int0AgWVfEkPsRnOHDGc,9139
14
- tweepy_self-1.2.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
15
- tweepy_self-1.2.1.dist-info/RECORD,,
13
+ tweepy_self-1.3.0.dist-info/METADATA,sha256=a4Iwl5zvqRiA3lFSvY_3eLnoVPLVDNccmk9R3wNIuNM,9139
14
+ tweepy_self-1.3.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
15
+ tweepy_self-1.3.0.dist-info/RECORD,,
twitter/account.py CHANGED
@@ -21,14 +21,14 @@ class AccountStatus(enum.StrEnum):
21
21
 
22
22
  class Account(BaseModel):
23
23
  auth_token: str | None = Field(default=None, pattern=r"^[a-f0-9]{40}$")
24
- ct0: str | None
25
- id: int | None
26
- name: str | None
27
- username: str | None
28
- password: str | None
29
- email: str | None
30
- totp_secret: str | None = Field(default=None, pattern=r"^[a-f0-9]{12}$")
31
- backup_code: str | None = Field(default=None, pattern=r"^[A-Z0-9]{16}$")
24
+ ct0: str | None = None
25
+ id: int | None = None
26
+ name: str | None = None
27
+ username: str | None = None
28
+ password: str | None = None
29
+ email: str | None = None
30
+ totp_secret: str | None = None
31
+ backup_code: str | None = None
32
32
  status: AccountStatus = AccountStatus.UNKNOWN
33
33
 
34
34
  @property
twitter/client.py CHANGED
@@ -36,7 +36,7 @@ class Client(BaseClient):
36
36
  'authority': 'twitter.com',
37
37
  'origin': 'https://twitter.com',
38
38
  'x-twitter-active-user': 'yes',
39
- # 'x-twitter-auth-type': 'OAuth2Session',
39
+ 'x-twitter-auth-type': 'OAuth2Session',
40
40
  'x-twitter-client-language': 'en',
41
41
  }
42
42
  _GRAPHQL_URL = 'https://twitter.com/i/api/graphql'
@@ -73,11 +73,15 @@ class Client(BaseClient):
73
73
  account: Account,
74
74
  *,
75
75
  wait_on_rate_limit: bool = True,
76
+ capsolver_api_key: str = None,
77
+ max_unlock_attempts: int = 4,
76
78
  **session_kwargs,
77
79
  ):
78
80
  super().__init__(**session_kwargs)
79
81
  self.account = account
80
82
  self.wait_on_rate_limit = wait_on_rate_limit
83
+ self.capsolver_api_key = capsolver_api_key
84
+ self.max_unlock_attempts = max_unlock_attempts
81
85
 
82
86
  async def request(
83
87
  self,
@@ -148,7 +152,11 @@ class Client(BaseClient):
148
152
 
149
153
  if 326 in exc.api_codes:
150
154
  self.account.status = AccountStatus.LOCKED
151
- raise Locked(self.account)
155
+ if not self.capsolver_api_key:
156
+ raise Locked(self.account)
157
+
158
+ await self.unlock()
159
+ return await self.request(method, url, auth, bearer, **kwargs)
152
160
 
153
161
  raise exc
154
162
 
@@ -170,7 +178,11 @@ class Client(BaseClient):
170
178
 
171
179
  if 326 in exc.api_codes:
172
180
  self.account.status = AccountStatus.LOCKED
173
- raise Locked(self.account)
181
+ if not self.capsolver_api_key:
182
+ raise Locked(self.account)
183
+
184
+ await self.unlock()
185
+ return await self.request(method, url, auth, bearer, **kwargs)
174
186
 
175
187
  raise exc
176
188
 
@@ -722,6 +734,8 @@ class Client(BaseClient):
722
734
  is_updated = all(response_json.get(key) == value for key, value in data.items() if key != "url")
723
735
  if website: is_updated &= URL(website) == URL(response_json["entities"]["url"]["urls"][0]["expanded_url"])
724
736
  await self.establish_status() # Изменение данных профиля часто замораживает аккаунт
737
+ await self.unlock()
738
+ await self.request_user_data()
725
739
  return is_updated
726
740
 
727
741
  async def establish_status(self):
@@ -888,11 +902,7 @@ class Client(BaseClient):
888
902
 
889
903
  return await self.request("POST", self._CAPTCHA_URL, data=payload, bearer=False)
890
904
 
891
- async def unlock(
892
- self,
893
- capsolver_api_key: str,
894
- attempts: int = 4):
895
- await self.establish_status()
905
+ async def unlock(self):
896
906
  if not self.account.status == "LOCKED":
897
907
  return
898
908
 
@@ -901,7 +911,7 @@ class Client(BaseClient):
901
911
  attempt = 1
902
912
 
903
913
  funcaptcha = {
904
- "api_key": capsolver_api_key,
914
+ "api_key": self.capsolver_api_key,
905
915
  "websiteURL": self._CAPTCHA_URL,
906
916
  "websitePublicKey": self._CAPTCHA_SITE_KEY,
907
917
  }
@@ -921,7 +931,7 @@ class Client(BaseClient):
921
931
  response, html = await self._confirm_unlock(authenticity_token, assignment_token,
922
932
  verification_string=token)
923
933
 
924
- if attempt > attempts or response.url == "https://twitter.com/?lang=en":
934
+ if attempt > self.max_unlock_attempts or response.url == "https://twitter.com/?lang=en":
925
935
  await self.establish_status()
926
936
  return
927
937
 
@@ -1034,10 +1044,6 @@ class Client(BaseClient):
1034
1044
  return await self._send_task(flow_token, subtask_inputs, auth=False)
1035
1045
 
1036
1046
  async def _viewer(self):
1037
- """
1038
- Здесь нужно забрать ct0
1039
- :return:
1040
- """
1041
1047
  url, query_id = self._action_to_url("Viewer")
1042
1048
  features = {
1043
1049
  'responsive_web_graphql_exclude_directive_enabled': True,
@@ -1066,6 +1072,8 @@ class Client(BaseClient):
1066
1072
  """
1067
1073
  url = 'https://twitter.com'
1068
1074
  response = await self._session.request("GET", url)
1075
+ # TODO Если в сессии есть рабочий auth_token, то не вернет нужную страницу.
1076
+ # Поэтому нужно очищать сессию перед вызовом этого метода.
1069
1077
  guest_token = re.search(r'gt\s?=\s?\d+', response.text)[0].split('=')[1]
1070
1078
  return guest_token
1071
1079
 
twitter/errors.py CHANGED
@@ -41,7 +41,7 @@ class BadToken(BadAccount):
41
41
 
42
42
  class Locked(BadAccount):
43
43
  def __init__(self, account: Account):
44
- exception_message = f"Twitter account is locked. Captcha required to unlock."
44
+ exception_message = (f"Twitter account is locked. Paste CapSolver API key into Client instance to autounlock.")
45
45
  super().__init__(account, custom_exception_message=exception_message)
46
46
 
47
47