Пользователи и чаты

Каналы

Узнайте, как работать с Telegram-каналами на PHP: отправка постов, редактирование, получение количества подписчиков и особенности работы с группами обсуждения.

Канал (Channel) в Telegram — это инструмент для публичного вещания на неограниченную аудиторию. В отличие от групп (о которых мы говорили в главе Группы), обычные участники канала не могут отправлять сообщения, оставлять медиафайлы или видеть список других подписчиков. Писать в канал могут только администраторы (включая вашего бота), а пользователи могут лишь читать публикации, оставлять реакции и писать комментарии в привязанной группе обсуждения.

Идентификаторы канала

У каждого канала есть два типа идентификаторов:

  • Публичный юзернейм (username) — например, @my_channel_news. Он настраивается в свойствах публичного канала. Вы можете использовать его напрямую в Bot API вместо числового ID.
  • Внутренний числовой идентификатор (chat_id) — уникальный ID, который всегда начинается с префикса -100 (например, -1001234567890).

Для надёжной работы бота всегда используйте числовой chat_id. Юзернейм канала администраторы могут изменить в любой момент, что сломает логику бота, если юзернейм захардкожен в коде. Числовой ID канала остаётся неизменным на протяжении всей его жизни.

Как узнать ID канала? Самый простой способ — переслать любой пост из этого канала специальному боту (например, @userinfobot), либо вызвать метод getChat, передав туда публичный юзернейм канала.

Добавление бота в канал

Бот не может самостоятельно подписаться на канал или войти в него. Чтобы бот мог публиковать посты, его необходимо вручную добавить в канал в качестве администратора (через интерфейс Telegram: Информация о канале → Администраторы → Добавить администратора).

При добавлении обязательно предоставьте боту следующие права (permissions):

  • post_messages (Публикация сообщений) — без этого права бот не сможет отправлять посты.
  • edit_messages (Редактирование сообщений) — позволяет изменять уже опубликованные ботом посты.
  • delete_messages (Удаление сообщений) — даёт право удалять публикации.

Если вы попытаетесь отправить сообщение в канал, где бот не является администратором с правом публикации, Telegram API вернёт ошибку 400 Bad Request: chat not found или 403 Forbidden: bot is not a member of the channel.

Отправка постов в канал

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

Используем функцию telegramApi(), которую мы создали в главе Первый запрос: getMe. Здесь мы вызываем её для отправки форматированного поста в канал.

<?php
// Токен получаем исключительно из переменных окружения
$token = getenv('TELEGRAM_BOT_TOKEN');
if (!$token) {
throw new RuntimeException('Переменная окружения TELEGRAM_BOT_TOKEN не задана');
}

// ID канала (всегда начинается с -100)
$channelId = '-1001234567890';

try {
// Отправляем пост с HTML-разметкой
$response = telegramApi($token, 'sendMessage', [
'chat_id' => $channelId,
'text' => "📢 <strong>Важное обновление проекта!</strong>\n\nМы запустили интеграцию с Telegram-каналами. Теперь бот умеет публиковать посты автоматически.",
'parse_mode' => 'HTML',
'disable_web_page_preview' => true
]);

// Выводим результат для отладки в терминале
echo "Пост успешно отправлен!\n";
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n";
} catch (Exception $e) {
echo "Ошибка при отправке: " . $e->getMessage() . "\n";
}

При успешном вызове API возвращает объект Message. Обратите внимание, что структура ответа для канала имеет свои особенности:

{
"ok": true,
"result": {
"message_id": 145,
"sender_chat": {
"id": -1001234567890,
"title": "Мой тестовый канал",
"username": "my_test_channel",
"type": "channel"
},
"chat": {
"id": -1001234567890,
"title": "Мой тестовый канал",
"username": "my_test_channel",
"type": "channel"
},
"date": 1710000000,
"text": "📢 Важное обновление проекта!\n\nМы запустили интеграцию с Telegram-каналами. Теперь бот умеет публиковать посты автоматически.",
"entities": [
{
"offset": 2,
"length": 26,
"type": "bold"
}
]
}
}

Что анализировать в ответе:

  • message_id — уникальный идентификатор поста в рамках этого канала. Сохраните его в базу данных, если планируете позже редактировать или удалять этот пост.
  • chat.type имеет значение channel, что подтверждает отправку именно в канал.
  • Поле sender_chat указывает, что автором сообщения является сам канал, а не конкретный пользователь.

Получение информации о канале

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

Используем функцию telegramApi(), которую мы создали в главе Первый запрос: getMe. Вызываем метод getChat для получения метаданных канала.

<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
if (!$token) {
throw new RuntimeException('Переменная окружения TELEGRAM_BOT_TOKEN не задана');
}

$channelId = '-1001234567890';

try {
$chatInfo = telegramApi($token, 'getChat', [
'chat_id' => $channelId
]);

echo "Информация о канале:\n";
echo "Название: " . $chatInfo['title'] . "\n";
echo "Описание: " . ($chatInfo['description'] ?? 'нет описания') . "\n";

// Количество подписчиков доступно в поле member_count при вызове getChat
if (isset($chatInfo['member_count'])) {
echo "Количество подписчиков: " . $chatInfo['member_count'] . "\n";
}
} catch (Exception $e) {
echo "Не удалось получить информацию: " . $e->getMessage() . "\n";
}

Пример JSON-ответа от метода getChat для канала:

{
"ok": true,
"result": {
"id": -1001234567890,
"title": "Мой тестовый канал",
"username": "my_test_channel",
"type": "channel",
"description": "Канал для тестирования Bot API на PHP",
"member_count": 1420,
"linked_chat_id": -1001987654321
}
}

Важные поля:

  • member_count — текущее число подписчиков канала. Обратите внимание: это значение кэшируется на стороне Telegram и может обновляться с задержкой в несколько минут.
  • linked_chat_id — идентификатор супергруппы, которая привязана к каналу в качестве чата обсуждения (комментариев). Если чат не привязан, этого поля в ответе не будет.

Группа обсуждения (Комментарии)

Если к каналу привязана группа обсуждения (Discussion Group), под каждым постом появляется кнопка «Прокомментировать».

С технической точки зрения, когда бот или администратор публикует пост в канале, Telegram автоматически пересылает этот пост в привязанную супергруппу. Все комментарии пользователей к этому посту пишутся внутри супергруппы в виде ответов (replies) на пересланное сообщение.

Если ваш бот состоит и в канале, и в группе обсуждения, он будет получать апдейты типа message из группы обсуждения. В таких сообщениях поле message.reply_to_message будет содержать оригинальный пост из канала. Подробнее о работе с супергруппами читайте в главе Группы.

Редактирование и удаление постов

Редактирование постов в канале происходит точно так же, как и в обычных чатах, но с обязательным указанием chat_id канала и message_id поста.

Используем функцию safeEditMessageText(), которую мы реализовали в главе Редактирование и удаление. Она позволяет безопасно обновить текст ранее отправленного поста.

<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
if (!$token) {
throw new RuntimeException('Переменная окружения TELEGRAM_BOT_TOKEN не задана');
}

$channelId = '-1001234567890';
$messageId = 145; // ID поста, полученный при отправке

// Безопасно редактируем текст поста
$success = safeEditMessageText(
$token,
$channelId,
$messageId,
"📢 <strong>Обновление проекта!</strong>\n\nТекст поста был успешно отредактирован ботом.",
'HTML'
);

if ($success) {
echo "Пост успешно отредактирован!\n";
} else {
echo "Не удалось отредактировать пост.\n";
}

Важные отличия каналов от групп

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

  • Отсутствие событий вступления/выхода: Telegram не присылает стандартные апдейты new_chat_members или left_chat_member, когда пользователи подписываются на канал или покидают его. Чтобы отслеживать подписки, нужно использовать специальный тип обновлений chat_member (требует предварительной настройки webhook или getUpdates).
  • Специфика Inline-кнопок: Если вы прикрепите Inline-клавиатуру к посту в канале, нажатия на кнопки с callback_data не будут отправлять апдейты callback_query напрямую из канала. Telegram доставит callback_query вашему боту только в том случае, если пользователь ранее запустил бота в личных сообщениях. Кнопки с url работают всегда и без ограничений.
  • Анонимность авторов: По умолчанию посты публикуются от имени канала. В настройках канала можно включить «Подписи авторов», тогда в объекте Message появится поле author_signature с именем администратора, опубликовавшего пост.

Дальше: HTTP-клиент на PHP