add buttons to messages and process them on the server side

Hey HABR! In this article I will try to show a small example of using the keyboard under a message in Telegram. That is, with the help of a bot, we will send a post to our channel using the PHP programming language. The Telegram BOT API is well documented, but newbies still have questions about how to put it all together to make it work.

InlineKeyboardMarkup – This object represents the built-in keyboard that appears below the corresponding message.


What do we want to do?

When publishing a message using a bot, under the message itself, display 5 buttons (Like, Haha, Wow!, I sympathize, Outrageous) in the form of emoticons. And their purpose is to display the number of people who clicked on a certain button.

There are already many ready-made PHP libraries on the network for working with the Telegram BOT API. For our task, they are not needed. So let’s get started.

We’ll need

  1. Create a telegram channel;
  2. Create a bot;
  3. Add bot to telegram channel;
  4. Hosting on which the button logic processing file will be located;
  5. The database in which we will store the id of the users who clicked on the button.

Logics

When you click on a certain button, add a counter to it. The user can only press one of the 5 buttons. In the database, we will store the message ID and the ID of users who have already responded to the message.

File structure

  1. send.php – send a message to the Telegram channel
  2. callback.php – process button clicks received from the Telegram channel

Contents of the send.php file

<?php
   define( 'TOKEN', '<token>' );
   define( 'CHAT_ID', '<chat_id>' ); // @name_chat
   define( 'API_URL', 'https://api.telegram.org/bot' . TOKEN . '/' );
   
   function request($method, $params = array()) {
      if ( (!empty($params) ) {
         $url = API_URL . $method . "?" . http_build_query($params);
      } else {
         $url = API_URL . $method;
      }

      return json_decode(file_get_contents($url), JSON_OBJECT_AS_ARRAY);
   }

   $keyboard = array(
      array(
         array('text'=>':like:','callback_data'=>'{"action":"like","count":0,"text":":like:"}'),
         array('text'=>':joy:','callback_data'=>'{"action":"joy","count":0,"text":":joy:"}'),
         array('text'=>':hushed:','callback_data'=>'{"action":"hushed","count":0,"text":":hushed:"}'),
         array('text'=>':cry:','callback_data'=>'{"action":"cry","count":0,"text":":cry:"}'),
         array('text'=>':rage:','callback_data'=>'{"action":"rage","count":0,"text":":rage:"}')
      )
   );

   request("sendMessage", array(
      'chat_id' => CHAT_ID,
      'text' => "hello world!",
      'disable_web_page_preview' => false,
      'reply_markup' => json_encode(array('inline_keyboard' => $keyboard))
   ));

As you can see from the code, it is very simple and we just send “Hello World!” message and add 5 buttons to it.

We also need to set up a webhook for the bot. This is necessary in order to tell the bot where (http://site.ru/callback.php) to send the result of button processing. This is very easy to do, in the browser collect a link of this format:

https://api.telegram.org/bot{my_bot_token}/setWebhook?url={url_to_send_updates_to}

In response, get a json with something like this:

{"ok":true,"result":true,"description":"Webhook was set"}

Contents of the callback.php file

<?php
   define( 'TOKEN', '<token>' );
   define( 'CHAT_ID', '<chat_id>' ); // @name_chat
   define( 'API_URL', 'https://api.telegram.org/bot' . TOKEN . '/' );

   function request($method, $params = array()) {
      if ( (!empty($params) ) {
         $url = API_URL . $method . "?" . http_build_query($params);
      } else {
         $url = API_URL . $method;
      }

      return json_decode(file_get_contents($url), JSON_OBJECT_AS_ARRAY);
   }

   function editMessageReplyMarkup($params){
      //В этом цикле мы изменяем сами кнопки, а именно текст кнопки и значение параметра callback_data
      foreach ( $params['inline_keyboard'][0] as $key => $value ) {
         $data_for = json_decode($value->callback_data, true); // изначально у нас callback_data храниться в виде json-а, декатируем в массив
         if ( $params['data']['action'] == $data_for['action'] ) { // определяем, на какую именно кнопку нажал пользователь под сообщением
            $data_for['count']++; //плюсуем единичку
            $value->text = $data_for['text'] . " " . $data_for['count']; // Изменяем текст кнопки смайлик + количество лайков
         }
         $value->callback_data = json_encode($data_for); // callback_data кнопки кодируем в json
         $params['inline_keyboard'][0][$key] = (array)$value; // изменяем кнопку на новую
      }

      //Изменяем кнопки к сообщению
      request("editMessageReplyMarkup", array(
         'chat_id' => CHAT_ID,
         'message_id' => $params['message_id'],
         'reply_markup' => json_encode(array('inline_keyboard' => $params['inline_keyboard'])),
      ));

      //Выводим сообщение в чат
      request("answerCallbackQuery", array(
         'callback_query_id' => $params['callback_query_id'],
         'text' => "Спасибо! Вы поставили " . $params['data']['text'],
      ));
}

   $result = json_decode(file_get_contents('php://input')); // получаем результат нажатия кнопки
   $inline_keyboard = $result->callback_query->message->reply_markup->inline_keyboard; // текущее состояние кнопок при нажатии на одну из 5 кнопок
   $data = json_decode($result->callback_query->data, true); // получаем значение с кнопки, а именно с параметра callback_data нажатой кнопки
   $message_id = $result->callback_query->message->message_id; // ID сообщения в чате
   $callback_query_id = $result->callback_query->id; //ID полученного результата
   $user_id = $result->callback_query->from->id; // ID пользователя

   $db_message = $db->super_query("SELECT * FROM bot_like WHERE message_id={$message_id}"); //Ищем в БД ID сообщения

   /*
   Я использую библиотеку ($db = new db;) от CMS DLE для работы с БД.
   super_query - этот метод возвращает первую найденную запись в виде массива
   */

   if ( $db_message === null ) {
      // Если не нашли в БД ID сообщения, записываем в БД текущий ID сообщения и ID пользователя, который отреагировал (нажал на одну из 5 кнопок) на сообщение. 
      $db->query("INSERT INTO " . PREFIX . "_posting_tg_bot_like (message_id, users) VALUES ('{$message_id}', '{$user_id}')");

      editMessageReplyMarkup(array(
         'inline_keyboard' => $inline_keyboard,
         'data' => $data,
         'message_id' => $message_id,
         'callback_query_id' => $callback_query_id
      ));
   } else {
      //Если в БД нашли сообщение
      $users = explode(",", $db_message['users']);
      
      // Если нашли в БД пользователя, выводим сообщение "Вы уже нажали на одну из 5 кнопок"
      if( in_array($user_id, $users) ) {
         request("answerCallbackQuery", array(
            'callback_query_id' => $callback_query_id,
            'text' => "Вы уже отреагировали на новость",
         ));
      } 

      // Если не нашли ID в БД изменяем одну из 5 кнопок и добавляем ID пользователя
      else {
         editMessageReplyMarkup(array(
            'inline_keyboard' => $inline_keyboard,
            'data' => $data,
            'message_id' => $message_id,
            'callback_query_id' => $callback_query_id
         ));

         array_push($users, $user_id);
         $users = implode(',', $users);
         $db->query("UPDATE bot_like SET users="{$users}" WHERE message_id='{$message_id}'");
    }
}

That’s all, such a small example turned out, sorry for the early ones if the code is written ugly. You can expand this code to the desired functionality, it already depends on your task. My task was to show a small example, and I hope I succeeded. Thank you for your attention, see you in the comments.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *