Как определить, что пользователь отписался от бота

Несколько методов для определения статуса использования бота пользователем, узнать возможность отправки ему сообщений

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

В любом из указанных событиях приходит объект my_chat_member в котором есть нужные нам данные пользователя в случае если он подписался или отписался от бота.

Исключение: В случае первого старта бота этот объект не приходит, если пользователь перезапускает ранее удаленного бота, то объект приходит с пометкой old_chat_member->status == "kicked"

{
  "chat":{
    "id":123456789,
    "first_name":"User",
    "type":"private"
  },
  "from":{
    "id":123456789,
    "is_bot":false,
    "first_name":"User",
    "language_code":"ru"
  },
  "date":1685526728,
  "old_chat_member":{
    "user":{
      "id":987654321,
      "is_bot":true,
      "first_name":"Bot",
      "username":"Bot_bot"
    },
    "status":"kicked",
    "until_date":0
  },
  "new_chat_member":{
    "user":{
      "id":987654321,
      "is_bot":true,
      "first_name":"Bot",
      "username":"Bot_bot"
    },
    "status":"member"
  }
}

При получении этих уведомлений достаточно проверить свойство объекта my_chat_member->new_chat_member->status в случае если оно равно "member", то это активный пользователь, если же оно равно "kicked", то это удаление бота с блокировкой.

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

Пример получения таких служебных уведомлений:

// токен бота
$token_bot = "903520000:A___________LnysLjuXLXfuZmIqjpVrg";
// получим данные из телеграм
$data = json_decode(file_get_contents("php://input"), false);
// получим id бота
$bot_id = explode(":", $token_bot)[0];
// проверим это объект начала диалога с ботом или удаление бота
if (isset($data->my_chat_member)) {
    // можно дополнительно проверить на id бота
    // но это излишнее условие, можно этого не делать - тк от другого бота это не придет
    if($data->my_chat_member->new_chat_member->user->id == $bot_id) {
        // получим объект пользователя
        $user = $data->my_chat_member->from;
        // если это начало диалога
        if($data->my_chat_member->new_chat_member->status == "member") {
            // здесь можно добавить пользователя в базу, или "активизировать"
            set("Active: " . json_encode($user));
            // ...
        }
        // если это удаление бота
        else if($data->my_chat_member->new_chat_member->status == "kicked") {
            // здесь можно удалить пользователя из базу или поставить флаг "неактивности"
            set("UnActive: " . json_encode($user));
            // ...
        }
    }
}

/** Вспомогательная функция для записи данных в файл
 * @param $data
 */
function set($data) {
    // откроем файл на запись, если его нет создадим
    $fh = fopen("./data.txt", 'a');
    // запишем данные в файл
    fwrite($fh, $data . "\n==================================\n");
    // закроем файл
    fclose($fh);
}

Альтернативный способ проверки

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

// пример ответа на запрос
{
    "ok":true,
    "result":true
}

// пример ответа на запрос при блокировке бота
{
    "ok":false,
    "error_code":403,
    "description":"Forbidden: bot was blocked by the user"
}

Можно направить безобидный (незаметно для пользователя) запрос на передачу действия бота через метод sendChatAction например typing, если пользователь не заблокировал бота, даже если он при этом удалил чат с ботом, в ответ придет положительный ответ. 

echo file_get_contents("https://api.telegram.org/bot<TOKENBOT>/sendChatAction?chat_id=<CHATID>&action=typing");

В зависимости от ответа можно сделать пометку в базе данных пользователю: "активный" или "неактивный".

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

0 комментариев
Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте по ссылке или QR бот @iMakeBot, нажмите кнопку Старт/Start.
Следуйте инструкциям бота.