Информер USD/EUR и криптовалют BTC/ETH в Телеграм бот PHP

09.01.2023     👁 2309


В продолжении предыдущих статей:

Внимание!

Прежде чем продолжить, давайте поясню: вы пишите, что в преудущих статьях бот не работает, но не забывайте, что вы правильно проделали все действия последовательно: начните с 1й статьи — Как создать простого бота для Телеграм на PHP — и заставьте его работать, а далее последовательно добавляйте меню и информеры. Возможно, на каком-то этапе закралась ошибка.

Данный бот должен работать, я его взял из https://t.me/novelsite_bot, заменив все персональные данные и ключи API.
Не забывайте их заменить на свои!
Не забывайте про работающий https!
Не забывайте правильно прописать webhook вашего бота и сообщить его Телеграм!
Не забывайте дать права на запись в папке бота!
На сервере PHP должен работать модуль CURL

Информер курсов USD/EUR и криптовалют BTC/ETH в Телеграм бот на PHP

Готовый код бота можно скачать по ссылке: bot_usd_btc.zip

1. ПОлучим курсы USD/EUR к рублю с сайта центробанка

  1. Курсы валют будем получать отсюда https://www.cbr.ru/scripts/XML_daily.asp
  2. Напишем функцию простого парсинга cbr_get_currency для полученгия данных по USD и EUR используя библиотеку simplexml_load_file
  3. Для снижения количества обращений к cbr (вдруг забанят), сделаем кэширование в файле и будем заменять кэш, например раз в час (3600 секунд)
  4. Дайте папке где будет сохранятся кэш-файл права на создание и запись файлов
function cbr_get_currency($currency_code) 
{
    $format = 4;
    $currency_code = (isset($currency_code) && $currency_code != '') ? strtoupper($currency_code) : 'USD';
	$date = date('d/m/Y'); // Текущая дата
	$cache_time_out = '3600'; // Время жизни кэша в секундах
	$file_currency_cache = __DIR__.'/XML_daily.xml';
	if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_daily.asp?date_req='.$date);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_HEADER, 0);
		$out = curl_exec($ch);
		curl_close($ch);
		file_put_contents($file_currency_cache, $out);
	}

	$content_currency = simplexml_load_file($file_currency_cache);
	$kurs = $content_currency->xpath('Valute[CharCode="'.$currency_code.'"]')[0]->Value;
	$nominal = $content_currency->xpath('Valute[CharCode="'.$currency_code.'"]')[0]->Nominal;
	return number_format(str_replace(',', '.', $kurs), $format).' ₽ за '.$nominal.' '.$currency_code;
}

Сервер возвращает результаты в виде массива XML-данных.

Теперь перепишем бота

  1. Добавим меню USD - пусть будет команда /cbr или /usd или /eur
  2. Добавим кусок кода в обработку бота
		elseif (substr($text, 0, 4) == '/cbr' || substr($text, 0, 4) == '/usd' || substr($text, 0, 4) == '/eur') {
            $text_return = cbr_get_currency('USD')."\n".cbr_get_currency('EUR')."\n";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/cbr');
        }

2. Получим курсы криптовалют BTC/ETH

  1. Курсы валют будим получать отсюда https://coincap.io
  2. Напишем функцию простого парсинга bitcoin_get_currency для полученгия данных по BTC и ETH используя json_decode и простой перебор массива
  3. Кэширование данных добавлять не стал, можете также как в USD примере сделать, если хотите
function bitcoin_get_currency()
{
	$text_return = '';
	$currency_code = '';
	if ($currency_code == '') {
		$curl = curl_init();
		curl_setopt_array($curl, array(
		  CURLOPT_URL => 'api.coincap.io/v2/assets',
		  CURLOPT_RETURNTRANSFER => true,
		  CURLOPT_ENCODING => '',
		  CURLOPT_MAXREDIRS => 10,
		  CURLOPT_TIMEOUT => 0,
		  CURLOPT_FOLLOWLOCATION => true,
		  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
		  CURLOPT_CUSTOMREQUEST => 'GET',
		));

		$response = curl_exec($curl);
		curl_close($curl);
		$data = json_decode($response, true);
		foreach($data['data'] as $p) {
			if ($p['id'] == 'bitcoin' || $p['id'] == 'ethereum') {
				$text_return .= $p['symbol'].": ".round($p['priceUsd'])." USD\n";
			}
		}
	}
	return $text_return;
}

Сервер возвращает результаты в виде json данных, которые и обработаем найдя bitcoin и etherium.

Теперь перепишем бота

  1. Добавим меню BTC - пусть будет команда /bitcoin или /btc или /eth
  2. Добавим кусок кода в обработку бота
		elseif (substr($text, 0, 8) == '/bitcoin' || substr($text, 0, 4) == '/btc' || substr($text, 0, 4) == '/eth') {
            $text_return = bitcoin_get_currency();
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/bitcoin');
        }

И в итоге получим весь код бота:

header('Content-Type: text/html; charset=utf-8');
/**
*   Simple chat bot Novelsite.ru
*
*   + usd + bitcoin + eth informers
*   
*   Webhook:
*   https://api.telegram.org/botXXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY/setWebhook?url=https://www.yoursite.ru/your_bot.php
*
*/

error_reporting(0);

$site_dir = dirname(dirname(__FILE__)).'/';
$bot_token = 'XXXXXXXXXX:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY';
$data = file_get_contents('php://input');
$data = json_decode($data, true);

$order_chat_id = 'MMMMMMMMM'; //manager for orders
$bot_state = '';

// last message to file
file_put_contents(__DIR__ . '/message.txt', print_r($data, true));
file_put_contents(__DIR__ . '/message_ip.txt', $_SERVER['REMOTE_ADDR']);

// buttons hack from callback_query
if (!empty($data['callback_query']['data'])) {
    $data['message']['from']['id'] = $data['callback_query']['from']['id'];
    $data['message']['from']['first_name'] = $data['callback_query']['from']['first_name'];
    $data['message']['from']['last_name'] = $data['callback_query']['from']['last_name'];
    $data['message']['text'] = $data['callback_query']['data'];
}

// message parsing
if (!empty($data['message']['text'])) {
    $chat_id = $data['message']['from']['id'];
    $user_name = $data['message']['from']['username'];
    $first_name = $data['message']['from']['first_name'];
    $last_name = $data['message']['from']['last_name'];
    $text = trim($data['message']['text']);
    $text_array = explode(" ", $text);
    

    $bot_state = get_bot_state ($chat_id);
    
    // send text order if need
    if (substr($bot_state, 0, 6) == '/order') {
        $text_return = 
"
Заявка от @$user_name:
Имя: $first_name $last_name 
$text
";
        message_to_telegram($bot_token, $order_chat_id, $text_return);
        set_bot_state ($chat_id, '');
    }
    else {
    
        if ($text == '/help' || mb_strstr($text, 'Помощь')) {
            $text_return = "$first_name $last_name, вы можете нажимать кнопки снизу или вводить команды: 
/help - список команд
/srv - список услуг
/about - о нас
/contact - контакты
/order - оставить заявку
/cbr - курсы валют
/btc - курсы криптовалют bitcoin, ethereum
/pogoda 1 - погода за 1 день

";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/help');
        }
        
        elseif (substr($text, 0, 4) == '/srv' || mb_strstr($text, 'Что')) {
            $ret = [];
            $num = (int)$text_array[array_key_last($text_array)];
            if ($num == 1) {
                $text_return = 
"1. Услуга 1:
--------------------------------------------------------
Описание услуги 1
";      
                $ret = [
                    ["text"=>"⬅️ Вернуться в Услуги", "callback_data"=>'/srv'],
                ];
            }
            elseif ($num == 2) {
                $text_return = 
"2. Услуга 2:
--------------------------------------------------------
Описание услуги 2
";      
                $ret = [
                    ["text"=>"⬅️ Вернуться в Услуги", "callback_data"=>'/srv'],
                ];
            }
        
            else {
                $text_return = 
"Услуги компании:
--------------------------------------------------------
 1. Услуга 1
 2. Услуга 2
";      
            }

            $reply_markup = json_encode([
                "inline_keyboard" => [
                    [
                        ["text"=>"1", "callback_data"=>'/srv 1'],
                        ["text"=>"2", "callback_data"=>'/srv 2'],
                    ],
                    $ret,
                ]
            ]);
                
            message_to_telegram($bot_token, $chat_id, $text_return, $reply_markup);
            set_bot_state ($chat_id, '/srv');
        }
        elseif (substr($text, 0, 6) == '/about' || mb_strstr($text, 'Кто')) {
            $text_return = 
"О компании:
--------------------------------------------------------
О компании: ООО \"Компания\";
Адрес: Город, улица, офис;
Описание проезда
";          
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/about');
        }
        elseif (substr($text, 0, 8) == '/contact' || mb_strstr($text, 'Контакты')) {
            $text_return = 
"Контакты компании:
--------------------------------------------------------
Телефон: +77777777777
E-mail: info@mydomain.ru
Сайт: www.mydomain.ru
Адрес: Город, улица, офис;
";          
            message_to_telegram($bot_token, $chat_id, $text_return);
        }
 
		elseif (substr($text, 0, 4) == '/cbr' || substr($text, 0, 4) == '/usd' || substr($text, 0, 4) == '/eur') {
            $text_return = cbr_get_currency('USD')."\n".cbr_get_currency('EUR')."\n";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/cbr');
        }
		
		elseif (substr($text, 0, 8) == '/bitcoin' || substr($text, 0, 4) == '/btc' || substr($text, 0, 4) == '/eth') {
            $text_return = bitcoin_get_currency();
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/bitcoin');
        }

        elseif (substr($text, 0, 7) == '/pogoda' || mb_strstr($text, "Погода")) {
            $num = (int)$text_array[array_key_last($text_array)];
            $city = "Yekaterinburg";
            $country = "RU";
            $mode = "json";
            $units = "metric";
            $lang = "ru";
            $countDay = ($num > 0) ? $num : 1;
            $appID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // ваш API погоды!
            $url = "http://api.openweathermap.org/data/2.5/forecast?q=$city,$country&cnt=$countDay&lang=$lang&units=$units&appid=$appID";
            $data = @file_get_contents($url);

            $text_return = '';
            if ($data) {
                $clima = json_decode($data, true);
                foreach($clima['list'] as $p) {
                    $text_return .= date("d.m.Y", $p['dt']).": ".$p['weather'][0]['description']."\n";
                    $text_return .= " Температура: ".round($p['main']['temp_min'])."°C .. ".round($p['main']['temp_max'])."°C\n";
                    $text_return .= " Влажность: ".$p['main']['humidity']."%\n";
                    $text_return .= " Ветер: ".$p['wind']['speed']."км/ч\n\n";
                }
            }
            else {
                $text_return = 'Тишина...';
            }
            message_to_telegram($bot_token, $chat_id, $text_return);
        }

        
        elseif (substr($text, 0, 6) == '/order' || mb_strstr($text, "Заявка")) {
            $ret = [];
            $num = (int)$text_array[array_key_last($text_array)];
            $text_return = 
    "$first_name $last_name, для подтверждения Заявки введите текст вашей заявки и нажмите отправьте его боту. 
    Наши специалисты свяжутся с вами в ближайшее время!
    ";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '/order '.$num);
        }
        elseif (!mb_strstr($text, 'Заявка от')) {
            $text_return = "Привет, $first_name $last_name!
Я бот компании. 
С помощью меня вы можете узнать о нас, услугах
/help - список команд
";
            message_to_telegram($bot_token, $chat_id, $text_return);
            set_bot_state ($chat_id, '');
        }
        
    }

}

// return answer to callback_query
if (!empty($data['callback_query']['data'])) {
   $callback_query_id = $data['callback_query']['id'];
   file_get_contents("https://api.telegram.org/bot".$bot_token."/answerCallbackQuery?callback_query_id=".$callback_query_id."&text=");
}


function message_to_telegram($bot_token, $chat_id, $text, $reply_markup = '')
{
    $ch = curl_init();
    if ($reply_markup == '') {
        $btn[] = ["text"=>"Кто", "callback_data"=>'/about'];
        $btn[] = ["text"=>"Что", "callback_data"=>'/srv'];
        $btn[] = ["text"=>"Где", "callback_data"=>'/contact'];
        $btn[] = ["text"=>"Заявка", "callback_data"=>'/order'];
        $btn[] = ["text"=>"USD", "callback_data"=>'/cbr'];
		$btn[] = ["text"=>"BTC", "callback_data"=>'/bitcoin'];
        $btn[] = ["text"=>"Погода", "callback_data"=>'/pogoda'];
        $reply_markup = json_encode(["keyboard" => [$btn],  "resize_keyboard" => true]);
    }
    $ch_post = [
        CURLOPT_URL => 'https://api.telegram.org/bot' . $bot_token . '/sendMessage',
        CURLOPT_POST => TRUE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_POSTFIELDS => [
            'chat_id' => $chat_id,
            'parse_mode' => 'HTML',
            'text' => $text,
            'reply_markup' => $reply_markup,
        ]
    ];

    curl_setopt_array($ch, $ch_post);
    curl_exec($ch);
}


function photo_to_telegram($bot_token, $chat_id, $text, $photo_url)
{
    $ch = curl_init();
    $ch_post = [
        CURLOPT_URL => 'https://api.telegram.org/bot' . $bot_token . '/sendPhoto',
        CURLOPT_POST => TRUE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_HTTPHEADER => ["Content-Type:multipart/form-data"],
        CURLOPT_POSTFIELDS => [
            'chat_id' => $chat_id,
            'photo' => new CURLFile(realpath($photo_url)),
            'caption' => $text,
        ]
    ];

    curl_setopt_array($ch, $ch_post);
    curl_exec($ch);
}

function set_bot_state ($chat_id, $data)
{
    file_put_contents(__DIR__ . '/users/'.$chat_id.'.txt', $data);   
}

function get_bot_state ($chat_id)
{
    if (file_exists(__DIR__ . '/users/'.$chat_id.'.txt')) {
        $data = file_get_contents(__DIR__ . '/users/'.$chat_id.'.txt');
        return $data;
    }
    else {
        return '';
    }
}



if (! function_exists("array_key_last")) {
    function array_key_last($array) {
        if (!is_array($array) || empty($array)) {
            return NULL;
        }
         
        return array_keys($array)[count($array)-1];
    }
}

function cbr_get_currency($currency_code) 
{
    $format = 4;
    $currency_code = (isset($currency_code) && $currency_code != '') ? strtoupper($currency_code) : 'USD';
	$date = date('d/m/Y'); // Текущая дата
	$cache_time_out = '3600'; // Время жизни кэша в секундах
	$file_currency_cache = __DIR__.'/XML_daily.xml';
	if(!is_file($file_currency_cache) || filemtime($file_currency_cache) < (time() - $cache_time_out)) {
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'https://www.cbr.ru/scripts/XML_daily.asp?date_req='.$date);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_HEADER, 0);
		$out = curl_exec($ch);
		curl_close($ch);
		file_put_contents($file_currency_cache, $out);
	}

	$content_currency = simplexml_load_file($file_currency_cache);
	$kurs = $content_currency->xpath('Valute[CharCode="'.$currency_code.'"]')[0]->Value;
	$nominal = $content_currency->xpath('Valute[CharCode="'.$currency_code.'"]')[0]->Nominal;
	
	return number_format(str_replace(',', '.', $kurs), $format).' ₽ за '.$nominal.' '.$currency_code;
}


function bitcoin_get_currency()
{
	$text_return = '';
	$currency_code = '';
	
	if ($currency_code == '') {
		$curl = curl_init();
		curl_setopt_array($curl, array(
		  CURLOPT_URL => 'api.coincap.io/v2/assets',
		  CURLOPT_RETURNTRANSFER => true,
		  CURLOPT_ENCODING => '',
		  CURLOPT_MAXREDIRS => 10,
		  CURLOPT_TIMEOUT => 0,
		  CURLOPT_FOLLOWLOCATION => true,
		  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
		  CURLOPT_CUSTOMREQUEST => 'GET',
		));

		$response = curl_exec($curl);
		curl_close($curl);
		
		$data = json_decode($response, true);
		
		foreach($data['data'] as $p) {
			if ($p['id'] == 'bitcoin' || $p['id'] == 'ethereum') {
				$text_return .= $p['symbol'].": ".round($p['priceUsd'])." USD\n";
			}
		}	
	}
	return $text_return;
}

P.S. Данный пример содержит работающий код бота на PHP, который может выдавать меню, показывать информацию по меню, есть подменю в разделе услуги, есть возможность отослать заявку менеджеру, и информеры: погода, валюты, криптовалюты. Для текста в кнопках меню бота и в выводах результатов можно использовать Эмодзи.

 


Николай Комарков



Подписывайся на наш Телеграм

Подписывайся на наш
Телеграм канал!
Контекст решает