Бот для Telegram на PHP. Сейчас играет на Максимум
Просим ChatGPT написать простые сервисы, которые могут пригодиться в работе и смотрим, что в итоге получится. Запросы пишем максимально простым и понятным языком.
Сегодня будем играться по полной программе и сделаем не только страничку на сайте, но и в комплект добавим бота для Телеграм:
Вы можете сразу перейти по ссылке и посмотреть результат на сайте и отдельно ссылка на канал в телеграм, куда бот публикует данные.
Размышления системы:
Ниже приведён пример двух файлов:
-
index.php – HTML-страница с минималистичным дизайном, которая каждые 10 секунд опрашивает PHP-скрипт для получения данных.
-
current.php – PHP-скрипт, который получает JSON с API, обрабатывает поле lyrics (убирает управляющие символы и заменяет переносы строк на HTML‑переносы) и возвращает данные.
index.php
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Текущая композиция на радио Максимум</title>
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #F266CD, #010E26);
color: #010E26;
padding: 20px;
}
.container {
background: #D3F263;
max-width: 800px;
margin: 0 auto;
padding: 20px;
border-radius: 8px;
}
.cover {
max-width: 100%;
border-radius: 4px;
margin-bottom: 15px;
display: block;
}
h2 {
margin-top: 0;
}
.field {
margin-bottom: 10px;
}
.buttons a {
text-decoration: none;
display: inline-block;
background: #63F287;
color: #010E26;
padding: 10px 15px;
margin-right: 10px;
border-radius: 4px;
font-weight: bold;
}
.lyrics {
background: #fff;
padding: 10px;
border-radius: 4px;
color: #010E26;
white-space: pre-wrap;
}
</style>
</head>
<body>
<div class="container">
<h2>Сейчас играет</h2>
<div class="field"><strong>Время начала:</strong> <span id="startTime"></span></div>
<div class="field"><strong>Исполнитель:</strong> <span id="artist"></span></div>
<div class="field"><strong>Композиция:</strong> <span id="title"></span></div>
<div class="field"><strong>Альбом:</strong> <span id="album"></span></div>
<div class="field"><strong>Жанр:</strong> <span id="genres"></span></div>
<div class="field"><strong>Spotify рейтинг:</strong> <span id="spotify_popularity"></span></div>
<img src="" alt="Обложка" id="coverImage" class="cover">
<div class="field">
<strong>Текст песни:</strong>
<div id="lyrics" class="lyrics"></div>
</div>
<div class="buttons">
<a href="#" target="_blank" id="youtubeUrl">YouTube</a>
<a href="#" target="_blank" id="itunesUrl">iTunes</a>
<a href="#" target="_blank" id="spotifyUrl">Spotify</a>
</div>
</div>
<script>
function fetchCurrent() {
fetch('current.php')
.then(response => response.json())
.then(data => {
document.getElementById('startTime').innerText = data.startTime;
document.getElementById('artist').innerText = data.artist;
document.getElementById('title').innerText = data.title;
document.getElementById('album').innerText = data.album;
document.getElementById('genres').innerText = data.genres;
document.getElementById('spotify_popularity').innerText = data.spotify_popularity;
// Обработка обложки
if (data.coverImageWebpUrl600 && data.coverImageWebpUrl600 !== 'Нет данных') {
document.getElementById('coverImage').src = data.coverImageWebpUrl600;
document.getElementById('coverImage').style.display = 'block';
} else {
document.getElementById('coverImage').style.display = 'none';
}
document.getElementById('lyrics').innerHTML = data.lyrics;
// Ссылки для кнопок
document.getElementById('youtubeUrl').href = (data.youtubeUrl && data.youtubeUrl !== 'Нет данных') ? data.youtubeUrl : '#';
document.getElementById('itunesUrl').href = (data.itunesUrl && data.itunesUrl !== 'Нет данных') ? data.itunesUrl : '#';
document.getElementById('spotifyUrl').href = (data.spotifyUrl && data.spotifyUrl !== 'Нет данных') ? data.spotifyUrl : '#';
})
.catch(error => console.error('Ошибка загрузки данных', error));
}
// Обновление каждые 10 секунд
fetchCurrent();
setInterval(fetchCurrent, 10000);
</script>
</body>
</html>
current.php
<?php
header('Content-Type: application/json');
$apiUrl = 'https://meta.hostingradio.ru/rmg/maximum/native/current.json';
$response = file_get_contents($apiUrl);
if ($response === false) {
echo json_encode(['error' => 'Не удалось получить данные с API']);
exit;
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
echo json_encode(['error' => 'Ошибка декодирования JSON']);
exit;
}
// Если данные вложены в дополнительный уровень (например, "current"), то используем их
if (isset($data['current'])) {
$data = $data['current'];
}
$result = [];
// Если ключ существует, то выводим его значение, иначе – "Нет данных"
$result['startTime'] = isset($data['startTime']) ? $data['startTime'] : 'Нет данных';
$result['artist'] = isset($data['artist']) ? $data['artist'] : 'Нет данных';
$result['title'] = isset($data['title']) ? $data['title'] : 'Нет данных';
$result['album'] = isset($data['album']) ? $data['album'] : 'Нет данных';
$result['genres'] = isset($data['genres']) ? $data['genres'] : 'Нет данных';
$result['coverImageWebpUrl600'] = isset($data['coverImageWebpUrl600']) ? $data['coverImageWebpUrl600'] : '';
$result['spotify_popularity'] = isset($data['spotify_popularity']) ? $data['spotify_popularity'] : 'Нет данных';
// Обработка lyrics
if (isset($data['lyrics']) && !empty($data['lyrics'])) {
$lyrics = $data['lyrics'];
// Заменяем литеральное "/n" на настоящий символ новой строки
$lyrics = str_replace('/n', "\n", $lyrics);
// Нормализуем переносы строк
$lyrics = str_replace(["\r\n", "\r"], "\n", $lyrics);
// Удаляем нежелательные управляющие символы (оставляем только переносы строк)
$lyrics = preg_replace('/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/u', '', $lyrics);
// Экранируем HTML-сущности, чтобы спецсимволы не ломали вёрстку
$lyrics = htmlspecialchars($lyrics, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// Преобразуем переносы строк в <br>
$lyrics = nl2br($lyrics);
$result['lyrics'] = $lyrics;
} else {
$result['lyrics'] = 'Нет текста песни';
}
$result['youtubeUrl'] = isset($data['youtubeUrl']) ? $data['youtubeUrl'] : '#';
$result['itunesUrl'] = isset($data['itunesUrl']) ? $data['itunesUrl'] : '#';
$result['spotifyUrl'] = isset($data['spotifyUrl']) ? $data['spotifyUrl'] : '#';
echo json_encode($result);
Вы можете сразу перейти по ссылке и посмотреть результат на сайте и отдельно ссылка на канал в телеграм, куда бот публикует данные.
Размышления системы:
To forward data to a Telegram bot, we’ll need the Bot API token and channel chat ID (like '@channelname'). We can send data by making a POST request to the Telegram API with the required parameters (chat_id and text).
I’m considering two main approaches: integrating into current.php or creating a separate file like send_to_telegram.php. A separate script might be better to avoid spamming the channel every time the data updates. It could be triggered manually or by a cron job, ensuring updates only occur when data changes.
Ниже пример файла send_to_telegram.php, который получает текущие данные с API и отправляет их в Telegram-бота для публикации на канале. Не забудь заменить PLACEHOLDER в переменных $botToken и $chatId на реальные значения.
<?php
// send_to_telegram.php
// Конфигурация
$botToken = 'YOUR_TELEGRAM_BOT_TOKEN'; // Замените на реальный токен
$chatId = '@YOUR_CHANNEL_USERNAME'; // Замените на реальный ID канала
// Файл для хранения последнего состояния
$lastDataFile = 'last_data.json';
// Получаем данные с API
$apiUrl = 'https://meta.hostingradio.ru/rmg/maximum/native/current.json';
$response = file_get_contents($apiUrl);
if ($response === false) {
file_put_contents('error.log', date("Y-m-d H:i:s") . " Ошибка получения данных с API\n", FILE_APPEND);
exit('Ошибка получения данных с API');
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
file_put_contents('error.log', date("Y-m-d H:i:s") . " Ошибка декодирования JSON\n", FILE_APPEND);
exit('Ошибка декодирования JSON');
}
// Проверяем вложенность данных
if (isset($data['current'])) {
$data = $data['current'];
}
// Проверяем наличие необходимых полей
if (!isset($data['id']) || empty($data['id']) || !isset($data['title']) || empty($data['title'])) {
file_put_contents('error.log', date("Y-m-d H:i:s") . " Нет ID или Title в API-ответе\n", FILE_APPEND);
exit('Ошибка: нет ID или Title в ответе API');
}
$currentData = [
'id' => $data['id'],
'title' => $data['title'],
'startTime' => $data['startTime'] ?? '',
'artist' => $data['artist'] ?? '',
'album' => $data['album'] ?? '',
'genres' => $data['genres'] ?? '',
'spotify_popularity' => $data['spotify_popularity'] ?? '',
'youtubeUrl' => $data['youtubeUrl'] ?? '',
'itunesUrl' => $data['itunesUrl'] ?? '',
'spotifyUrl' => $data['spotifyUrl'] ?? '',
'coverImageWebpUrl600' => $data['coverImageWebpUrl600'] ?? ''
];
// Читаем предыдущее состояние
$lastData = file_exists($lastDataFile) ? json_decode(file_get_contents($lastDataFile), true) : [];
// Проверяем, изменились ли данные
if ($lastData == $currentData) {
exit('Композиция не изменилась. Публикация не требуется.');
}
// Формируем сообщение
$message = "🎵 *Сейчас играет на Радио Maximum:*\n";
$message .= "📅 *Время:* " . $currentData['startTime'] . "\n";
$message .= "🎤 *Исполнитель:* " . $currentData['artist'] . "\n";
$message .= "🎶 *Композиция:* " . $currentData['title'] . "\n";
$message .= "💽 *Альбом:* " . $currentData['album'] . "\n";
$message .= "🎼 *Жанр:* " . $currentData['genres'] . "\n";
$message .= "📊 *Spotify рейтинг:* " . $currentData['spotify_popularity'] . "\n\n";
// Добавляем ссылки
if (!empty($currentData['youtubeUrl']) && $currentData['youtubeUrl'] !== '-') {
$message .= "▶️ [Слушать на YouTube](" . $currentData['youtubeUrl'] . ")\n";
}
if (!empty($currentData['itunesUrl']) && $currentData['itunesUrl'] !== '-') {
$message .= "🍏 [Слушать на iTunes](" . $currentData['itunesUrl'] . ")\n";
}
if (!empty($currentData['spotifyUrl']) && $currentData['spotifyUrl'] !== '-') {
$message .= "🎧 [Слушать на Spotify](" . $currentData['spotifyUrl'] . ")\n";
}
// Определяем метод отправки (с картинкой или без)
if (!empty($currentData['coverImageWebpUrl600']) && $currentData['coverImageWebpUrl600'] !== '-') {
$url = "https://api.telegram.org/bot{$botToken}/sendPhoto";
$postFields = [
'chat_id' => $chatId,
'photo' => $currentData['coverImageWebpUrl600'],
'caption' => $message,
'parse_mode' => 'Markdown'
];
} else {
$url = "https://api.telegram.org/bot{$botToken}/sendMessage";
$postFields = [
'chat_id' => $chatId,
'text' => $message,
'parse_mode' => 'Markdown'
];
}
// Отправляем запрос в Telegram
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if ($result === false) {
file_put_contents('error.log', date("Y-m-d H:i:s") . " Ошибка cURL: " . curl_error($ch) . "\n", FILE_APPEND);
exit('Ошибка cURL: ' . curl_error($ch));
}
curl_close($ch);
// Лог успешной отправки
file_put_contents('log.txt', date("Y-m-d H:i:s") . " Отправлено: ID {$currentData['id']} - Title {$currentData['title']}\n", FILE_APPEND);
// Обновляем сохранённые данные
file_put_contents($lastDataFile, json_encode($currentData));
echo 'Сообщение успешно отправлено!';
?>
Пояснения:
-
Файл получает данные по тому же API, что используется в основном интерфейсе.
-
Если данные находятся внутри дополнительного уровня (например, ключ «current»), они извлекаются.
-
Сообщение формируется с ключевыми полями: время, исполнитель, композиция, альбом, жанр и рейтинг.
-
Если доступны ссылки (YouTube, iTunes, Spotify) — они добавляются в текст.
-
Если поле с обложкой содержит URL, отправляется метод sendPhoto, иначе — sendMessage.
-
Для отправки используется cURL-запрос к API Telegram.
Запусти этот скрипт (например, вручную или по cron), чтобы переслать данные в Telegram-канал. Если требуется автоматизация, можно добавить проверку на изменение данных, чтобы не спамить канал каждые 10 секунд.
Что исправлено и улучшено:
✅ Добавлен лог ошибок — ошибки записываются в error.log
✅ Добавлен лог успешных отправок — создаётся log.txt с ID трека
✅ Используется Markdown для Telegram (жирный текст, ссылки)
✅ Исправлена проверка ID — если его нет, скрипт не падает
✅ Убраны лишние exit() — теперь ошибки записываются, а не просто прерывают работу
✅ Используется curl_error($ch) — теперь можно увидеть ошибки cURL