Telegram бот на Python, отправка файлов, встроенная клавиатура

Telegram бот на Python, отправка файлов, встроенная клавиатура

Автор: Рамис | Статьи 26 сентября 2021

Часть 1. Простой Telegram бот на Python, метод getUpdates

Часть 2. Telegram бот на Python, отправка файлов, встроенная клавиатура

Часть 3. Telegram бот на Python, работа с геолокацией пользователяа

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

Отправка файлов Telegram API

В Telegram API есть три способа отправки файлов, для демонстрации воспользуемся методом sendPhoto и добавим три функции для отправки фотографии.

Первая способ: Предоставить файл по URL, Telegram скачает и отправит его (максимальный размер 5 МБ).

def send_photo_url(chat_id, img_url):
    requests.get(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}&photo={img_url}')

Второй способ: Отправить файл с компьютера (максимальный размер фотографий - 10 МБ, для остальных файлов - 50 МБ).

def send_photo_file(chat_id, img):
    files = {'photo': open(img, 'rb')}
    requests.post(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}', files=files)

Третий способ: Отправить, передав в параметрах file_id файла который уже хранится где-то на серверах Telegram (ограничений нет).

def send_photo_file_id(chat_id, file_id):
    requests.get(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}&photo={file_id}')

Проверка

Почти все готово, осталось немного отредактировать функцию check_message и приступим к проверке бота.

def check_message(chat_id, message):
    if message.lower() in ['привет', 'hello']:
        send_message(chat_id, 'Привет :)')
    elif message.lower() in 'фото по url':
        # Отправить URL-адрес картинки (телеграм скачает его и отправит)
        send_photo_url(chat_id, 'https://ramziv.com/static/assets/img/home-bg.jpg')
    elif message.lower() in 'фото с компьютера':
        # Отправить файл с компьютера
        send_photo_file(chat_id, 'photo.jpg')
    elif message.lower() in 'фото с сервера телеграм':
        # Отправить id файла (файл уже хранится где-то на серверах Telegram) 
        send_photo_file_id(chat_id, 'AgACAgIAAxkBAAMqYVGBbdbivL53IzKLfUKUClBnB0cAApy0MRtfMZBKHL0tNw9aITwBAAMCAAN4AAMhBA')

Полный код

import requests
import time

TOKEN = 'токен'
URL = 'https://api.telegram.org/bot'

def get_updates(offset=0):
    result = requests.get(f'{URL}{TOKEN}/getUpdates?offset={offset}').json()
    return result['result']

def send_message(chat_id, text):
    requests.get(f'{URL}{TOKEN}/sendMessage?chat_id={chat_id}&text={text}')

def send_photo_url(chat_id, img_url):
    requests.get(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}&photo={img_url}')

def send_photo_file(chat_id, img):
    files = {'photo': open(img, 'rb')}
    requests.post(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}', files=files)

def send_photo_file_id(chat_id, file_id):
    requests.get(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}&photo={file_id}')

def check_message(chat_id, message):
    if message.lower() in ['привет', 'hello']:
        send_message(chat_id, 'Привет :)')
    elif message.lower() in 'фото по url':
        # Отправить URL-адрес картинки (телеграм скачает его и отправит)
        send_photo_url(chat_id, 'https://ramziv.com/static/assets/img/home-bg.jpg')
    elif message.lower() in 'фото с компьютера':
        # Отправить файл с компьютера
        send_photo_file(chat_id, 'photo.jpg')
    elif message.lower() in 'фото с сервера телеграм':
        # Отправить id файла (файл уже хранится где-то на серверах Telegram) 
        send_photo_file_id(chat_id, 'AgACAgIAAxkBAAMqYVGBbdbivL53IzKLfUKUClBnB0cAApy0MRtfMZBKHL0tNw9aITwBAAMCAAN4AAMhBA')


def run():
    update_id = get_updates()[-1]['update_id'] # Присваиваем ID последнего отправленного сообщения боту
    while True:
        time.sleep(2)
        messages = get_updates(update_id) # Получаем обновления
        for message in messages:
            # Если в обновлении есть ID больше чем ID последнего сообщения, значит пришло новое сообщение
            if update_id < message['update_id']:
                update_id = message['update_id'] # Присваиваем ID последнего отправленного сообщения боту
                # Отвечаем тому кто прислал сообщение боту
                check_message(message['message']['chat']['id'], message['message']['text'])

if __name__ == '__main__':
    run()

Результат проверки:

Фото по url

телеграм бота на Python

Фото с компьютера

телеграм бота на Python

Фото с сервера телеграм

телеграм бота на Python

Таким образом вы можете отправить документ, видео, или аудиофайл заменив в URL метод sendPhoto на подходящий.

  • sendVoice Используйте этот метод для отправки аудиофайлов, если вы хотите, чтобы клиент Telegram отображал файл как воспроизводимое голосовое сообщение.
  • sendDocument Используйте этот метод для отправки общих файлов.
  • sendAudio Используйте этот метод для отправки аудиофайлов, если вы хотите, чтобы клиент Telegram отображал их в музыкальном проигрывателе.
  • sendVideo Используйте этот метод для отправки видеофайлов, клиент Telegram поддерживают видео в формате mp4 (другие форматы могут быть отправлены как документ ).
  • sendPhoto Используйте этот метод для отправки фотографий.

С полным списком методов можно ознакомиться здесь

Встроенная клавиатура

Добавим две функции для вывода настраиваемой клавиатуры в телеграм

InlineKeyboardMarkup - Этот объект представляет собой встроенную клавиатуру, которая появляется рядом с отправленным сообщением.

def inline_keyboard(chat_id, text):
    reply_markup = {'inline_keyboard': [[{'text': 'Наш сайт', 'url': 'https://ramziv.com'}]]}
    data = {'chat_id': chat_id, 'text': text, 'reply_markup': json.dumps(reply_markup)}
    requests.post(f'{URL}{TOKEN}/sendMessage', data=data)

ReplyKeyboardMarkup - Этот объект представляет собой настраиваемую клавиатуру с параметрами ответа

def reply_keyboard(chat_id, text):
    reply_markup ={ "keyboard": [["Фото по url", "Сайт"], ["Привет"]], "resize_keyboard": True, "one_time_keyboard": True}
    data = {'chat_id': chat_id, 'text': text, 'reply_markup': json.dumps(reply_markup)}
    requests.post(f'{URL}{TOKEN}/sendMessage', data=data)

Отредактируем функцию check_message для вывода нашей клавиатуры

def check_message(chat_id, message):
    if message.lower() in ['привет', 'hello']:
        send_message(chat_id, 'Привет :)')
    elif message.lower() in 'сайт':
        inline_keyboard(chat_id, 'Вы можете ознакомиться\nс товаром на сайте')
    elif message.lower() in 'фото по url':
        # Отправить URL-адрес картинки (телеграм скачает его и отправит)
        send_photo_url(chat_id, 'https://ramziv.com/static/assets/img/home-bg.jpg')
    elif message.lower() in 'фото с компьютера':
        # Отправить файл с компьютера
        send_photo_file(chat_id, 'photo.jpg')
    elif message.lower() in 'фото с сервера телеграм':
        # Отправить id файла (файл уже хранится где-то на серверах Telegram) 
        send_photo_file_id(chat_id, 'AgACAgIAAxkBAAMqYVGBbdbivL53IzKLfUKUClBnB0cAApy0MRtfMZBKHL0tNw9aITwBAAMCAAN4AAMhBA')
    else:
        reply_keyboard(chat_id, 'Вот что я умею')

Проверка

Проверим как все работает

Отправим боту сообщение Сайт

телеграм бота на Python

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

телеграм бота на Python

Полный код

import requests
import time
import json

TOKEN = 'токен'
URL = 'https://api.telegram.org/bot'

def get_updates(offset=0):
    result = requests.get(f'{URL}{TOKEN}/getUpdates?offset={offset}').json()
    return result['result']

def send_message(chat_id, text):
    requests.get(f'{URL}{TOKEN}/sendMessage?chat_id={chat_id}&text={text}')

def send_photo_url(chat_id, img_url):
    requests.get(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}&photo={img_url}')

def send_photo_file(chat_id, img):
    files = {'photo': open(img, 'rb')}
    requests.post(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}', files=files)

def send_photo_file_id(chat_id, file_id):
    requests.get(f'{URL}{TOKEN}/sendPhoto?chat_id={chat_id}&photo={file_id}')

def inline_keyboard(chat_id, text):
    reply_markup = {'inline_keyboard': [[{'text': 'Наш сайт', 'url': 'https://ramziv.com'}]]}
    data = {'chat_id': chat_id, 'text': text, 'reply_markup': json.dumps(reply_markup)}
    requests.post(f'{URL}{TOKEN}/sendMessage', data=data)

def reply_keyboard(chat_id, text):
    reply_markup ={ "keyboard": [["Фото по url", "Сайт"], ["Привет"]], "resize_keyboard": True, "one_time_keyboard": True}
    data = {'chat_id': chat_id, 'text': text, 'reply_markup': json.dumps(reply_markup)}
    requests.post(f'{URL}{TOKEN}/sendMessage', data=data)

def check_message(chat_id, message):
    if message.lower() in ['привет', 'hello']:
        send_message(chat_id, 'Привет :)')
    elif message.lower() in 'сайт':
        inline_keyboard(chat_id, 'Вы можете ознакомиться\nс товаром на сайте')
    elif message.lower() in 'фото по url':
        # Отправить URL-адрес картинки (телеграм скачает его и отправит)
        send_photo_url(chat_id, 'https://ramziv.com/static/assets/img/home-bg.jpg')
    elif message.lower() in 'фото с компьютера':
        # Отправить файл с компьютера
        send_photo_file(chat_id, 'photo.jpg')
    elif message.lower() in 'фото с сервера телеграм':
        # Отправить id файла (файл уже хранится где-то на серверах Telegram) 
        send_photo_file_id(chat_id, 'AgACAgIAAxkBAAMqYVGBbdbivL53IzKLfUKUClBnB0cAApy0MRtfMZBKHL0tNw9aITwBAAMCAAN4AAMhBA')
    else:
        reply_keyboard(chat_id, 'Вот что я умею')

def run():
    update_id = get_updates()[-1]['update_id'] # Присваиваем ID последнего отправленного сообщения боту
    while True:
        time.sleep(2)
        messages = get_updates(update_id) # Получаем обновления
        for message in messages:
            # Если в обновлении есть ID больше чем ID последнего сообщения, значит пришло новое сообщение
            if update_id < message['update_id']:
                update_id = message['update_id'] # Присваиваем ID последнего отправленного сообщения боту
                # Отвечаем тому кто прислал сообщение боту
                check_message(message['message']['chat']['id'], message['message']['text'])

if __name__ == '__main__':
    run()
Вот и все, теперь бот может не только поприветствовать, но и отправить файл, и вывести настраиваемую клавиатуру. Скоро я выпушу третью часть, где мы добавим оплату через QIWI кошелек, или любой другой функционал который вы пожелаете. (напишите мне если вы хотите третью часть побыстрее)

Дополнительную информацию о методах вы можете получить в документации.

Комментарии

Рамис
@ramas
06 декабря 2021

Первый комментарий)

Ответить
parampampam888
@parampampam888
31 марта 2022

А как заставить его не падать если он получает не текст а например фотографию или стикер . Ошибка : KeyError: 'text' Я понимаю что нужен фильтр но как его воткнуть что то не пойму.

Ответить
Рамис
@ramas
31 марта 2022

@parampampam888, если вы используете Python 3.8 и выше.

def run():
    update_id = get_updates()[-1]['update_id'] # Сохраняем ID последнего отправленного сообщения боту
    while True:
        time.sleep(2)
        messages = get_updates(update_id) # Получаем обновления
        for message in messages:
            # Если в обновлении есть ID больше чем ID последнего сообщения, значит пришло новое сообщение
            if update_id < message['update_id']:
                update_id = message['update_id']# Сохраняем ID последнего отправленного сообщения боту
                if (user_message := message['message'].get('text')): # Проверим, есть ли текст в сообщении
                    check_message(message['message']['chat']['id'], user_message) # Отвечаем

Ответить
parampampam888
@parampampam888
01 апреля 2022

@ramas, Спасибо , за статью и за помощь !

Ответить
Рамис
@ramas
01 апреля 2022

@parampampam888, Не за что, обращайтесь.

Ответить
yura_mars
@yura_mars
07 сентября 2022

Очень долго искал решение! Спасибо огромное)))

Ответить
Рамис
@ramas
08 сентября 2022

@yura_mars, Всегда пожалуйста)

Ответить
Markdown
Войти