Еще один слабенький туториал, но мы не жалуемся.

небольшая предыстория: мне нравится создавать случайные фракталы (NFT любой). Я могу просто часами смотреть на один и видеть все разные вещи. так как лучше поделиться своими творениями? конечно, твиттер-бот, но давайте также заставим его делать что-то еще.

Предварительный просмотр

вы можете попробовать это сами, написав «создать сетку» на @machineation в твиттере. бот хэширует ваше имя пользователя, а затем использует его в качестве семени для создания уникальной цветовой сетки на основе имени пользователя. Давайте начнем.

требования:

  • питон >= 3.10
  • учетная запись разработчика Twitter (не рассматривается в руководстве)
  • щепетильный
  • пустышка
  • подушка

если вы не знакомы с учетной записью разработчика Twitter, пожалуйста Проверь это потому что создание учетной записи разработчика, приложения и получение аутентификации не рассматриваются в этом руководстве.

давайте начнем с установки необходимых пакетов. Не стесняйтесь использовать виртуальную среду или pip3, если у вас есть обе версии Python.

pip install tweepy numpy pillow
Войти в полноэкранный режим

Выйти из полноэкранного режима

после того, как все будет установлено, давайте создадим файл с именем «bot.py», но вы можете назвать свой как угодно, а затем давайте импортируем то, что нам нужно.

import tweepy, random, time, os, pathlib, numpy, hashlib
from PIL import Image
Войти в полноэкранный режим

Выйти из полноэкранного режима

после этого нам нужно добавить аутентификацию и создать объект API с помощью tweepy. вы можете прочитать о tweepy аутентификации в документы но, по сути, вам нужен ключ API, секрет ключа API, токен доступа и секрет токена доступа

ваши ключи секретны. не включайте их в сценарий и не загружайте в любое общедоступное облако. используйте .env или какой-либо другой метод для хранения секретов. для простоты, учебник не охватывает это

auth = tweepy.OAuthHandler("xxxx", "xxxx")
auth.set_access_token("xxxx", "xxxx")

#create API object
api = tweepy.API(auth, wait_on_rate_limit=True)
Войти в полноэкранный режим

Выйти из полноэкранного режима

  • wait_on_rate_limit – следует ли автоматически ожидать пополнения лимитов ставок.

Чтобы не отвечать на один и тот же твит несколько раз, а также получать только те упоминания, которые бот еще не видел, мы обязательно сохраним идентификатор последнего упоминания твита. Мы сохраним его в файл, чтобы даже если мы остановили бота, а затем возобновили, мы начали с тех упоминаний, которые мы еще не видели, а не с начала.
Создадим 2 функции. Один для чтения идентификатора из файла и один для хранения идентификатора.

def read_last_seen(FILE_NAME):
  file_read = open(FILE_NAME,'r')
  last_seen_id = int(file_read.read().strip())
  file_read.close()
  return last_seen_id

def store_last_seen(FILE_NAME, last_seen_id):
  file_write = open(FILE_NAME,'w')
  file_write.write(str(last_seen_id))
  file_write.write("\n")
  file_write.close()
  return
Войти в полноэкранный режим

Выйти из полноэкранного режима

Обратите внимание, что первая функция для чтения идентификатора принимает один параметр, который является именем файла, а функция для сохранения идентификатора принимает два параметра: имя файла и идентификатор. в будущем, если вы хотите иметь больше функций, которые хранят и считывают разные вещи, вы можете вызывать те же функции и изменять параметры, и мы, например, заменим «last_seen_id» на «данные».

Теперь давайте создадим функцию для создания сетки цветов из имени пользователя. Я решил закодировать это как отдельную функцию.

def make_grid(handle):
    hash = int(hashlib.sha256(handle.encode('utf-8')).hexdigest(), 16) % 10**8
    numpy.random.seed(hash)
    # Generate 100x100 grid of random colours
    grid = numpy.random.randint(0,256, (100,100,3), dtype=numpy.uint8)
    im = Image.fromarray(grid).resize((1600,1600), resample=Image.Resampling.NEAREST)

    im.save(os.path.join(os.path.dirname(__file__), "grids/") + handle + '.png')
Войти в полноэкранный режим

Выйти из полноэкранного режима

  • «handle»: параметр, который будет именем пользователя, которое мы передаем функции.
  • «hash»: мы будем хэшировать имя пользователя с помощью sha256, чтобы использовать его в качестве случайного семени для numpy.
  • «сетка»: используя numpy, мы создаем сетку со случайными цветами (с хешем имени пользователя). вы можете сделать его любого размера, который вы хотите.
  • «im»: использование подушки для создания изображения 1600×1600 из данных. вы можете использовать любой размер вы хотите.

Затем мы сохраняем изображение png в папке в том же каталоге с именем «сетки» с именем пользователя в качестве имени файла.

Следующий шаг, давайте создадим функцию, которая будет:

  1. Получить упоминания с момента последнего сохраненного идентификатора твита.
  2. Перебирайте упоминания.
  3. Сохраните идентификатор твита.
  4. Проверьте, не является ли твит нашим ботом.
  5. Проверьте, содержит ли твит определенные слова.
  6. Проверьте, не содержит ли твит лишних слов, и если да, то ответьте сообщением.
  7. Ответ на твит в зависимости от совпадающего слова.

это означает, что вы можете расширить бота, чтобы он выполнял другие действия на основе содержания твита (команды). Но сначала нам нужно установить некоторые переменные.

def grid_tweet():
    bot_id = xxxxxxxxxxxx
    FILE_NAME = os.path.join(os.path.dirname(__file__), "grid_last_seen.txt")
    words = ["make grid"]
    message = "Here is your unique color grid, @{}"
    grid_unknown = "@{} If you want a grid, You just need to tweet 'make grid' to Me without any other words and I will create and send You one."
Войти в полноэкранный режим

Выйти из полноэкранного режима

давайте пройдемся по ним:


bot_id

мы устанавливаем эту переменную, чтобы мы могли проверить, не является ли автор твита нашим ботом. таким образом мы гарантируем, что если наш бот написал в Твиттере те же слова, которые мы ищем, бот не ответит сам себе. вы можете получить идентификатор бота разными способами, но вот простой

Через браузер
вы можете перейти на страницу бота в твиттере, щелкнуть правой кнопкой мыши в любом месте страницы и нажать «Проверить», затем выполнить поиск «идентификатора» в элементах, которые будут выглядеть примерно так.

"identifier": "1572580999673831426"


ИМЯ ФАЙЛА

это файл, который мы будем использовать для чтения и хранения идентификатора последнего упоминания твита. Это будет использоваться для вызова уже созданных нами функций и передачи им переменной. Затем мы можем иметь разные файлы для разных функций, если захотим.


слова

Список слов, которые мы ищем. вы можете добавить больше через запятую. В нашем примере мы используем только «создать сетку».


сообщение

сообщение, которое мы собираемся включить в наш ответ. мы используем {} в конце, чтобы отформатировать его позже и добавить к нему имя пользователя.


grid_unknown

Еще одно сообщение, если в твите есть лишние слова помимо «сделать сетку». также используя {} для последующего форматирования с именем пользователя.

теперь давайте создадим остальную часть кода.

    while True:
        # Finding tweets that mention our bot
        mentions = api.mentions_timeline(since_id=read_last_seen(FILE_NAME)) 
        # Iterating through each mention tweet
        for mention in mentions:
            # Save the tweet id in the file
            store_last_seen(FILE_NAME, mention.id)
            # Check to see if the tweet author is not our bot
            if mention.author.id != bot_id:
                # Check if the tweet has any of the words we defined in our list after converting the tweet to lower case
                if True in [word in mention.text.lower() for word in words]:
                    # Removes the first part of the mention which is our bot username like so @username
                    command = mention.text.lower().split(' ',1)[1]
                    # Act based on the matched word/command. can later be used to add more functionality.
                    match command:
                        case "make grid":
                            try:
                                # Prints the username and tweet
                                print(f"{mention.author.screen_name} - {mention.text}")
                                print('Creating Grid')
                                # Calls our make_grid function and passing the username.
                                make_grid(mention.author.screen_name)
                                # Set the media to the image created by our function
                                media = os.path.join(os.path.dirname(__file__), "grids/") + mention.author.screen_name + '.png'
                                print("Attempting to reply...")
                                # Reply with the message after formatting to include username and the media
                                api.update_status_with_media(message.format(mention.author.screen_name), media, in_reply_to_status_id=mention.id_str)
                                print("Successfully replied :)")
                            # Error handling. for now it just prints the error.
                            except Exception as exc:
                                print(exc)
                        # If the tweet contains extra words in addition to our command
                        case other:
                            try:
                                print('tweet contains other words')
                                # Reply with the grid_unknown message
                                api.update_status(grid_unknown.format(mention.author.screen_name), in_reply_to_status_id=mention.id_str)
                                print("Successfully replied with explaination :)")
                            except Exception as exc:
                                print(exc)
        # Sleep for 2 minutes
        time.sleep(120)
Войти в полноэкранный режим

Выйти из полноэкранного режима

так что в конце наш файл будет выглядеть так:

import tweepy, random, time, os, pathlib, numpy, hashlib
from PIL import Image

auth = tweepy.OAuthHandler("xxxx", "xxxx")
auth.set_access_token("xxxx", "xxxx")

#create API object
api = tweepy.API(auth, wait_on_rate_limit=True)

def read_last_seen(FILE_NAME):
  file_read = open(FILE_NAME,'r')
  last_seen_id = int(file_read.read().strip())
  file_read.close()
  return last_seen_id

def store_last_seen(FILE_NAME, last_seen_id):
  file_write = open(FILE_NAME,'w')
  file_write.write(str(last_seen_id))
  file_write.write("\n")
  file_write.close()
  return    

def make_grid(handle):
    hash = int(hashlib.sha256(handle.encode('utf-8')).hexdigest(), 16) % 10**8
    numpy.random.seed(hash)
    # Generate 100x100 grid of random colours
    grid = numpy.random.randint(0,256, (100,100,3), dtype=numpy.uint8)
    im = Image.fromarray(grid).resize((1600,1600), resample=Image.Resampling.NEAREST)

    im.save(os.path.join(os.path.dirname(__file__), "grids/") + handle + '.png')
def grid_tweet():
    bot_id = xxxxxxxxxxxx
    FILE_NAME = os.path.join(os.path.dirname(__file__), "grid_last_seen.txt")
    words = ["make grid"]
    message = "Here is your unique color grid, @{}"
    grid_unknown = "@{} If you want a grid, You just need to tweet 'make grid' to Me without any other words and I will create and send You one."
    while True:
        # Finding tweets that mention our bot
        mentions = api.mentions_timeline(since_id=read_last_seen(FILE_NAME)) 
        # Iterating through each mention tweet
        for mention in mentions:
            # Save the tweet id in the file
            store_last_seen(FILE_NAME, mention.id)
            # Check to see if the tweet author is not our bot
            if mention.author.id != bot_id:
                # Check if the tweet has any of the words we defined in our list after converting the tweet to lower case
                if True in [word in mention.text.lower() for word in words]:
                    # Removes the first part of the mention which is our bot username like so @username
                    command = mention.text.lower().split(' ',1)[1]
                    # Act based on the matched word/command. can later be used to add more functionality.
                    match command:
                        case "make grid":
                            try:
                                # Prints the username and tweet
                                print(f"{mention.author.screen_name} - {mention.text}")
                                print('Creating Grid')
                                # Calls our make_grid function and passing the username.
                                make_grid(mention.author.screen_name)
                                # Set the media to the image created by our function
                                media = os.path.join(os.path.dirname(__file__), "grids/") + mention.author.screen_name + '.png'
                                print("Attempting to reply...")
                                # Reply with the message after formatting to include username and the media
                                api.update_status_with_media(message.format(mention.author.screen_name), media, in_reply_to_status_id=mention.id_str)
                                print("Successfully replied :)")
                            # Error handling. for now it just prints the error.
                            except Exception as exc:
                                print(exc)
                        # If the tweet contains extra words in addition to our command
                        case other:
                            try:
                                print('tweet contains other words')
                                # Reply with the grid_unknown message
                                api.update_status(grid_unknown.format(mention.author.screen_name), in_reply_to_status_id=mention.id_str)
                                print("Successfully replied with explaination :)")
                            except Exception as exc:
                                print(exc)
        # Sleep for 2 minutes
        time.sleep(120)

if __name__ == "__main__":
    print('The mighty Machineation is starting...')
    grid_tweet()
Войти в полноэкранный режим

Выйти из полноэкранного режима

и все.. теперь все, что вам нужно сделать, это начать с:
pyhton bot.py
и твитните своему боту с другой учетной записи, говоря «сделать сетку», и он должен ответить через пару минут с цветовой сеткой.