Сообщить об ошибке.

Работа с файлами/media, модуль python-telegram-bot в Python

Приемы работы с файлами, media и URL-адресами

В разделе рассмотрены примеры сниппетов, для работы с файлами, медиа и URL-адресами при создании Telegram бота с помощью пакета python-telegram-bot.

Внимание! Пакеты python-telegram-bot версии 13.x будут придерживаться многопоточной парадигмы программирования (*на данный момент актуальна версия 13.15). Пакеты версий 20.x и новее предоставляют чистый асинхронный Python интерфейс для Telegram Bot API. Дополнительно смотрите основные изменения в пакете python-telegram-bot версии 20.x.

Здесь рассматривается методы экземпляра bot = telegram.Bot(). Если при создании бота используется пакет расширения telegram.ext, то методы объекта bot будут доступны через:

  • updater.bot - это экземпляр telegram.Bot, связанный с экземпляром Updater, который присылает и отправляет все сообщения;
  • в функции обратного вызова через контекст context.bot - это telegram.Bot связанный с контекстом обработанного сообщения.

Например:

from telegram.ext import Updater, CommandHandler
TOKEN = 'Замените строку на Ваш token'
updater = Updater(token=TOKEN)
dispatcher = updater.dispatcher

# экземпляр `telegram.Bot`, связанный с экземпляром `Updater`
updater.bot.send_photo(...)

# методы `telegram.Bot` доступны через `context` 
def call_back(update, context):
    ...
    # `telegram.Bot` связанный с контекстом 
    # обработанного сообщения
    context.bot.send_photo(...)
...
dispatcher.add_handler(CommandHandler("you_command", call_back))

Публикация файлов, media и URL-адресов в Telegram.

Если нужно отправить файл, например, отправить фото, то для этого есть три метода:

  • Загрузить файл в Telegram.
  • Отправить HTTP-ссылку, ведущую к файлу
  • Отправить file_id уже отправленного файла.

Обратите внимание, что не каждый метод поддерживается везде (например, для thumbnails нельзя передать file_id).

Смотрим, как можно отправить документ.

  1. Загрузка файла в Telegram:

    bot.send_document(chat_id=chat_id, document=open('tests/test.png', 'rb'))
    
  2. Отправка HTTP-ссылки в Telegram:

    bot.send_document(chat_id=chat_id, document='https://site.ru/static/test.gif'))
    
  3. Отправка file_id:

    bot.send_document(chat_id=chat_id, document=file_id))
    

    Два замечания по этому поводу:

    • У каждого бота есть свои собственные идентификаторы файлов, т.е. нельзя использовать идентификатор файла от другого бота для отправки фотографии
    • Как получить fileid фотографии, которую вы отправили? Прочтите его из возвращаемого значения bot.senddocument (или любого другого объекта Message, который вы получите):

      message = bot.send_document(...)
      file_id = message.document.file_id
      

Примечание. Метод bot.send_document используется для отправки файлов любого типа. В настоящее время боты могут отправлять файлы любого типа размером до 50 МБ, это ограничение может быть изменено в будущем. Аргументом document может быть либо file_id, либо URL-адрес, либо файл с диска открытый как open(file_name, 'rb'). Отправка по URL в настоящее время работает только с файлами GIF, PDF и ZIP.

Это почти так же работает для всех других методов send_media_type, таких как bot.send_photo(), bot.send_video() и т. д.

Далее рассматриваются другие распространенные примеры кода. Обратите внимание на то, что подход к публикации файлов почти одинаков, НО методы экземпляра bot разные!

Опубликовать файл изображения с диска в Telegram.

bot.send_photo(chat_id=chat_id, photo=open('tests/test.png', 'rb'))

Опубликовать фото с URL-адреса в Telegram.

bot.send_photo(chat_id=chat_id, photo='https://telegram.org/img/t_logo.png')

Опубликовать голосовой файл с диска в Telegram.

bot.send_voice(chat_id=chat_id, voice=open('tests/telegram.ogg', 'rb'))

Опубликовать аудио файл с диска в Telegram.

bot.send_audio(chat_id=chat_id, audio=open('tests/test.mp3', 'rb'))

Опубликовать документ или архив с диска в Telegram.

bot.send_document(chat_id=chat_id, document=open('tests/test.zip', 'rb'))

Опубликовать гифку в Telegram.

Используйте этот метод для отправки файлов анимации (видео в формате GIF или H.264/MPEG-4 AVC без звука). В настоящее время боты могут отправлять файлы анимации размером до 50 МБ, это ограничение может быть изменено в будущем.

bot.send_animation(chat_id=chat_id, document=open('tests/animation.gif', 'rb'))

Опубликовать медиа-группу из фото, расположенных в URL-адресах:

Используйте этот метод для отправки группы фотографий или видео в виде альбома.

from telegram import InputMediaPhoto

list_of_urls = [
    'https://example.org/commons/foto1.jpg',
    'https://example.org/commons/foto2.jpg',
    'https://example.org/commons/foto3.jpg' 
]

# список мультимедиа
media_group = []

for number, url in enumerate(list_of_urls):
    media_group.append(InputMediaPhoto(media=url, caption="Фотография №" + number))

bot.send_media_group(chat_id=chat_id, media=media_group)

Примечание Элементы в списке мультимедиа media_group обязательно должны быть экземплярами InputMediaAudio, InputMediaDocument, InputMediaPhoto или InputMediaVideo.

Редактирование файла, отправленного в Telegram.

Если файл отправлен, то можно его отредактировать. Это работает аналогично send_media_group, т. е. медиаданные должны быть заключены в объект InputMedia<media_type>. Опять же, с документом в качестве примера:

bot.edit_message_media(chat_id=chat_id, message_id=message_id, 
            media=InputMediaDocument(media=open('tests/test.png'), ...))

Ознакомьтесь с ограничениями на редактирование мультимедиа в документах send_media_group.

Выложить изображение прочитанное в оперативную память:

В этом примере изображение является объектом изображения модуля Pillow, но оно работает одинаково со всеми типами мультимедиа.

from io import BytesIO
bio = BytesIO()
bio.name = 'image.jpeg'
image.save(bio, 'JPEG')
bio.seek(0)
bot.send_photo(chat_id, photo=bio)

Получить изображение с размерами, максимально приближенными к желаемому размеру:

Где photos - это список объектов PhotoSize, а desired_size - кортеж, содержащий нужный размер.

def get_closest(photos, desired_size):
    def diff(p): 
        return p.width - desired_size[0], p.height - desired_size[1]
    def norm(t): 
        return abs(t[0] + t[1] * 1j)
    return min(photos, key=lambda p:  norm(diff(p)))

Загрузка файлов из Telegram сообщений.

Примечание. При загрузке фотографий имейте в виду, что update.message.photo - это массив фотографий разных размеров (упорядоченный от самого малого к большому).

Используйте update.message.photo[-1], чтобы получить самый большой размер.

file_id = message.voice.file_id
newFile = bot.get_file(file_id)
newFile.download('voice.ogg')

Для полученного video, voice и т.д нужно изменить message.document на message.video, message.voice и т.д. Однако есть одно исключение: message.photo - это список объектов PhotoSize, которые представляют разные размеры одной и той же фотографии. Чтобы получить наибольший размер, нужно используйте message.photo[-1].file_id.

Кроме того, приведенный выше фрагмент можно сократить, используя встроенные ссылки:

newFile = message.effective_attachment.get_file()
newFile.download('file_name')

message.efficient_attachment автоматически содержит любое мультимедийное вложение, которое есть в сообщении - в случае фотографии снова придется использовать, например: message.efficient_attachment[-1].get_file().