Pull to refresh

ПитательныйБот или как я хочу отобрать хлеб у фитнес-тренеров

Reading time5 min
Views5.9K
Всем привет! Все разработчики сталкиваются однажды с желанием покодить что-нибудь для себя, и даже становится неважна материальная ценность продукта, главное, что оно работает само по себе. Кайф.  

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

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

И я решила: а создам-ка я такую систему, которая будет автоматически высчитывать людям продукты в граммах, в зависимости от их цели и параметров.

Так как я бэкенд разработчик, с фронтом сталкиваюсь редко, обдумала и решила сделать бота. На выбор мессенджера повлияли несколько факторов: востребованность и наличие платежных систем. Подошла социальная сеть Вконтакте.

Для расчетов я использовала формулу Харриса- Бенедикта. В учет брала такие входные параметры ( которые пользователь бота вводит):

  • Вес
  • Рост
  • Цель (похудеть/ набрать массу/ поддерживать)
  • Физическая активность (вся информация доступная и стандартная для расчетов по формуле Харриса-Бенедикта)
  • Переносимость лактозы
  • Пол

Создала базу продуктов, в которой у продукта были поля: Белки, Жиры, Углеводы, Ккал, ГИ (гликемический индекс), а также содержание лактозы. Вообще, хочу привести листинг и по ходу комментировать.

У Вконтакте доступный и понятный API

Использовала язык PHP.

Во-первых, определила несколько нужных функций и констант:

header('Content-Type: text/html; charset=utf-8');
$request = file_get_contents("php://input"); 
$input = json_decode($request, true);

define('VK_API_VERSION', '5.95'); //Используемая версия API 
define('VK_API_ENDPOINT', "https://api.vk.com/method/"); 

//Функция для вызова произвольного метода API 
function _vkApi_call($method, $params = array()) { 
  $params['access_token'] = //Тут должен быть ваш токен, который вы получаете при создании бота в паблике; 
  $params['v'] = VK_API_VERSION; 
  $url = VK_API_ENDPOINT.$method.'?'.http_build_query($params); 
  $curl = curl_init($url); 
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
  $json = curl_exec($curl); 
  curl_close($curl); 
  $response = json_decode($json, true); 
  return $response['error']['error_msg']; 
  $err=$response['error']['error_msg'];
} 

//Функция для вызова messages.send 
function vkApi_messagesSend($peer_id, $message) { 
 return _vkApi_call('messages.send', array( 
 'peer_id' => $peer_id, 
 'user_id' => $peer_id, 
 'message' => $message, 
 'random_id' => rand(), 
 'qroup_id' => //Здесь должен быть айдишник вашей группы (паблика)    
  ));} 

//Функция для отправки кнопок с сообщением
function vkApi_buttonSend($peer_id, $message,$button) { 
return _vkApi_call('messages.send', array( 
'peer_id' => $peer_id, 
'user_id' => $peer_id, 
'message' => $message, 
'random_id' => rand(), 
'keyboard' => $button, 
'qroup_id' => //Здесь должен быть айдишник вашей группы (паблика)       
  ));} 

В настройках бота вы указывается ссылку на свой скрипт (вебхук). Кстати, в API VK можно использовать два метода для получения сообщений. Я использовала вебхуки. Мне кажется, что это удобнее, привычнее.

Далее обрабатываю полученный json.

$test_type=$input['type'];
$test_group_id=$input['group_id'];
$user_id=$input['object']['user_id'];
$text=$input['object']['body'];
$text_body=explode(" ", $text);

$vk_pay=$text_body[0];
$caption=$input['object']['attachments'][0]['link']['caption'];
$url=$input['object']['attachments'][0]['link']['url'];
$str3=$input['object']['attachments'][0]['link']['title'];
$str2 = explode(" ", $str3);
$money =(int)$str2[0];
$money=strstr($str3, ' ', true);
$money=(int)$money;

Так как у VK есть платежные системы, я предусмотрела оплату через VK pay (сервера VK отправляют на ваш вебхук такие запросы, но только если у вас паблик указан как МАГАЗИН и есть ТОВАР, который можно оплатить через VK pay), а также оплату простым денеженым переводом, который можно прикрепить к сообщению.

Каждого пользователя, который пишет что-то боту, сохраняю в базе, и далее всё общение с ботом происходит в зависимости от оплаты. Если оплаты не было, бот скажет, что нужно сначала оплатить, если оплата произошла — подскажет, что делать дальше. Для тестирования можно ввести любое сообщение боту для составления плана.

После оплаты, бот будет спрашивать параметры, необходимые для расчета, сохраняю это всё в базе для конкретного пользователя, а после всей полученной информацию считаю и выдаю ответ. Отправляю сообщение, используя созданную функцию, указав user_id пользователя:

vkApi_messagesSend($user_id, 'Отлично! Какой твой возраст?'); 

Также учла момент неправильного ввода пользователем какой-нибудь информации: в таком случае нужно отправить боту число 404, и он начнет спрашивать сначала, обнулив данные в базе.

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

$buttons='{ 
"one_time":true, 
 "buttons":[[{ 
 "action":{ 
 "type":"text", 
 "payload":"{\"button\": \"1\"}", 
 "label":"Я женщина" }, 
 "color":"primary" }, 
 { 
 "action":{ 
 "type":"text", 
 "payload":"{\"button\": \"2\"}", 
 "label":"Я мужчина" }, 
 "color":"primary"}]]}';
vkApi_buttonSend($user_id,'Укажи пол',$buttons) ;

А дальше всё самое интересное! После собранных данных происходит сам расчет. Ничего не придумываю сама, лишь правильно оформляю нужные формулы, опираясь на формулу Харриса-Бенедикта, а также знания в области правильного питания (здесь важны количества приемов пищи, процентное распределение белков/жиров/углеводов на эти приемы и т.д.).

Вообщем, подобные вещи:

$BMR=88.363+(13.397*$weight)+(4.799*$height)-(5.677*$age);
$BMR_AMR=$BMR*1.2-500;
$b_kkal=0.35*$BMR_AMR;
$b_gr=$b_kkal/4;
$g_kkal=0.3*$BMR_AMR;
$g_gr=$g_kkal/9;
$u_kkal=0.35*$BMR_AMR;
$u_gr=$u_kkal/4;
$break_b=0.15*$b_gr;
$break_u=0.25*$u_gr;
$break_g=0.25*$g_gr;
$break_kk=0.25*$BMR_AMR;
$snack_b=0.1*$b_gr;
$snack_u=0.1*$u_gr;
$snack_g=0.15*$g_gr;
$snack_kk=1*$BMR_AMR;
$snack2_b=0.05*$b_gr;
$snack2_u=0.05*$u_gr;
$snack2_kk=0.05*$BMR_AMR;
$lunch_b=0.45*$b_gr;
$lunch_u=0.4*$u_gr;
$lunch_g=0.4*$g_gr;
$lunch_kk=0.4*$BMR_AMR;
$dinner_b=0.25*$b_gr;
$dinner_u=0.2*$u_gr;
$dinner_g=0.2*$g_gr;
$dinner_kk=0.2*$BMR_AMR;

Соответственно, для людей с сидячим образом жизни и людей с гиперактивностью будут другие коэффициенты, я привела небольшой пример.

После высчитанных БЖУ и ККАЛ собираю набор продуктов. Кстати, если после полученного плана питания ввести число 404 и начать сначала (возможнно похудели/набрали вес, изменился образ жизни и т.д.), набор продуктов рандомно изменится. И вот у вас уже другой план питания!

В итоге получился вот такой вот сервис (я его официально разместила ВК для тестирования, разработчик я начинающий, и сама не могу поймать все свои баги, если вдруг они есть):

скриншоты бота
image image
image image


Из замеченных мною ошибок (требует доработки) :


  • Кнопки не открываются сразу. Нужно найти возле кнопки «отправить» значок клавиатуры. Это очень путает людей, и пишут неправильно (если кнопка нажата, то я обрабатываю текст с кнопки, данные, которые пользователь вводит сам, игнорируются).
  • Не очень большая база продуктов, столкнулась с тем, что такое кушать никто не будет.

Для желающих потестить и посмотреть ссылка на паблик.
Tags:
Hubs:
Total votes 27: ↑15 and ↓12+3
Comments23

Articles