Users & chats

chat_id and user_id

chat_id и user_id — основные идентификаторы в Bot API. Понимание их отличий критично для адресации сообщений и работы с правами.

user_id

user_id — уникальный идентификатор пользователя или бота в Telegram. Положительное 64-битное число. Не меняется никогда. Виден в поле from.id объекта Message и CallbackQuery.

Используется для:

  • личных сообщений боту (приватный чат — chat_id === user_id);
  • проверки прав администратора в группах;
  • связки с вашей БД (primary key).

chat_id

chat_id — идентификатор чата любого типа. Формат зависит от типа:

  • Private (личка с ботом): положительное, равно user_id собеседника.
  • Group (обычная группа): отрицательное, до -10^9 (legacy).
  • Supergroup и Channel: отрицательное, начинается с -100 (например, -1001234567890).

Всегда используйте chat_id из входящего Update (message.chat.id, callback_query.message.chat.id). Не собирайте его вручную.

Получение ID

Самый простой способ — переслать боту любое сообщение и прочитать message.chat.id и message.from.id в логах. Для каналов: добавьте бота администратором, отправьте пост, прочитайте channel_post.chat.id.

$update = json_decode(file_get_contents('php://input'), true);
$chatId = $update['message']['chat']['id'] ?? $update['callback_query']['message']['chat']['id'] ?? null;
$userId = $update['message']['from']['id'] ?? $update['callback_query']['from']['id'] ?? null;
if ($chatId === null) {
    error_log('chat_id not found in update');
    exit;
}
// $chatId используем в sendMessage, $userId — для проверок прав

Типы чатов и поле type

Объект Chat содержит поле type:

  • private — личка;
  • group — обычная группа;
  • supergroup — супергруппа;
  • channel — канал.

Проверка типа позволяет разделить логику:

$chatType = $update['message']['chat']['type'];
if ($chatType === 'private') {
    // личный диалог
} elseif (in_array($chatType, ['group', 'supergroup'])) {
    // групповая логика
}

Частые ошибки

  • Передача user_id вместо chat_id в sendMessage для групп — бот пришлёт сообщение в личку пользователю, а не в группу.
  • Потеря префикса -100 при сохранении ID супергруппы/канала в БД (колонка должна быть BIGINT).
  • Попытка написать в канал без прав администратора — вернёт 403 Forbidden.

Права бота

В группах и каналах бот должен быть администратором с правом can_post_messages (каналы) или can_send_messages (группы). Проверяйте через getChatMember:

function isAdmin(int $chatId, int $userId): bool {
    $url = "https://api.telegram.org/bot{$token}/getChatMember?chat_id={$chatId}&user_id={$userId}";
    $res = json_decode(file_get_contents($url), true);
    return in_array($res['result']['status'] ?? '', ['administrator', 'creator']);
}

Дальше: Группы