PyTelegramBotAPI на примере проекта сбора обратной связи #4. Последние штрихи

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

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

Всем вновь привет! Продолжаем цикл статей, посвящённых разработке телеграм бота на PyTelegramBotAPI.

Сегодня мы полностью доделаем код нашего бота, напишем аннотацию типов, приготовим проект к деплою.


<<< Предыдущий урок

А начнём мы, конечно, с чего-нибудь новенького, а именно - покажем уведомление при нажатии на кнопку, вместо сообщения. Напомню, что на прошлом уроке мы сделали две клавиатуры - Reply и Inline, но нас сейчас интересует вторая. Сейчас при нажатии на кнопку сообщение отредактируется, а сама клавиатура пропадёт. Но мы сделаем круче, пусть пр нажатии на кнопку показывается уведомление, а сообщение просто удаляется, мне кажется так будет красивее и лаконичнее (ну и новый функционал на примере разберём).

Есть два вида уведомлений:

1)

Уведомление появляется сверху
Уведомление появляется сверху

2)

Уведомление появляется в центре экрана
Уведомление появляется в центре экрана

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

Чтобы удалить сообщение надо вызвать соответствующий метод и передать в него id чата и id сообщения. Полный код функции save_btn будет выглядеть так:

@bot.callback_query_handler(func=lambda call: call.data == 'save_data')
def save_btn(call):
    message = call.message
    chat_id = message.chat.id
    message_id = message.message_id
    bot.answer_callback_query(call.id, text="Данные сохранены")
    bot.delete_message(chat_id=chat_id, message_id=message_id)

Удаление сообщения происходит на 7 строке.

Теперь давайте отправим фото. А отправлять мы его будем, когда пользовать напишет команду /start. Напомню, что у нас уже есть обработчик этой команды - это функция welcome. Отправить фото легко, сохраняем его в папку с проектом, открываем файл и читаем его в бинарном виде, а далее вызываем метод send_photo передав туда id чата и прочтённые бинарные данные.

Код изменённой функции welcome выглядит так:

@bot.message_handler(commands=['start'])
def welcome(message):
    chat_id = message.chat.id
    keyboard = telebot.types.ReplyKeyboardMarkup()
    button_save = telebot.types.InlineKeyboardButton(
        text="Написать в поддержку")
    keyboard.add(button_save)
    bot.send_message(chat_id,
                     'Добро пожаловать в бота сбора обратной связи',
                     reply_markup=keyboard)
    with open('feedback.jpeg', 'rb') as file:
        photo = file.read()
    bot.send_photo(chat_id, photo)

Вот так это будет выглядеть:

Ну, а теперь финальный штрих. После того как пользователь укажет имя, фамилию и нажмёт кнопку Сохранить, мы должны запросить у него отзыв (у нас же всё таки бот обратной связи) и отправить его в телеграм заранее указанным администраторам.

Для хранения ID чата администраторов я буду использовать кортеж (чтобы получить id чата, вы можете вывести print'ом переменную chat_id).

bot = telebot.TeleBot(TOKEN)

users = {}

administrators = (814401631,)

Запишем это в самом верху, сразу после переменной users.

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

@bot.callback_query_handler(func=lambda call: call.data == 'save_data')
def save_btn(call):
    message = call.message
    chat_id = message.chat.id
    message_id = message.message_id
    bot.answer_callback_query(call.id, text="Данные сохранены")
    bot.delete_message(chat_id=chat_id, message_id=message_id)
    bot.send_message(chat_id, 'Введите текст отзыва: ')
    bot.register_next_step_handler(message, send_feedback_administrators)

А теперь создадим и саму функцию send_feedback_administrators, он будет отправлять всем указанным в кортеже администраторам сообщение в формате: %Фамилия% %Имя% оставил отзыв: %Текст отзыва%

def send_feedback_administrators(message):
    feedback = message.text
    user = users[message.chat.id]
    name = user['name']
    surname = user['surname']
    for admin_chat_id in administrators:
        bot.send_message(admin_chat_id,
                         f'{surname} {name} оставил отзыв: {feedback}')

Теперь посмотрим как это выглядит:

Отлично, всё прекрасно работает!

Итоговый код выглядит так:

import telebot
from config import TOKEN

bot = telebot.TeleBot(TOKEN)

users = {}

administrators = (814401631,)


@bot.message_handler(commands=['start'])
def welcome(message):
    chat_id = message.chat.id
    keyboard = telebot.types.ReplyKeyboardMarkup()
    button_save = telebot.types.InlineKeyboardButton(
        text="Написать в поддержку")
    keyboard.add(button_save)
    bot.send_message(chat_id,
                     'Добро пожаловать в бота сбора обратной связи',
                     reply_markup=keyboard)
    with open('feedback.jpeg', 'rb') as file:
        photo = file.read()
    bot.send_photo(chat_id, photo)


@bot.message_handler(
    func=lambda message: message.text == 'Написать в поддержку')
def write_to_support(message):
    chat_id = message.chat.id
    bot.send_message(chat_id, 'Введите своё имя')
    users[chat_id] = {}
    bot.register_next_step_handler(message, save_username)


def save_username(message):
    chat_id = message.chat.id
    name = message.text
    users[chat_id]['name'] = name
    bot.send_message(chat_id, f'Отлично, {name}. Теперь укажи свою фамилию')
    bot.register_next_step_handler(message, save_surname)


def save_surname(message):
    chat_id = message.chat.id
    surname = message.text
    users[chat_id]['surname'] = surname
    keyboard = telebot.types.InlineKeyboardMarkup()
    button_save = telebot.types.InlineKeyboardButton(text="Сохранить",
                                                     callback_data='save_data')
    button_change = telebot.types.InlineKeyboardButton(text="Изменить",
                                                       callback_data='change_data')
    keyboard.add(button_save, button_change)

    bot.send_message(chat_id, f'Сохранить данные?', reply_markup=keyboard)


@bot.message_handler(commands=['who_i'])
def who_i(message):
    chat_id = message.chat.id
    name = users[chat_id]['name']
    surname = users[chat_id]['surname']
    bot.send_message(chat_id, f'Вы: {name} {surname}')


@bot.callback_query_handler(func=lambda call: call.data == 'save_data')
def save_btn(call):
    message = call.message
    chat_id = message.chat.id
    message_id = message.message_id
    bot.answer_callback_query(call.id, text="Данные сохранены")
    bot.delete_message(chat_id=chat_id, message_id=message_id)
    bot.send_message(chat_id, 'Введите текст отзыва: ')
    bot.register_next_step_handler(message, send_feedback_administrators)


def send_feedback_administrators(message):
    feedback = message.text
    user = users[message.chat.id]
    name = user['name']
    surname = user['surname']
    for admin_chat_id in administrators:
        bot.send_message(admin_chat_id,
                         f'{surname} {name} оставил отзыв: {feedback}')


@bot.callback_query_handler(func=lambda call: call.data == 'change_data')
def save_btn(call):
    message = call.message
    chat_id = message.chat.id
    message_id = message.message_id
    bot.edit_message_text(chat_id=chat_id, message_id=message_id,
                          text='Изменение данных!')
    write_to_support(message)


if __name__ == '__main__':
    print('Бот запущен!')
    bot.infinity_polling()

А теперь, подведём итоги, сегодня мы сделали:

  1. Отправку уведомлений, удаление сообщений

  2. Отправку фото

  3. Закончили всю техническую часть бота, связанную именно с разработкой

<<< Предыдущий урок


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

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

Код с этого урока на GitHub.

Источник: https://habr.com/ru/articles/776220/


Интересные статьи

Интересные статьи

Мы внедряли один из облачных модулей SAP, но нижеследующие уроки, которыми я хочу поделиться, применимы к любому проекту.Мой первый проект в роли РП получился достаточно сумбурным. Пресейл по нему бы...
Блокчейн-технологии постепенно проникают в разные (все еще относительно немногие) направления бизнеса, включая логистику, страхование, финансы и т.п. В России с блокчейном связаны, например, М.Видео, ...
Почти 3 года назад вышла статья Онлайн-конструктор переговорной комнаты — подбор оптимального решения ВКС, в которой рассказывается о решении задачи выбора оборудования для переговорных комнат использ...
JavaScript – это один из языков с динамической типизацией. Такие языки удобны для быстрой разработки приложений, но когда несколько команд берутся за разработку одного большого проекта, лучше...
Осваивая рецепты эффективного развития программного проекта, постарался для себя найти причины, делающие полезным использование принципов развития архитектуры SOLID (статья Как не понимать принци...