Как сделать кнопки в боте телеграм php
Перейти к содержимому

Как сделать кнопки в боте телеграм php

  • автор:

Создание Telegram бота на PHP #3: примеры отправки сообщений с кнопками в Telegram

В новом уроке мы с вами рассмотрим отправку базовых запросов в Telegram. Я покажу вам как отправлять простые текстовые сообщения в Telegram, как отправлять кнопки и дополнительные клавиатуры.

Всю информацию по параметрам запросов мы будем брать из официальной документации Telegram.

Полный список всех записей курса находится на сайте или в публикациях на Хабр.

Все ответы от Telegram приходят в виде JSON строки. Для удобного отображения массива ответа в браузере, советую вам установить специальное расширение для браузера, которое называется JSON Viewer.

Отправка простых сообщений

Для отправки простых текстовых сообщений, нам необходимо воспользоваться методом sendMessage.

Ранее я показывал вам, как отправлять запросы с передачей параметров в URL, теперь для удобства я буду использовать запись параметров в массиве и с помощью функции http_build_query мы будем формировать строку с GET параметрами.

$token = "5340791844:AAEXXDduvInvQrlykV91USOQSevrPVU"; $getQuery = array( "chat_id" => 1424625511, "text" => "Новое сообщение из формы", "parse_mode" => "html" ); $ch = curl_init("https://api.telegram.org/bot". $token ."/sendMessage?" . http_build_query($getQuery)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, false); $resultQuery = curl_exec($ch); curl_close($ch); echo $resultQuery;

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

Отправка ответа на сообщение

Для отправки ответа на ранее созданное сообщения, вам необходимо в новом запросе sendMessage отправить дополнительный параметр reply_to_message_id, передав в него id сообщения, которое вы хотите прикрепить.

Полный запрос будет выглядеть так…

$token = "5340791844:AAEXXDduvInvQrlykV91USOQSevrPVU"; $getQuery = array( "chat_id" => 1424625511, "text" => "Новое сообщение из формы", "parse_mode" => "html", "reply_to_message_id" => 7 ); $ch = curl_init("https://api.telegram.org/bot". $token ."/sendMessage?" . http_build_query($getQuery)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, false); $resultQuery = curl_exec($ch); curl_close($ch); echo $resultQuery;

Удаление сообщений из чата

Для удаления сообщений, вам нужно воспользоваться методом deleteMessage и знать id сообщения которое вы хотите удалить.

Пример кода для удаления сообщений выглядит так:

$token = "5340791844:AAEXXDduvInvQrlykV91USOQSevrPVU"; $getQuery = array( "chat_id" => 1424625511, "message_id" => 32456, ); $ch = curl_init("https://api.telegram.org/bot". $token ."/deleteMessage?" . http_build_query($getQuery)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, false); $resultQuery = curl_exec($ch); curl_close($ch); echo $resultQuery;

Отправка кнопок в чат

На данный момент, существует 3 вида кнопок в чате, в Telegram.

  1. Кнопки которые прикреплены к сообщению (inline_keyboard).
  2. Кнопки которые располагаются под строкой ввода сообщения, они называются клавиатурой (keyboard).
  3. Кнопки меню команд, которые чаще всего располагаются слева от строки ввода сообщения.

Для начала давайте рассмотрим как нам добавить кнопки которые будут прикреплены к сообщению.

Для отправки таких кнопок, нам нужно воспользоваться методом sendMessage и передать ему в качестве параметра reply_markup — массив со свойствами клавиатуры.

Данный массив выглядит следующим образом…

. 'reply_markup' => json_encode(array( 'inline_keyboard' => array( array( array( 'text' => 'Button 1', 'callback_data' => 'test_2', ), array( 'text' => 'Button 2', 'callback_data' => 'test_2', ), ) ), )), . 

Разберём всё по порядку.

Первое важное правило — reply_markup принимает json, поэтому для создания кнопок, вам нужно конвертировать массив в JSON с помощью функции json_encode.

В массиве с параметрами кнопок, есть особые параметры. Эти параметры, так же, указаны в документации.

  • С помощью параметра text вы можете передать текст кнопки.
  • параметр url указывает ссылку, если вам нужно сделать кнопку для перехода на внешний ресурс.
  • параметр callback_data указывает строку которая будет возвращена после нажатия на кнопку. Данную строку используют как команду.

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

Таким образом, для создания 2 кнопок в одном ряду, мы будем использовать следующий код

. 'reply_markup' => json_encode(array( 'inline_keyboard' => array( array( array( 'text' => 'Button 1', 'callback_data' => 'test_2', ), array( 'text' => 'Button 2', 'callback_data' => 'test_2', ), ) ), )), . 

Для создания 2 рядов по 2 кнопки используйте код .

. 'reply_markup' => json_encode(array( 'inline_keyboard' => array( array( array( 'text' => 'Button 1', 'callback_data' => 'test_2', ), array( 'text' => 'Button 2', 'callback_data' => 'test_2', ), ), array( array( 'text' => 'Button 3', 'callback_data' => 'test_3', ), array( 'text' => 'Button 4', 'callback_data' => 'test_4', ), ) ), )), . 

И для создания одной кнопки в первом ряду и 2 — во втором, используйте следующий код.

. 'reply_markup' => json_encode(array( 'inline_keyboard' => array( array( array( 'text' => 'Button 2', 'callback_data' => 'test_2', ), ), array( array( 'text' => 'Button 3', 'callback_data' => 'test_3', ), array( 'text' => 'Button 4', 'callback_data' => 'test_4', ), ) ), )), . 

Надеюсь, я смог объяснить данную тему доступно, если у вас будут вопросы, пишите их в нашем Telegram канале.

Отправка клавиатуры в чат

Аналогичные параметры имеет и массив для отправки клавиатуры в чат. Для создания клавиатуры пропишем следующий код.

. 'reply_markup' => json_encode(array( 'keyboard' => array( array( array( 'text' => 'Тестовая кнопка 1', 'url' => 'YOUR BUTTON URL', ), array( 'text' => 'Тестовая кнопка 2', 'url' => 'YOUR BUTTON URL', ), ) ), 'one_time_keyboard' => TRUE, 'resize_keyboard' => TRUE, )), . 

Структура массивом для кнопок та же, но только есть отличие в названиях и количестве параметров.

Ключ inline_keyboard заменяется на keyboard.

А так же для клавиатуры добавляются 2 дополнительных параметра:

  • one_time_keyboard — скрыть клавиатуру, как только она была использована. Клавиатура по-прежнему будет доступна, но клиенты будут автоматически отображать обычную, буквенную клавиатуру в чате — пользователь может нажать специальную кнопку в поле ввода, чтобы снова увидеть пользовательскую клавиатуру. Значение по умолчанию равно false.
  • resize_keyboard — изменяет размер клавиатуры по вертикали для оптимальной подгонки (например, уменьшить клавиатуру, если есть только два ряда кнопок). По умолчанию установлено значение false, и в этом случае пользовательская клавиатура всегда имеет ту же высоту, что и стандартная клавиатура приложения.
  • В новом уроке мы с вами разобрали самый популярный метод для работы с Телеграм ботами — sendMessage. Данный метод позволяет отправлять текстовые сообщения с привязанными кнопками и клавиатурами.
  • Научились удалять сообщения
  • Разобрали какие бывают типы кнопок и научились создавать массивы для гибкой структуры вывода дополнительных клавиатур и кнопок.

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

Добавляем пункты меню в Телеграм бота на PHP

В продолжении предыдущей статьи «Как создать простого бота для Телеграм на PHP», представляем вам продолжение данной темы: «Как добавить меню в простого Телеграм бота на PHP».

Добавляем пункты меню в Телеграм бота на PHP

Итак, бота вы уже сделали, благодаря предудущей статье. Будем использовать код из этой статьи, который вы можете скачать тут: verysimple_bot.zip (2 Kb).

Для этого перепишем функцию отправки сообщения от бота message_to_telegram

  1. Для вывода меню снизу сообщения бота, нужно при каждой передачи сообщения от бота в диалог, передавать массив $reply_markup в формате json.
  2. Мы будем использовать тип меню, который привязан к сообщению, поэтому и нужно передавать каждый раз, а бывает меню привязанное ко всему диалогу.
  3. При этом будем выводить меню по-умолчанию, если мы не передали массив.
  4. Это нужно для организации меню второго уровня.
  5. Сделаем это на примере входа в раздел Услуги и там выведем подменю в виде нескольких услуг.
  6. Общее меню будет: О нас, Услуги, Контакты, Заявка
  7. Меню раздела Услуги будет содержать: Услуга 1, Услуга 2
  8. При этом при нажатии на меню будет происходить передача команды в диалог бота, например при нажатии на «О нас» будет передана команда /about — это наиболее простой способ организации диалогового меню.
 function message_to_telegram($bot_token, $chat_id, $text, $reply_markup = '') < $ch = curl_init(); if ($reply_markup == '') < $btn[] = ["text"=>"О нас", "callback_data"=>'/about']; $btn[] = ["text"=>"Услуги", "callback_data"=>'/srv']; $btn[] = ["text"=>"Контакты", "callback_data"=>'/contact']; $btn[] = ["text"=>"Заявка", "callback_data"=>'/order']; $reply_markup = json_encode(["keyboard" => [$btn], "resize_keyboard" => true]); > $ch_post = [ CURLOPT_URL => 'https://api.telegram.org/bot' . $bot_token . '/sendMessage', CURLOPT_POST => TRUE, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_TIMEOUT => 10, CURLOPT_POSTFIELDS => [ 'chat_id' => $chat_id, 'parse_mode' => 'HTML', 'text' => $text, 'reply_markup' => $reply_markup, ] ]; curl_setopt_array($ch, $ch_post); curl_exec($ch); > 

Теперь перепишем бота, добавив обработку меню бота

  1. В частности выведем раздел Услуги и подменю в нем.
  2. И дополним обработку вывода текста по Услуга 1 и Услуга 2.
/** * Very simple chat bot @verysimple_bot_menu by Novelsite.ru * + menu * 22.06.2022 */ header('Content-Type: text/html; charset=utf-8'); // на всякий случай досообщим PHP, что все в кодировке UTF-8 $site_dir = dirname(dirname(__FILE__)).'/'; // корень сайта $bot_token = '1234567899:AAKJhkkjhkjhKhKhjkhkhk_kJhgkjhJhgjghjhG'; // токен вашего бота $data = file_get_contents('php://input'); // весь ввод перенаправляем в $data $data = json_decode($data, true); // декодируем json-закодированные-текстовые данные в PHP-массив $order_chat_id = '123456789'; //chat_id менеджера компании для заявок $bot_state = ''; // состояние бота, по-умолчанию пустое // Для отладки, добавим запись полученных декодированных данных в файл message.txt, // который можно смотреть и понимать, что происходит при запросе к боту // Позже, когда все будет работать закомментируйте эту строку: file_put_contents(__DIR__ . '/message.txt', print_r($data, true)); // Основной код: получаем сообщение, что юзер отправил боту и // заполняем переменные для дальнейшего использования if (!empty($data['message']['text'])) < $chat_id = $data['message']['from']['id']; $user_name = $data['message']['from']['username']; $first_name = $data['message']['from']['first_name']; $last_name = $data['message']['from']['last_name']; $text = trim($data['message']['text']); $text_array = explode(" ", $text); // получим текущее состояние бота, если оно есть $bot_state = get_bot_state ($chat_id); // если текущее состояние бота отправка заявки, то отправим заявку менеджеру компании на $order_chat_id if (substr($bot_state, 0, 6) == '/order') < $text_return = " Заявка от @$user_name: Имя: $first_name $last_name $text "; message_to_telegram($bot_token, $order_chat_id, $text_return); set_bot_state ($chat_id, ''); // не забудем почистить состояние на пустоту, после отправки заявки >// если состояние бота пустое -- то обычные запросы else < // вывод информации Помощь if ($text == '/help') < $text_return = "Привет, $first_name $last_name, вот команды, что я понимаю: /help - список команд /about - о нас /order - оставить заявку "; message_to_telegram($bot_token, $chat_id, $text_return); set_bot_state ($chat_id, '/help'); >// вывод информации о нас elseif ($text == '/about') < $text_return = "verysimple_bot: Я пример самого простого бота для телеграм, написанного на PHP. Мой код можно скачивать, дополнять, исправлять. Код доступен в этой статье: https://www.novelsite.ru/kak-sozdat-prostogo-bota-dlya-telegram-na-php.html также есть дополнение статиь про добавление пунктов меню в бота: https://www.novelsite.ru/dobavlyaem-punkty-menyu-telegram-bota-na-php.html "; message_to_telegram($bot_token, $chat_id, $text_return); set_bot_state ($chat_id, '/about'); >// вывод информации об услугах и подменю elseif ($text == '/srv') < $num = (int)$text_array[array_key_last($text_array)]; if ($num == 1) < $ret = ["text"=>"⬅️ Вернуться", "callback_data"=>'/srv'],; $text_return = "Услуга 1: --------------------- Текст об услуга 1 услуга 1 услуга 1 услуга 1 услуга 1 услуга 1 услуга 1. "; > elseif ($num == 2) < $ret = ["text"=>"⬅️ Вернуться", "callback_data"=>'/srv'],; $text_return = "Услуга 2: --------------------- Текст об услуга 2 услуга 2 услуга 2 услуга 2 услуга 2 услуга 2 услуга 2. "; > else < $ret = []; $text_return = "Услуги: --------------------- 1. Услуга 1 2. Услуга 2 "; > $reply_markup = json_encode([ "inline_keyboard" => [ [ ["text"=>"Услуга 1", "callback_data"=>'/srv 1'], ["text"=>"Услуга 2", "callback_data"=>'/srv 2'], ], $ret, ] ]); message_to_telegram($bot_token, $chat_id, $text_return, $reply_markup); set_bot_state ($chat_id, '/srv'); > // переход в режим Заявки elseif ($text == '/order') < $text_return = "$first_name $last_name, для подтверждения Заявки введите текст вашей заявки и нажмите отправить. Наши специалисты свяжутся с вами в ближайшее время! "; message_to_telegram($bot_token, $chat_id, $text_return); set_bot_state ($chat_id, '/order'); >> > // функция отправки сообщения от бота в диалог с юзером function message_to_telegram($bot_token, $chat_id, $text, $reply_markup = '') < $ch = curl_init(); if ($reply_markup == '') < $btn[] = ["text"=>"О нас", "callback_data"=>'/about']; $btn[] = ["text"=>"Услуги", "callback_data"=>'/srv']; $btn[] = ["text"=>"Контакты", "callback_data"=>'/contact']; $btn[] = ["text"=>"Заявка", "callback_data"=>'/order']; $reply_markup = json_encode(["keyboard" => [$btn], "resize_keyboard" => true]); > $ch_post = [ CURLOPT_URL => 'https://api.telegram.org/bot' . $bot_token . '/sendMessage', CURLOPT_POST => TRUE, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_TIMEOUT => 10, CURLOPT_POSTFIELDS => [ 'chat_id' => $chat_id, 'parse_mode' => 'HTML', 'text' => $text, 'reply_markup' => $reply_markup, ] ]; curl_setopt_array($ch, $ch_post); curl_exec($ch); > // сохранить состояние бота для пользователя function set_bot_state ($chat_id, $data) < file_put_contents(__DIR__ . '/users/'.$chat_id.'.txt', $data); >// получить текущее состояние бота для пользователя function get_bot_state ($chat_id) < if (file_exists(__DIR__ . '/users/'.$chat_id.'.txt')) < $data = file_get_contents(__DIR__ . '/users/'.$chat_id.'.txt'); return $data; >else < return ''; >> 
  • Скачать данный пример:verysimple_bot_menu.php (2.7 kb)

P.S. Для текста в кнопках меню бота можно использовать Эмодзи. Не все корректно работают, но многие общеупотребительные работают правильно. Вставлять обычным образом копи-паст, а искать в интренете поиском например так: «Эмодзи для сайта».

Николай Комарков

Как сделать кнопки в боте телеграм php

Добрый день,форумчане!
Подскажите пожалуйста как вывести клавиатуру(inlineKeyboard или replyKeyboard) в телеграмм-боте.
Вот функция ПолучитьСписокСообщений,где используется getUpdates:

Функция ПолучитьСписокСообщений() Экспорт
Результат = getUpdates(Константы.update_id.Получить() + 1);

Если Результат.Свойство(«ok») И Результат.ok = Истина Тогда
Если Результат.Свойство(«result») Тогда
Для Каждого НС Из Результат.result Цикл
Если НС.Свойство(«message») И НС.message.Свойство(«chat») Тогда
Если НС.message.text = «/start» Тогда

chat = НС.message.chat;
sendMessage(id, «Здравствуй, дорогой друг)». );

КонецЕсли;
Константы.update_id.Установить(НС.update_id);
КонецЕсли;

КонецЕсли;
КонецЕсли; //показать прайс показать долг сделать заказ

Возврат Результат;
КонецФункции

Вот сама функция getUpdates:
Функция getUpdates(offset = 0,limit = 0,timeout = 0) Экспорт
method_param = Новый Массив;
Если offset> 0 Тогда
method_param.Добавить(«offset=» + ФорматироватьСтроку(offset));
КонецЕсли;
Если limit> 0 Тогда
method_param.Добавить(«limit=» + ФорматироватьСтроку(limit));
КонецЕсли;
Если offset> 0 Тогда
method_param.Добавить(«timeout=» + ФорматироватьСтроку(timeout));
КонецЕсли;

Результат = ОтправитьHTTPЗапрос(ПолучитьAcessToken(),»getUpdates», method_param);
Возврат ОбработатьJSON(Результат);
КонецФункции

Вот функция sendMessage:
Функция sendMessage(chat_id,text,parse_mode = Неопределено,disable_web_page_preview = Неопределено,disable_notification = Неопределено, reply_to_message_id = 0,reply_markup = Неопределено) Экспорт
Если НЕ ЗначениеЗаполнено(chat_id) ИЛИ НЕ ЗначениеЗаполнено(text) Тогда
Возврат Неопределено;
КонецЕсли;

method_param = Новый Массив;
method_param.Добавить(«chat_id=» + ФорматироватьСтроку(chat_id));
method_param.Добавить(«text=» + text);

Если НЕ parse_mode = Неопределено Тогда
method_param.Добавить(«parse_mode» + parse_mode);
КонецЕсли;
Если НЕ disable_web_page_preview = Неопределено Тогда
method_param.Добавить(«disable_web_page_preview» + disable_web_page_preview);
КонецЕсли;
Если НЕ disable_notification = Неопределено Тогда
method_param.Добавить(«disable_notification» + disable_notification);
КонецЕсли;
Если НЕ reply_to_message_id > 0 Тогда
method_param.Добавить(«reply_to_message_id» + ФорматироватьСтроку(reply_to_message_id));
КонецЕсли;
Если НЕ reply_markup = Неопределено Тогда
method_param.Добавить(«reply_markup=» + reply_markup);
КонецЕсли;

Результат = ОтправитьHTTPЗапрос(ПолучитьAcessToken(),»sendMessage», method_param);
Возврат ОбработатьJSON(Результат);
КонецФункции

Как я понял reply_markup отвечает за вывод клавиатуры,но как её вывести я так и не понял

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

Продолжаем показывать, как работают вместе бэкенд и фронтенд. У нас уже вышло про это две статьи — как сделать простой проект телеграм-бота и как запустить с ним полноценный бэкенд. Вот краткое содержание:

  • У нас есть скрипт на Python, который играет роль бэкенда — он записывает некие данные в базу и потом их выводит.
  • Скрипт получает данные из фронтенда — Телеграма. В Телеграме для этого работает бот, а мостиком между Телеграмом и нашим скриптом служит специальная библиотека Python.
  • На фронтенде пользователь отчитывается, что он сделал за сегодня. Эти отчёты прилетают на бэкенд, наш скрипт их принимает и записывает в базу данных.
  • По специальной команде скрипт выплёвывает то, что у него сейчас есть в базе данных. Выплёвывает в бота.

При этом бэкенд не зависит от фронтенда — ему всё равно, куда отдавать данные и как их будут отображать. Воспользуемся этим и сделаем ещё один фронтенд для проекта — на этот раз в виде веб-страницы. Предположим, что это для менеджера, который хочет контролировать работу команды.

Что делаем

  1. Веб-страницу, внутри которой будет работать второй фронтенд.
  2. Внутри неё — PHP-скрипт, который будет получать данные из бэкенда.

Почему PHP? Потому что он подходит для этой простой задачи: вывести все данные из базы один раз.

Если бы нам нужно было закрыть эту страницу паролем, выдавать разные ключи разным людям, выводить данные по разным пользователям и т. д. — нужно было бы использовать Python и фреймворк Django. Но это большой труд: развернуть всё это хозяйство на сервере, а потом изучить конструкции и паттерны Django. Это имеет смысл для большого долгоиграющего проекта и не имеет для одноразовой странички.

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

Исходный Python-код телеграм-бота

# подключаем модуль для Телеграма import telebot # модуль работы со временем from datetime import datetime, timezone, timedelta # модуль для работы с базой данных import sqlite3 as sl # указываем токен для доступа к боту bot = telebot.TeleBot('6285051364:AAGG2iZ77NIeWj0YjqIs791qxPhvcS3Yu0s') # приветственный текст start_txt = 'Привет! Это журнал «Код». \n\nТеперь у бота появился бэкенд.' # подключаемся к файлу с базой данных con = sl.connect('reports.db') # открываем файл with con: # получаем количество таблиц с нужным нам именем data = con.execute("select count(*) from sqlite_master where type='table' and name='reports'") for row in data: # если таких таблиц нет if row[0] == 0: # создаём таблицу для отчётов with con: con.execute(""" CREATE TABLE reports ( datetime VARCHAR(40) PRIMARY KEY, date VARCHAR(20), id VARCHAR(200), name VARCHAR(200), text VARCHAR(500) ); """) # обрабатываем старт бота @bot.message_handler(commands=['start']) def start(message): # выводим приветственное сообщение bot.send_message(message.from_user.id, start_txt, parse_mode='Markdown') # обрабатываем команду /now @bot.message_handler(commands=['now']) def start(message): # подключаемся к базе con = sl.connect('reports.db') # получаем сегодняшнюю дату now = datetime.now(timezone.utc) date = now.date() # пустая строка для будущих отчётов s = '' # работаем с базой with con: # выполняем запрос к базе data = con.execute('SELECT * FROM reports WHERE date = :Date;',) # перебираем все результаты for row in data: # формируем строку в общем отчёте s = s + '*' + row[3] + '*' + ' → ' + row[4] + '\n\n' # если отчётов не было за сегодня if s == '': # формируем новое сообщение s = 'За сегодня ещё нет записей' # отправляем общий отчёт обратно в телеграм bot.send_message(message.from_user.id, s, parse_mode='Markdown') # обрабатываем команду /yesterday @bot.message_handler(commands=['yesterday']) def start(message): # подключаемся к базе con = sl.connect('reports.db') # получаем вчерашнюю дату yesterday = datetime.today() - timedelta(days=1) y_date = yesterday.date() # пустая строка для будущих отчётов s = '' # работаем с базой with con: # выполняем запрос data = con.execute('SELECT * FROM reports WHERE date = :Date;',) # смотрим на результат for row in data: # если результат пустой — ничего не делаем if row[0] == 0: pass # если вчера были какие-то отчёты else: # добавляем их в общий список отчётов s = s + '*' + row[3] + '*' + ' → ' + row[4] + '\n\n' # если отчётов не было за вчера if s == '': # формируем новое сообщение s = 'За вчерашний день нет записей' # отправляем пользователю это новое сообщение bot.send_message(message.from_user.id, s, parse_mode='Markdown') # обрабатываем входящий отчёт пользователя @bot.message_handler(content_types=['text']) def func(message): # подключаемся к базе con = sl.connect('reports.db') # подготавливаем запрос sql = 'INSERT INTO reports (datetime, date, id, name, text) values(?, ?, ?, ?, ?)' # получаем дату и время now = datetime.now(timezone.utc) # и просто дату date = now.date() # формируем данные для запроса data = [ (str(now), str(date), str(message.from_user.id), str(message.from_user.username), str(message.text[:500])) ] # добавляем с помощью запроса данные with con: con.executemany(sql, data) # отправляем пользователю сообщение о том, что отчёт принят bot.send_message(message.from_user.id, 'Принято, спасибо!', parse_mode='Markdown') # запускаем бота if __name__ == '__main__': while True: # в бесконечном цикле постоянно опрашиваем бота — есть ли новые сообщения try: bot.polling(none_stop=True, interval=0) # если возникла ошибка — сообщаем про исключение и продолжаем работу except Exception as e: print('❌❌❌❌❌ Сработало исключение! ❌❌❌❌❌')

Запускаем скрипт бэкенда на сервере

Сейчас наш скрипт работает локально на компьютере. Если компьютер выключить или пропадёт интернет, скрипт и бот перестанут работать. Это плохо для бэкенда — он должен работать всё время и без перебоев.

Мы можем запустить скрипт на сервере — то есть на чужом компьютере, который мы арендуем за деньги. Разница в том, что сервер всё время работает и редко перезагружается.

Для запуска скрипта на сервере нам потребуется собственно арендованный виртуальный сервис. А дальше воспользуемся рецептом из нашей старой статьи про запуск бота:

  1. Запускаем SSH-клиент и входим на наш сервер как администраторы.
  2. В SSH-терминале пишем по очереди такие команды (вместо .thecode можно написать название каталога, которое вам по душе):
    virtualenv .thecode
    source .thecode/bin/activate
  3. Установим Python-модуль для работы с Телеграмом:
    pip install pytelegrambotapi
  4. Когда установка закончится, пишем такую команду (не забывайте поменять путь к файлу на свой):
    python3 osebe/public_html/projects/front/backend.py
  5. Если хотите, чтобы после закрытия SSH-клиента или терминала бот продолжал работать, в последней команде в начале напишите nohup

Проверим работу бота после запуска на сервере:

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

Бот реагирует на команды и запоминает то, что мы ему пишем, значит, бот на сервере работает как нужно.

По идее нам нужно было отправить бота в защищённую папку, например cgi-bin, чтобы никто не мог получить доступ к базе. Но для простоты проекта мы не стали тратить на это время — сделаем это отдельно и расскажем, как это работает.

Создаём страницу

Наш новый фронт — это веб-страница, поэтому напишем простой код, который создаст обычную страницу с заголовком. Создадим новый файл front.php (не HTML, это важно!) и запишем в него такой код. Это весь HTML-код, который нам понадобится, — всё остальное будем делать на PHP. Если не знаете, что такое PHP, — вот подборка для начала:

А вот код страницы:

      Простой фронтенд к базе данных   

Отчёты

Теперь кладём этот файл на сервер в ту же папку, где и python-скрипт, чтобы всё было в одном месте, и открываем страницу в браузере.

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

Подключаемся к базе данных

Сразу после заголовка добавляем PHP-вставку, вся магия будет происходить внутри.

Чтобы подключиться к базе данных, используем команду SQLite3() и сразу выведем сообщение об успешном подключении. Если мы его увидим — всё работает, можно двигаться дальше.

// подключаемся к базе данных $connection = new SQLite3('reports.db'); // если подключились if($connection)< // выводим сообщение echo "

✅ Подключились к базе данных

"; >

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

Выводим отчёты

Мы будем выводить две группы отчётов: за сегодня и за остальные дни. Для этого нам нужно сделать так:

  1. Получить дату в нужном формате.
  2. Выгрузить все сегодняшние отчёты.
  3. Посмотреть, есть ли они вообще, если нет — выдать сообщение, что их нет.
  4. Если есть — вывести даты и отчёты.
  5. То же самое сделать для отчётов за остальные дни.

Запишем это всё на PHP — мы добавили комментарий к каждой строчке, чтобы было понятнее, как это всё работает:

// получаем дату в нужном формате $date = date('Y-m-d'); // выводим подзаголовок echo '

За сегодня

'; // получаем сегодняшние отчёты из базы $results = $connection->query("SELECT * FROM 'reports' WHERE 'date' == $date"); // получаем количество отчётов $row=$results->fetchArray(SQLITE3_ASSOC); // если они есть if ($row != false) < // заново получаем отчёты из базы $results = $connection->query("SELECT * FROM 'reports' WHERE 'date' == $date"); // пока есть записи в результатах поиска — выводим их while($row=$results->fetchArray(SQLITE3_ASSOC))< echo '' . $row['date'] . '
'; echo 'Ник: ' . $row['name'] . '
'; echo 'Отчёт: ' . $row['text'] . '
'; echo '
'; > // если отчётов нет > else < echo "

За сегодня записей нет

"; > // выводим подзаголовок echo '

Остальные отчёты

'; // выгружаем остальные отчёты из базы $results = $connection->query("SELECT * FROM 'reports' WHERE 'date' != $date"); // пока есть записи в результатах поиска — выводим их while($row=$results->fetchArray(SQLITE3_ASSOC))< echo '' . $row['date'] . '
'; echo 'Ник: ' . $row['name'] . '
'; echo 'Отчёт: ' . $row['text'] . '
'; echo '
'; >

Добавляем этот код в PHP-блок после подключения к базе, заливаем файл front.php на сервер и обновляем страницу:

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

Получается, что у нашего телеграм-бота появился второй фронтенд, который берёт те же данные, что и бот, но отображает их в другом месте и в другом формате.

Что дальше

Технически у нас всё сделано:

  • есть бэкенд на сервере, который принимает отчёты и сохраняет их в базе;
  • есть фронтенд — телеграм-бот со стандартным интерфейсом;
  • есть ещё один фронтенд — веб-страница со всеми отчётами;
  • всё это работает на сервере без нашего участия.

Но внутри много шероховатостей: всё ещё неоптимизированный код, небезопасное расположение базы, нет кнопок выбора дня на странице и так далее. Это можно исправлять в будущем.

Ещё один шаг в Python

Мы сделали проект с фронтом на PHP, а бэкенд работает на Python и SQLite. Если вам интересно делать такое, возможно, это ваше призвание. Приходите в Практикум: нам нужны такие, как вы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *