В разделе рассмотрены примеры сниппетов, для работы с файлами, медиа и 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))
Если нужно отправить файл, например, отправить фото, то для этого есть три метода:
file_id уже отправленного файла.Обратите внимание, что не каждый метод поддерживается везде (например, для thumbnails нельзя передать file_id).
bot.send_document(chat_id=chat_id, document=open('tests/test.png', 'rb'))
bot.send_document(chat_id=chat_id, document='https://site.ru/static/test.gif'))
file_id:bot.send_document(chat_id=chat_id, document=file_id))
Два замечания по этому поводу:
+ У каждого бота есть свои собственные идентификаторы файлов, т.е. нельзя использовать идентификатор файла от другого бота для отправки фотографии
+ Как получить file_id фотографии, которую вы отправили? Прочтите его из возвращаемого значения bot.send_document (или любого другого объекта Message, который вы получите):
```python
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 разные!
bot.send_photo(chat_id=chat_id, photo=open('tests/test.png', 'rb'))
bot.send_photo(chat_id=chat_id, photo='https://telegram.org/img/t_logo.png')
bot.send_voice(chat_id=chat_id, voice=open('tests/telegram.ogg', 'rb'))
bot.send_audio(chat_id=chat_id, audio=open('tests/test.mp3', 'rb'))
bot.send_document(chat_id=chat_id, document=open('tests/test.zip', 'rb'))
Используйте этот метод для отправки файлов анимации (видео в формате GIF или H.264/MPEG-4 AVC без звука). В настоящее время боты могут отправлять файлы анимации размером до 50 МБ, это ограничение может быть изменено в будущем.
bot.send_animation(chat_id=chat_id, document=open('tests/animation.gif', 'rb'))
Используйте этот метод для отправки группы фотографий или видео в виде альбома.
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.
Если файл отправлен, то можно его отредактировать. Это работает аналогично 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)))
Примечание. При загрузке фотографий имейте в виду, что
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().