Skip to main content

Unofficial Twitter and Discord API

Project description

Better Site Automation

Telegram channel PyPI version info PyPI supported Python versions

pip install better-automation
  • Unofficial Twitter and Discord API

More libraries of the family:

BaseSession

Взаимодействие с Twitter происходит через слегка модифицированную асинхронную сессию из библиотеки curl_cffi.

Вот так можно создать сессию с прокси:

from better_automation.base import BaseAsyncSession

async def main():
  async with BaseAsyncSession(proxy="http://login:password@host:port") as session:
    ...

Если вы работаете под Windows, то может потребоваться дополнительная настройка перед совершением запросов (подробнее):

import sys, asyncio

def set_windows_event_loop_policy():
    if sys.version_info >= (3, 8) and sys.platform.lower().startswith("win"):
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

set_windows_event_loop_policy()

Если вы имеете проблемы с SSL сертификатами, то задайте параметр verify=False для сессии:

async with BaseAsyncSession(verify=False) as session:
    ...

Пример работы сессией:

import sys
import asyncio
from pprint import pprint

from better_automation.base import BaseAsyncSession


PROXY = None  # "http://login:password@host:port"


def set_windows_event_loop_policy():
    if sys.version_info >= (3, 8) and sys.platform.lower().startswith("win"):
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())


async def curl_cffi_example(proxy: str = None):
    async with BaseAsyncSession(proxy=proxy, verify=False) as session:
        response = await session.get("https://ipapi.co/json")
        response_json = response.json()
        print(f"{response_json['ip']} {response_json['country_name']}")
        
        response = await session.get("https://tls.browserleaks.com/json")
        response_json = response.json()
        pprint(response_json)


if __name__ == '__main__':
    set_windows_event_loop_policy()
    asyncio.run(curl_cffi_example(PROXY))

В дальнейшем работать напрямую с сессией не придется. Клиенты для Twitter и Discord сами создадут сессию внутри себя.

Twitter

Библиотека позволяет работать с неофициальным API Twitter.

А именно:

  • Привязывать сервисы (приложения).
  • Устанавливать статус аккаунта (бан, лок).
  • Загружать изображения на сервер и изменять баннер и аватарку.
  • Изменять данные о пользователе: имя, описание профиля и другое.
  • Изменять имя пользователя и пароль.
  • Запрашивать информацию о подписчиках.
  • Запрашивать некоторую информацию о пользователе (количество подписчиков и другое).
  • Голосовать.
  • Подписываться и отписываться.
  • Лайкать и дизлайкать.
  • Твиттить, ретвиттить с изображением и без.
  • Закреплять твиты.
  • Удалять твиты.
  • ...

TwitterAccount

Аккаунт представляет собой контейнер для следующих данных:

  • Токены авторизации: auth_token и x-csrf-token (ct0).
  • Имя пользователя (username) и пароль.
  • ID пользователя.

Аккаунт можно создать из auth_token'а, cookies в формате JSON или base64:

from better_automation.twitter import TwitterAccount

# Аккаунту можно задать пароль (требуется для смены пароля)
account = TwitterAccount("auth_token", password="password")
account = TwitterAccount.from_cookies("JSON cookies")
account = TwitterAccount.from_cookies("base64 cookies", base64=True)

Аккаунты можно загрузить напрямую из файла:

accounts = TwitterAccount.from_file("twitter_auth_tokens.txt")
accounts = TwitterAccount.from_file("twitter_json_cookies.txt", cookies=True)
accounts = TwitterAccount.from_file("twitter_base64_cookies.txt", cookies=True, base64=True)

После любого взаимодействия с Twitter устанавливается статус аккаунта:

  • BAD_TOKEN - Неверный токен.
  • UNKNOWN - Статус аккаунта не установлен.
  • SUSPENDED - Действие учетной записи приостановлено (бан).
  • LOCKED - Учетная запись заморожена (лок) (требуется прохождение капчи).
  • GOOD - Аккаунт в порядке.

TwitterClient

Для взаимодействия с Twitter нужно создать экземпляр класса TwitterClient, передав в него аккаунт.

В клиента можно передавать параметры сессии, включая:

  • Прокси в формате http://login:password@host:port.
  • verify=False для отключения проверки SSL сертификатов.
from better_automation.twitter import TwitterAccount, TwitterClient

account = TwitterAccount("auth_token", password="password")
proxy = "http://login:password@host:port"

async with TwitterClient(account, proxy=proxy, verify=False) as twitter:
    ...

Примеры работы

Список доступных методов:

  • bind_app(**bind_data) -> bind_code Привязка (авторизация) стороннего сервиса
  • upload_image(image) -> media_id
  • tweet(text, media_id)
  • repost(tweet_id)
  • quote(tweet_url, text, media_id)
  • reply(tweet_id, text, media_id)
  • like(tweet_id)
  • unlike(tweet_id)
  • follow(user_id)
  • unfollow(user_id)
  • pin_tweet(tweet_id)
  • delete_tweet(tweet_id)
  • change_password(password)
  • change_username(username)
  • update_profile(name, description, location)
  • update_profile_banner(media_id)
  • update_profile_avatar(media_id)
  • request_user_data(username) -> UserData
  • request_followings(user_id) -> list[UserData]
  • request_followers(user_id) -> list[UserData]

Демонстрационные скрипты (папка examples/twitter)`:

  • Установка статуса аккаунтов (проверка на блокировку, заморозку)
  • Голосование

Запрос информации о пользователе:

# Запрос информации о текущем пользователе:
me = await twitter.request_user_data()
print(f"[{account.short_auth_token}] {me}")
print(f"Аккаунт создан: {me.created_at}")
print(f"Following (подписан ты): {me.followings_count}")
print(f"Followers (подписаны на тебя): {me.followers_count}")
print(f"Прочая информация: {me.raw_data}")

# Запрос информации об ином пользователе:
elonmusk = await twitter.request_user_data("@elonmusk")
print(elonmusk)

Смена имени пользователя и пароля:

account = TwitterAccount("auth_token", password="password")
...
await twitter.change_username("new_username")
await twitter.request_user_data()
print(f"New username: {account.data.username}")

await twitter.change_password("new_password")
print(f"New password: {account.password}")
print(f"New auth_token: {account.auth_token}")

Смена данных профиля:

await twitter.update_birthdate(day=1, month=12, year=2000)
await twitter.update_profile(  # Locks account!
    name="New Name",
    description="New description",
    location="New York",
    website="https://github.com/alenkimov/better_automation",
)

Загрузка изображений и смена аватара и баннера:

image = open(f"image.png", "rb").read()
media_id = await twitter.upload_image(image)
avatar_image_url = await twitter.update_profile_avatar(media_id)
banner_image_url = await twitter.update_profile_banner(media_id)

Привязка сервиса (приложения):

# Изучите запросы сервиса и найдите подобные данные для авторизации (привязки):
bind_data = {
    'response_type': 'code',
    'client_id': 'TjFVQm52ZDFGWEtNT0tKaktaSWU6MTpjaQ',
    'redirect_uri': 'https://waitlist.lens.xyz/tw/',
    'scope': 'users.read tweet.read offline.access',
    'state': 'state',  # Может быть как статичным, так и динамическим.
    'code_challenge': 'challenge',
    'code_challenge_method': 'plain'
}

bind_code = await twitter.bind_app(**bind_data)
# Передайте код авторизации (привязки) сервису.
# Сервис также может потребовать state, если он динамический.

Отправка сообщения:

bro = await twitter.request_user_data("@username")
await twitter.send_message(bro.id, "I love you!")

Запрос входящих сообщений:

messages = await twitter.request_messages()
for message in messages:
    message_data = message["message_data"]
    recipient_id = message_data["recipient_id"]
    sender_id = message_data["sender_id"]
    text = message_data["text"]
    print(f"[id  {sender_id}] -> [id {recipient_id}]: {text}")

Другие методы:

# Выражение любви через твит
tweet_id = await twitter.tweet("I love YOU! !!!!1!1")
print(f"Любовь выражена! Tweet id: {tweet_id}")

print(f"Tweet is pined: {await twitter.pin_tweet(tweet_id)}")

# Лайк
print(f"Tweet {tweet_id} is liked: {await twitter.like(tweet_id)}")

# Репост (ретвит)
print(f"Tweet {tweet_id} is retweeted. Tweet id: {await twitter.repost(tweet_id)}")

# Коммент (реплай)
print(f"Tweet {tweet_id} is replied. Reply id: {await twitter.reply(tweet_id, 'tem razão')}")

# Подписываемся на Илона Маска
print(f"@{elonmusk.username} is followed: {await twitter.follow(elonmusk.id)}")

# Отписываемся от Илона Маска
print(f"@{elonmusk.username} is unfollowed: {await twitter.unfollow(elonmusk.id)}")

tweet_url = 'https://twitter.com/CreamIce_Cone/status/1691735090529976489'
# Цитата (Quote tweet)
quote_tweet_id = await twitter.quote(tweet_url, 'oh....')
print(f"Quoted! Tweet id: {quote_tweet_id}")

# Запрашиваем первых трех подписчиков
# (Параметр count по каким-то причинам работает некорректно)
followers = await twitter.request_followers(count=20)
print("Твои подписчики:")
for follower in followers:
    print(follower)

Discord

Библиотека позволяет работать с неофициальным API Discord.

А именно:

  • Привязывать сервисы (приложения).
  • Ловить флаги аккаунта (спаммер, карантин).
  • Отправлять сообщения на сервер. Ставить реакции.
  • Нажимать кнопки на сервере. (не тестировалось!)

DiscordAccount

Аккаунт представляет собой контейнер для следующих данных:

  • Токен авторизации.
  • Имя пользователя (username) и пароль.

Аккаунт можно создать из токена авторизации:

from better_automation.discord import DiscordAccount

account = DiscordAccount("auth_token")

Аккаунты можно загрузить напрямую из файла:

accounts = DiscordAccount.from_file("discord_tokens.txt")

После любого взаимодействия с Discord устанавливается статус аккаунта:

  • BAD_TOKEN - Неверный токен.
  • UNKNOWN - Статус аккаунта не установлен.
  • BANNED - Бан.
  • GOOD - Аккаунт в порядке.

Баны сейчас не отлавливаются. Зато отлавливается статус BAD_TOKEN.

DiscordClient

Для взаимодействия с Discord нужно создать экземпляр класса DiscordClient, передав в него аккаунт.

В клиента можно передавать параметры сессии, включая:

  • Прокси в формате http://login:password@host:port.
  • verify=False для отключения проверки SSL сертификатов.
from better_automation.discord import DiscordAccount, DiscordClient

account = DiscordAccount("auth_token", password="password")
proxy = "http://login:password@host:port"

async with DiscordClient(account, proxy=proxy, verify=False) as discord:
    ...

Примеры работы

Список доступных методов:

  • bind_app(**bind_data) -> bind_code Привязка (авторизация) стороннего сервиса
  • request_messages и request_message
  • press_button
  • send_reaction
  • send_guild_chat_message

Привязка сервиса (приложения):

# Изучите запросы сервиса и найдите подобные данные для авторизации (привязки):
BIND_DATA = {
    'client_id': '986938000388796468',
    'response_type': 'code',
    'scope': 'identify guilds guilds.members.read',
}

# Привязка приложения
bind_code = await discord.bind_app(**bind_data)
print(f"Bind code: {bind_code}")

# Передайте код авторизации (привязки) сервису.
# Сервис также может потребовать state, если он динамический.

Не реализовано

Credits

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

better_automation-2.0.0.tar.gz (86.1 kB view hashes)

Uploaded Source

Built Distribution

better_automation-2.0.0-py3-none-any.whl (39.4 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page