tweepy-self 1.9.0__py3-none-any.whl → 1.10.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- tweepy_self-1.10.0.dist-info/METADATA +306 -0
- {tweepy_self-1.9.0.dist-info → tweepy_self-1.10.0.dist-info}/RECORD +10 -10
- twitter/_capsolver/core/serializer.py +1 -1
- twitter/account.py +5 -5
- twitter/base/client.py +3 -3
- twitter/client.py +577 -295
- twitter/errors.py +13 -7
- twitter/models.py +36 -25
- twitter/utils/html.py +6 -2
- tweepy_self-1.9.0.dist-info/METADATA +0 -225
- {tweepy_self-1.9.0.dist-info → tweepy_self-1.10.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,306 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: tweepy-self
|
3
|
+
Version: 1.10.0
|
4
|
+
Summary: Twitter (selfbot) for Python!
|
5
|
+
Home-page: https://github.com/alenkimov/tweepy-self
|
6
|
+
Author: Alen
|
7
|
+
Author-email: alen.kimov@gmail.com
|
8
|
+
Requires-Python: >=3.11,<4.0
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
12
|
+
Requires-Dist: aiohttp (>=3.9,<4.0)
|
13
|
+
Requires-Dist: beautifulsoup4 (>=4,<5)
|
14
|
+
Requires-Dist: better-proxy (>=1.1,<2.0)
|
15
|
+
Requires-Dist: curl_cffi (==0.6.2)
|
16
|
+
Requires-Dist: loguru (>=0.7,<0.8)
|
17
|
+
Requires-Dist: lxml (>=5,<6)
|
18
|
+
Requires-Dist: pydantic (>=2,<3)
|
19
|
+
Requires-Dist: pyotp (>=2,<3)
|
20
|
+
Requires-Dist: requests (>=2,<3)
|
21
|
+
Requires-Dist: tenacity (>=8,<9)
|
22
|
+
Requires-Dist: yarl (>=1,<2)
|
23
|
+
Project-URL: Repository, https://github.com/alenkimov/tweepy-self
|
24
|
+
Project-URL: Source, https://github.com/alenkimov/tweepy-self
|
25
|
+
Description-Content-Type: text/markdown
|
26
|
+
|
27
|
+
# Tweepy-self
|
28
|
+
[](https://t.me/cum_insider)
|
29
|
+
[](https://pypi.python.org/pypi/tweepy-self)
|
30
|
+
[](https://pypi.python.org/pypi/tweepy-self)
|
31
|
+
[](https://pypi.python.org/pypi/tweepy-self)
|
32
|
+
|
33
|
+
A modern, easy to use, feature-rich, and async ready API wrapper for Twitter's user API written in Python.
|
34
|
+
|
35
|
+
_NEW!_ Менеджер аккаунтов с базой данных:
|
36
|
+
- [tweepy-manager](https://github.com/alenkimov/tweepy-manager)
|
37
|
+
|
38
|
+
More libraries of the family:
|
39
|
+
- [better-proxy](https://github.com/alenkimov/better_proxy)
|
40
|
+
- [better-web3](https://github.com/alenkimov/better_web3)
|
41
|
+
|
42
|
+
Отдельное спасибо [Кузнице Ботов](https://t.me/bots_forge) за код для авторизации и разморозки! Подписывайтесь на их Telegram :)
|
43
|
+
|
44
|
+
## Key Features
|
45
|
+
- Modern Pythonic API using async and await.
|
46
|
+
- Prevents user account automation detection.
|
47
|
+
|
48
|
+
## Installing
|
49
|
+
```bash
|
50
|
+
pip install tweepy-self
|
51
|
+
```
|
52
|
+
|
53
|
+
## Example
|
54
|
+
```python
|
55
|
+
import asyncio
|
56
|
+
import twitter
|
57
|
+
|
58
|
+
twitter_account = twitter.Account(auth_token="auth_token")
|
59
|
+
|
60
|
+
async def main():
|
61
|
+
async with twitter.Client(twitter_account) as twitter_client:
|
62
|
+
print(f"Logged in as @{twitter_account.username} (id={twitter_account.id})")
|
63
|
+
tweet = await twitter_client.tweet("Hello tweepy-self! <3")
|
64
|
+
print(tweet)
|
65
|
+
|
66
|
+
if __name__ == "__main__":
|
67
|
+
asyncio.run(main())
|
68
|
+
```
|
69
|
+
|
70
|
+
## Документация
|
71
|
+
### Некоторые истины
|
72
|
+
Имена пользователей нужно передавать БЕЗ знака `@`.
|
73
|
+
Чтобы наверняка убрать этот знак можно передать имя пользователя в функцию `twitter.utils.remove_at_sign()`
|
74
|
+
|
75
|
+
Automating user accounts is against the Twitter ToS. This library is a proof of concept and I cannot recommend using it. Do so at your own risk
|
76
|
+
|
77
|
+
### Как включить логирование
|
78
|
+
```python
|
79
|
+
import sys
|
80
|
+
from loguru import logger
|
81
|
+
|
82
|
+
logger.remove()
|
83
|
+
logger.add(sys.stdout, level="INFO")
|
84
|
+
logger.enable("twitter")
|
85
|
+
```
|
86
|
+
|
87
|
+
`level="DEBUG"` позволяет увидеть информацию обо всех запросах.
|
88
|
+
|
89
|
+
### Аккаунт
|
90
|
+
После любого взаимодействия с Twitter устанавливается статус аккаунта:
|
91
|
+
- `UNKNOWN` - Статус аккаунта не установлен. Это статус по умолчанию.
|
92
|
+
- `BAD_TOKEN` - Неверный или мертвый токен.
|
93
|
+
- `SUSPENDED` - Действие учетной записи приостановлено. Тем не менее возможен запрос данных, а также авторизация через OAuth и OAuth2.
|
94
|
+
- `LOCKED` - Учетная запись заморожена (лок). Для разморозки (анлок) требуется прохождение капчи (funcaptcha).
|
95
|
+
- `CONSENT_LOCKED` - Учетная запись заморожена (лок). Условия для разморозки неизвестны.
|
96
|
+
- `GOOD` - Аккаунт в порядке.
|
97
|
+
|
98
|
+
Не каждое взаимодействие с Twitter достоверно определяет статус аккаунта.
|
99
|
+
Например, простой запрос данных об аккаунте честно вернет данные, даже если действие вашей учетной записи приостановлено.
|
100
|
+
|
101
|
+
Для достоверной установки статуса аккаунта используйте метод `Client.establish_status()`
|
102
|
+
|
103
|
+
### Настройка клиента
|
104
|
+
Класс `twitter.Client` может быть сконфигурирован перед работой. Он принимает в себя следующие параметры:
|
105
|
+
- `wait_on_rate_limit` Если включено, то при достижении Rate Limit будет ждать, вместо того, чтобы выбрасывать исключение. Включено по умолчанию.
|
106
|
+
- `capsolver_api_key` API ключ сервиса [CapSolver](https://dashboard.capsolver.com/passport/register?inviteCode=m-aE3NeBGZLU). Нужен для автоматической разморозки аккаунта.
|
107
|
+
- `max_unlock_attempts` Максимальное количество попыток разморозки аккаунта. По умолчанию: 5.
|
108
|
+
- `auto_relogin` Если включено, то при невалидном токене (`BAD_TOKEN`) и предоставленных данных для авторизации (имя пользователя, пароль и totp_secret) будет произведен автоматический релогин (замена токена). Включено по умолчанию.
|
109
|
+
- `update_account_info_on_startup` Если включено, то на старте будет автоматически запрошена информация об аккаунте. Включено по умолчанию.
|
110
|
+
- `**session_kwargs` Любые параметры, которые может принимать сессия `curl_cffi.requests.AsyncSession`. Например, можно передать параметр `proxy`.
|
111
|
+
|
112
|
+
Пример настройки клиента:
|
113
|
+
```python
|
114
|
+
async with twitter.Client(
|
115
|
+
twitter_account,
|
116
|
+
capsolver_api_key="CAP-00000000000000000000000000000000",
|
117
|
+
proxy="http://login:password@ip:port", # Можно передавать в любом формате, так как используется библиотека better_proxy
|
118
|
+
) as twitter_client:
|
119
|
+
...
|
120
|
+
```
|
121
|
+
|
122
|
+
### Доступные методы
|
123
|
+
Список всех методов.
|
124
|
+
|
125
|
+
#### Запрос информации о собственном аккаунте
|
126
|
+
```python
|
127
|
+
twitter_client.update_account_info()
|
128
|
+
print(twitter_client.account)
|
129
|
+
```
|
130
|
+
|
131
|
+
#### Запрос пользователя по username или по ID
|
132
|
+
|
133
|
+
```python
|
134
|
+
bro = twitter_client.request_user_by_username(bro_username)
|
135
|
+
bro = twitter_client.request_user_by_id(bro_id)
|
136
|
+
bros = twitter_client.request_users_by_ids([bro1_id, bro2_id, ...])
|
137
|
+
```
|
138
|
+
|
139
|
+
#### Загрузка изображения на сервер, смена аватарки и баннера
|
140
|
+
```python
|
141
|
+
image = open("image.png", "rb").read()
|
142
|
+
media = await twitter_client.upload_image(image)
|
143
|
+
avatar_image_url = await twitter_client.update_profile_avatar(media.id)
|
144
|
+
banner_image_url = await twitter_client.update_profile_banner(media.id)
|
145
|
+
```
|
146
|
+
|
147
|
+
#### Изменения данных профиля
|
148
|
+
```python
|
149
|
+
await twitter_client.update_birthdate(day=1, month=12, year=2000)
|
150
|
+
await twitter_client.update_profile( # Locks account!
|
151
|
+
name="New Name",
|
152
|
+
description="New description",
|
153
|
+
location="New York",
|
154
|
+
website="https://github.com/alenkimov/tweepy-self",
|
155
|
+
)
|
156
|
+
```
|
157
|
+
|
158
|
+
#### Включение TOTP (2FA)
|
159
|
+
```python
|
160
|
+
if await twitter_client.totp_is_enabled():
|
161
|
+
print(f"TOTP уже включен.")
|
162
|
+
return
|
163
|
+
|
164
|
+
await twitter_client.enable_totp()
|
165
|
+
```
|
166
|
+
|
167
|
+
#### Логин, если включен TOTP (2FA)
|
168
|
+
```python
|
169
|
+
import twitter
|
170
|
+
|
171
|
+
twitter_account = twitter.Account(auth_token="...", username="...", password="...", totp_secret="...")
|
172
|
+
await twitter_client.login()
|
173
|
+
print(f"Logged in! New auth_token: {twitter_account.auth_token}")
|
174
|
+
```
|
175
|
+
|
176
|
+
#### Смена имени пользователя и пароля
|
177
|
+
```python
|
178
|
+
twitter_account = twitter.Account("auth_token", password="password")
|
179
|
+
...
|
180
|
+
await twitter_client.change_username("new_username")
|
181
|
+
await twitter_client.request_user()
|
182
|
+
print(f"New username: {twitter_account.username}")
|
183
|
+
|
184
|
+
await twitter_client.change_password("new_password")
|
185
|
+
print(f"New password: {twitter_account.password}")
|
186
|
+
print(f"New auth_token: {twitter_account.auth_token}")
|
187
|
+
```
|
188
|
+
|
189
|
+
#### Авторизация с OAuth
|
190
|
+
```python
|
191
|
+
auth_code = await twitter_client.oauth(oauth_token, **oauth_params)
|
192
|
+
```
|
193
|
+
|
194
|
+
#### Авторизация с OAuth2
|
195
|
+
```python
|
196
|
+
# Изучите запросы сервиса и найдите подобные данные для авторизации (привязки):
|
197
|
+
oauth2_data = {
|
198
|
+
'response_type': 'code',
|
199
|
+
'client_id': 'TjFVQm52ZDFGWEtNT0tKaktaSWU6MTpjaQ',
|
200
|
+
'redirect_uri': 'https://waitlist.lens.xyz/tw/',
|
201
|
+
'scope': 'users.read tweet.read offline.access',
|
202
|
+
'state': 'state', # Может быть как статичным, так и динамическим.
|
203
|
+
'code_challenge': 'challenge',
|
204
|
+
'code_challenge_method': 'plain'
|
205
|
+
}
|
206
|
+
|
207
|
+
auth_code = await twitter_client.oauth2(**oauth2_data)
|
208
|
+
# Передайте код авторизации (привязки) сервису.
|
209
|
+
# Сервис также может потребовать state, если он динамический.
|
210
|
+
```
|
211
|
+
|
212
|
+
#### Отправка сообщения:
|
213
|
+
```python
|
214
|
+
bro = await twitter_client.request_user("bro_username")
|
215
|
+
await twitter_client.send_message(bro.id, "I love you!")
|
216
|
+
```
|
217
|
+
|
218
|
+
#### Запрос входящих сообщений:
|
219
|
+
```python
|
220
|
+
messages = await twitter_client.request_messages()
|
221
|
+
for message in messages:
|
222
|
+
message_data = message["message_data"]
|
223
|
+
recipient_id = message_data["recipient_id"]
|
224
|
+
sender_id = message_data["sender_id"]
|
225
|
+
text = message_data["text"]
|
226
|
+
print(f"[id {sender_id}] -> [id {recipient_id}]: {text}")
|
227
|
+
```
|
228
|
+
|
229
|
+
Так как мне почти не приходилось работать с сообщениями, я еще не сделал для этого удобных моделей.
|
230
|
+
Поэтому приходится работать со словарем.
|
231
|
+
|
232
|
+
#### Пост (твит)
|
233
|
+
```python
|
234
|
+
tweet = await twitter_client.tweet("I love you tweepy-self! <3")
|
235
|
+
print(f"Любовь выражена! Tweet id: {tweet.id}")
|
236
|
+
```
|
237
|
+
|
238
|
+
#### Лайк, репост (ретвит), коммент (реплай)
|
239
|
+
```python
|
240
|
+
# Лайк
|
241
|
+
print(f"Tweet {tweet_id} is liked: {await twitter_client.like(tweet_id)}")
|
242
|
+
|
243
|
+
# Репост (ретвит)
|
244
|
+
print(f"Tweet {tweet_id} is retweeted. Tweet id: {await twitter_client.repost(tweet_id)}")
|
245
|
+
|
246
|
+
# Коммент (реплай)
|
247
|
+
print(f"Tweet {tweet_id} is replied. Reply id: {await twitter_client.reply(tweet_id, 'tem razão')}")
|
248
|
+
```
|
249
|
+
|
250
|
+
#### Цитата
|
251
|
+
```python
|
252
|
+
tweet_url = 'https://twitter.com/CreamIce_Cone/status/1691735090529976489'
|
253
|
+
# Цитата (Quote tweet)
|
254
|
+
quote_tweet_id = await twitter_client.quote(tweet_url, 'oh....')
|
255
|
+
print(f"Quoted! Tweet id: {quote_tweet_id}")
|
256
|
+
```
|
257
|
+
|
258
|
+
#### Подписка и отписка
|
259
|
+
```python
|
260
|
+
# Подписываемся на Илона Маска
|
261
|
+
print(f"@{elonmusk.username} is followed: {await twitter_client.follow(elonmusk.id)}")
|
262
|
+
|
263
|
+
# Отписываемся от Илона Маска
|
264
|
+
print(f"@{elonmusk.username} is unfollowed: {await twitter_client.unfollow(elonmusk.id)}")
|
265
|
+
```
|
266
|
+
|
267
|
+
#### Закрепление твита
|
268
|
+
```python
|
269
|
+
pinned = await twitter_client.pin_tweet(tweet_id)
|
270
|
+
print(f"Tweet is pined: {pinned}")
|
271
|
+
```
|
272
|
+
|
273
|
+
#### Запрос своих и чужих подписчиков
|
274
|
+
```python
|
275
|
+
|
276
|
+
followers = await twitter_client.request_followers()
|
277
|
+
print("Твои подписчики:")
|
278
|
+
for user in followers:
|
279
|
+
print(user)
|
280
|
+
|
281
|
+
followings = await twitter_client.request_followings()
|
282
|
+
print(f"Ты подписан на:")
|
283
|
+
for user in followings:
|
284
|
+
print(user)
|
285
|
+
|
286
|
+
bro_followers = await twitter_client.request_followers(bro_id)
|
287
|
+
print(f"Подписчики твоего бро (id={bro_id}):")
|
288
|
+
for user in bro_followers:
|
289
|
+
print(user)
|
290
|
+
|
291
|
+
bro_followings = await twitter_client.request_followings(bro_id)
|
292
|
+
print(f"На твоего бро (id={bro_id}) подписаны:")
|
293
|
+
for user in bro_followings:
|
294
|
+
print(user)
|
295
|
+
```
|
296
|
+
|
297
|
+
#### Голосование
|
298
|
+
```python
|
299
|
+
vote_data = await twitter_client.vote(tweet_id, card_id, choice_number)
|
300
|
+
votes_count = vote_data["card"]["binding_values"]["choice1_count"]["string_value"]
|
301
|
+
print(f"Votes: {votes_count}")
|
302
|
+
```
|
303
|
+
|
304
|
+
Так как мне почти не приходилось работать с голосованиями, я еще не сделал для этого удобных моделей.
|
305
|
+
Поэтому приходится работать со словарем.
|
306
|
+
|
@@ -4,20 +4,20 @@ twitter/_capsolver/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
4
4
|
twitter/_capsolver/core/base.py,sha256=In3qDLgRh1z1UZLaLFgYcDEdnqW3d62PVzgEjU2S4BU,8883
|
5
5
|
twitter/_capsolver/core/config.py,sha256=8_eXT6N2hBheN2uCMNhqk8tLZRJjLDTYLK208fqIkhM,1054
|
6
6
|
twitter/_capsolver/core/enum.py,sha256=ivfAEN6jrg3iaq5C3H7CuRqsvOloX1b8lF8cLa3zaiY,1741
|
7
|
-
twitter/_capsolver/core/serializer.py,sha256=
|
7
|
+
twitter/_capsolver/core/serializer.py,sha256=xPEUIPgytuw2wM1ubTY3RMhJGVyp_d3bokPTx0BjF0c,2602
|
8
8
|
twitter/_capsolver/fun_captcha.py,sha256=VVbTmn08cGnvPMGdJmPxaLfAIPxyA68oTSAyEL8RWnU,10974
|
9
|
-
twitter/account.py,sha256=
|
9
|
+
twitter/account.py,sha256=joAB5Zw-Le5E3kOZ-1nb4DPGlTqWYv2Vs6gJ3cwu7is,3175
|
10
10
|
twitter/base/__init__.py,sha256=Q2ko0HeOS5tiBnDVKxxaZYetwRR3YXJ67ujL3oThGd4,141
|
11
|
-
twitter/base/client.py,sha256=
|
11
|
+
twitter/base/client.py,sha256=J_iL4ZGfwTbZ2gpjtFCbBxNgt7weJ55EeMGzYsLtjf4,500
|
12
12
|
twitter/base/session.py,sha256=JFPS-9Qae1iY3NfNcywxvWWmRDijaU_Rjs3WaQ00iFA,2071
|
13
|
-
twitter/client.py,sha256=
|
13
|
+
twitter/client.py,sha256=VZ9cymxz1KMSaqVTTFfCfuC1c5xZHdRUOD0XENSf53w,75555
|
14
14
|
twitter/enums.py,sha256=-OH6Ibxarq5qt4E2AhkProVawcEyIf5YG_h_G5xiV9Y,270
|
15
|
-
twitter/errors.py,sha256=
|
16
|
-
twitter/models.py,sha256=
|
15
|
+
twitter/errors.py,sha256=oNa0Neos80ZK4-0FBzqgxXonH564qFnoN-kavHalfR4,5274
|
16
|
+
twitter/models.py,sha256=CrGb3dvA0U4PfPTkUtuprPKXpqkLpM8AR_-De4D3efM,5677
|
17
17
|
twitter/utils/__init__.py,sha256=usxpfcRQ7zxTTgZ-i425tT7hIz73Pwh9FDj4t6O3dYg,663
|
18
18
|
twitter/utils/file.py,sha256=Sz2KEF9DnL04aOP1XabuMYMMF4VR8dJ_KWMEVvQ666Y,1120
|
19
|
-
twitter/utils/html.py,sha256=
|
19
|
+
twitter/utils/html.py,sha256=nrOJw0vUKfBaHgFaQSQIdXfvfZ8mdu84MU_s46kJTJ4,2087
|
20
20
|
twitter/utils/other.py,sha256=9RIYF2AMdmNKIwClG3jBP7zlvxZPEgYfuHaIiOhURzM,1061
|
21
|
-
tweepy_self-1.
|
22
|
-
tweepy_self-1.
|
23
|
-
tweepy_self-1.
|
21
|
+
tweepy_self-1.10.0.dist-info/METADATA,sha256=VxhYCaJLHUnrJTKxD8tnFVPtm8lTFCi0qQTG2wDXewo,13287
|
22
|
+
tweepy_self-1.10.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
23
|
+
tweepy_self-1.10.0.dist-info/RECORD,,
|
@@ -45,7 +45,7 @@ class CaptchaResponseSer(ResponseSer):
|
|
45
45
|
solution: Dict[str, Any] = Field(None, description="Task result data. Different for each type of task.")
|
46
46
|
|
47
47
|
class Config:
|
48
|
-
|
48
|
+
populate_by_name = True
|
49
49
|
|
50
50
|
|
51
51
|
class ControlResponseSer(ResponseSer):
|
twitter/account.py
CHANGED
@@ -12,11 +12,11 @@ from .models import User
|
|
12
12
|
class Account(User):
|
13
13
|
# fmt: off
|
14
14
|
auth_token: str | None = Field(default=None, pattern=r"^[a-f0-9]{40}$")
|
15
|
-
ct0: str | None = None
|
16
|
-
password: str | None = None
|
17
|
-
email: str | None = None
|
18
|
-
totp_secret: str | None = None
|
19
|
-
backup_code: str | None = None
|
15
|
+
ct0: str | None = None # 160
|
16
|
+
password: str | None = None # 128
|
17
|
+
email: str | None = None # 254
|
18
|
+
totp_secret: str | None = None # 16
|
19
|
+
backup_code: str | None = None # 12
|
20
20
|
status: AccountStatus = AccountStatus.UNKNOWN
|
21
21
|
# fmt: on
|
22
22
|
|
twitter/base/client.py
CHANGED