• Mysql и Telegram bot

  •  

В интернете и так полным-полно мануалов по подключению базы данных к любому скрипту. Однако, несмотря на такое обилие информации, мои комментарии буквально ломятся от вопросов вида «как?»: «подключить, использовать, настроить» базу данных к telegram боту. Окей, почему бы не написать об этом соответствующую статью.

За основу возьмем заготовку, написанную в статье про бота для Telegram на Php, потому что в основном такие сложности возникают у читателей в комментариях этого материала.

Основа

Имеется скрипт-заготовка бота и имеется mysql, а так-же phpmyadmin, который мы и будем использовать для создания базы.

Да, чтобы работать с базой данных ее надо сначала… создать! Увы, система не сделает ничего за вас, придется делать все вручную. При первом знакомстве в mysql меня это немного разочаровало, но такова реальность. Можно, конечно, написать скрипт инициализации на манер wordpress’овского, я подобное уже делал, но это явно будет не уровень новичка. Поэтому руками, все руками!

Открываем phpmyadmin, заходим туда и создаем новую базу данных. Я назову ее «revcom_base»;

Тыкаем там создать, а потом переходим туда внутрь. Внутри базы нам надо перейти на вкладку «Операции». Там будет возможность создать первую таблицу.

Называем ее users и тыкаем «вперед». После чего задаем параметры столбцов в таблице:

ВНИМАНИЕ! Тут опечатка у поля Name должен быть тип или TEXT или VARCHAR!

Поле id у нас имеет атрибут A_I, то есть AUTO_INCREMENT, что означает буквально: у каждого нового пользователя будет свой id, который автоматически будет увеличиваться на 1 для каждого нового пользователя. Поле data_json — это данные пользователя. Если проще — обычное текстовое поле. В него будем записывать пользовательские настройки в формате json. Остальное думаю и так понятно.

Замечу, что все это можно было сгенерить используя SQL, но для простоты делать этого мы тут не будем.

Тыкаем внизу «создать» и получаем первую и единственную нужную нам для демонстрации таблицу. Теперь создадим «модель» то есть php обертку таблицы, которая удобно позволит работать с ней. Ато развелось любителей создавать сложные select запросы и всякие там fetch_assoc прямо в обработчиках команд… Так конечно тоже можно, но код смотрится страшно… И это не верный подход. Поэтому делать будем обертку.

Однако сначала подключение.

Подключение к базе данных

Тут все элементарно. Создаем файл «db_connect.php» прямо в папке бота, куда помещаем типичный шаблонный код:


<?php
/*подключение к базе данных*/

$host = "localhost"; // в 90% случаев это менять не надо
$password = "ваш пароль от phpmyadmin";
$username = "юзернейм, с которым вы входили в phpmyadmin";
$databasename = "revcom_base";

global $db;
$db = mysql_connect($host,$username,$password) or die("error: Failed_connect_database");

mysql_select_db($databasename, $db) or die("error:Database not selected witch mysql_select_db");

mysql_query('SET NAMES utf8',$db);
mysql_query('SET CHARACTER SET utf8',$db );
mysql_query('SET COLLATION_CONNECTION="utf8_general_ci"',$db ); 
setlocale(LC_ALL,"ru_RU.UTF8");

Используем этот файл в начале нашего бота, размещая там строчку

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

И на страничке бота ошибок нет:

Если у вас есть — указывайте правильные логин и пароль к базе до тех пор пока ошибки не пропадут.

Модель базы

Теперь делаем обертку для нашей базы данных.

Что нам надо уметь?

  1. Нам надо уметь создавать новых пользователей, то есть создавать новые записи в таблице «users»
  2. Нам надо уметь проверять есть этот пользователь в базе или его нет(чтобы не плодить сущности и не создавать по две-три записи в базе для одного пользователя)
  3. Нам надо уметь добавлять данные настроек бота(какие-нибудь) к пользователю
  4. Нам надо уметь считывать сохраненные данные пользователя

Ну вот и пишем нужные нам методы.

Вставка пользователей в базу

Первый метод — это создание, то есть сохранение юзера, в таблицу и выглядеть он будет так:

function make_user($name,$chat_id){
	global $db;
	$name = mysql_real_escape_string($name);
	$chat_id = mysql_real_escape_string($chat_id);
	$query = "insert into `users`(name,chat_id) values('{$name}','{$chat_id}')";
	mysql_query($query,$db) or die("пользователя создать не удалось");
}

Добавим этот метод в файл users.php, который, разумеется, надо сначала создать. Этот файл и будет нашей моделью для работы с базой.


Подключать его надо ниже под db_connect.php, вот так:

 

Ну и, чтобы … убрать вашу неуверенность, вот так выглядит сам файл users.php с нужным нам методом, на данном этапе:

 

Теперь давайте протестируем как работает этот метод. Человек должен добавляться в базу при поступлении от него первой команды. Поэтому лучше всего будет добавить метод make_user в начало секции on то есть вот, примерно, так:

// регистрация юзера
$bot->on(function($Update) use ($bot){
	$message = $Update->getMessage();
	$mtext = $message->getText();
	$cid = $message->getChat()->getId();
	make_user($message->getFrom()->getUsername(),$cid);
	
}, function($message) use ($name){
	return true; // когда тут true - команда проходит
});

Если у вас уже этот обработчик есть просто добавьте строчку make_user($message->getFrom()->getUsername(),$cid); в нужное место.

Ну и, собственно, сохраняем, а потом пишем что-нибудь боту. Это должно добавить новую запись в таблицу.

Ремарка: у меня phpmyadmin глючит(чинить лень ибо это ни на что не влияет), поэтому внутрь таблицы я зайти не могу(а значит не могу и скриншет содержимого сделать), это исключительно проблема моего собственного сервера, у вас таких проблем быть не должно.

Впрочем это никак не повредит мне в разработке т.к. я отлично представляю себе как работает mysql.

Проверка на наличие пользователя в базе

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

Для этого будем использовать запрос select и mysql_fetch_array вот так:

function is_user_set($name){
	global $db;
	$name = mysql_real_escape_string($name);
	$result = mysql_query("select * from `users` where name='$name' LIMIT 1",$db);

    if(mysql_fetch_array($result) !== false) return true;
    return false;
}

Теперь мы можем проверять есть этот пользователь в базе или нет. Делаем в методе on так:

if(is_user_set($message->getFrom()->getUsername()) == false){
		make_user($message->getFrom()->getUsername(),$cid);
	}

Отлично, теперь сущности не плодятся:

Сохранение пользовательских данных

Теперь надо добавить методы задания настроек пользователем и считывания этих настроек, соответственно. Вообще зачем эти настройки нужны? А нужны они нам для множества разных вещей, от работы с несколькими состояниями бота, до, например, приема отзывов на бота.

// задание настройки
function set_udata($name,$data = array()){
	global $db;
	$name = mysql_real_escape_string($name);
	if(!is_user_set($name)){
		make_user($name,0); // если каким-то чудом этот пользователь не зарегистрирован в базе
	}
	$data = json_encode($data,JSON_UNESCAPED_UNICODE);
	mysql_query("update `users` SET data_json = '{$data}' WHERE name = '{$name}'",$db); // обновляем запись в базе
}

// считываение настройки
function get_udata($name){
	global $db;
	$res = array();
	$name = mysql_real_escape_string($name);
	$result = mysql_query("select * from `users` where name='$name'",$db);
	$arr = mysql_fetch_assoc($result);
    if(isset($arr['data_json'])){
		$res = json_decode($arr['data_json'], true);
	}
	
	return $res;
}

Для проверки этих методов засунем в on такой код:

// сохранение тестовых данных
	$data = array( "prevmsg" => $mtext );
	set_udata($message->getFrom()->getUsername(), $data);
	
	// тест получения данных
	$data = get_udata($message->getFrom()->getUsername());
	$bot->sendMessage($message->getChat()->getId(), json_encode($data,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); // тут меня кто-то спрашивал как дебажить базу данных. Вот так ее дебажат.

Теперь можно написать что-нибудь в бота и посмотреть на результат. Сначала надпись будет в базу помещена, а потом выдана нам в формате массива.

Все работает, так, как я и задумывал.

Пример использования

Теперь давайте сделаем небольшое взаимодействие с этим инструментарием.

Создадим разветвленный диалог вида: «ваше имя, ваш сайт» и после получения этих данных сохраним их в базе.

// регистрация юзера
$bot->on(function($Update) use ($bot){
	$message = $Update->getMessage();
	$mtext = $message->getText();
	$cid = $message->getChat()->getId();
	
	if(is_user_set($message->getFrom()->getUsername()) == false){
		make_user($message->getFrom()->getUsername(),$cid);
	}
	
	$data = get_udata($message->getFrom()->getUsername()); // получаем массив данных
	if(!isset($data["mode"])){ // если в нем нет режима - значит человек еще не взаимодействовал с этой командой
		$mode = "name"; // поэтому задаем ему действие по дефолту
	}else{
		$mode = $data["mode"];
	}
	
	if($mtext == "/dbact"){
		// по команде /dbact запускаем цепочку
		if($mode == "name"){
			$bot->sendMessage($message->getChat()->getId(), "Добрый день, укажите, пожалуйста, ваше имя");
			$data["mode"] = "aftername";
			set_udata($message->getFrom()->getUsername(), $data); // сохраняем изменения
		}
		
	}
	if($mode == "aftername"){
		// помещаем имя в массив данных
		$data["name"] = $message->getText(); // очевидно, что после запроса имени пользователь отправит следюущей командой свое имя, то есть оно будет в тексте сообщения.
		$bot->sendMessage($message->getChat()->getId(), "Добрый день, укажите ваш сайт");
		$data["mode"] = "website";
		set_udata($message->getFrom()->getUsername(), $data); // сохраняем изменения
	}
	if($mode == "website"){
		$data["website"] = $message->getText(); // очевидно, что после запроса сайта пользователь отправит следюущей командой свой сайт, то есть адрес будет в тексте сообщения.
		$bot->sendMessage($message->getChat()->getId(), "спасибо.");
		$data["mode"] = "done";
		set_udata($message->getFrom()->getUsername(), $data); // сохраняем изменения
	}
	
	if($mode == "done"){
		// если человек уже прошел опрос - выводим ему собранную у него-же информацию
		$bot->sendMessage($message->getChat()->getId(), "Вы уже проходили опрос и указали такие данные:\nИмя - ".$data["name"]."\nсайт - ".$data["website"]);
	}
	
}, function($message) use ($name){
	return true; // когда тут true - команда проходит
});

При вызове команды /dbact мы сможем пройти такой вот диалог:

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

Скачать готовый пример

Как обычно вы можете скачать готовый пример бота с этим функционалом

демо php telegram бота с базой данных
Скачано: 288, размер: 597.2 KB, дата: 14.Фев.2018
 17 комментариев
Страница 1 из 1
    seoonly.ru

    хорошая вещь!

    ◇◇◇◇☆ ◆◆◆◆★

    Топ топ топ еще раз топ спасибо огромное!,

    ◇◇◇◇☆ ◆◆◆◆★

    А как сделать чтоб Инфу с бд выводил только по команде а не по каждому сообщению!

    Влад

    Спасибо за подробный урок и наглядный пример.

    ◇◇◇◇☆ ◆◆◆◆★

    Добовлю к командам вот так:
    $bot->command(‘help’, function ($message) use ($bot) {
    $bot->sendMessage($message->getChat()->getId(), «Вы уже проходили опрос и указали такие данные:\nИмя — «.$data[«name»].»\nсайт — «.$data[«website»]);

    });

    У меня выводит по cmd все без значений

    harry

    Очень жаль, что такие посты не находят отклика у читателей. Зато в ридерах одно унылое говно из «финстрипов, «отчетов» и рекламы курсов. Полезных материалов вообще нет.

    Вероника

    Добрый день! Наверно мой вопрос покажется глупым, ведь вроде всё дано, но всё равно туплю.. Как сделать, чтобы после сообщения бота «Введите пароль» и после ввода пользователем пароля в строку ввода телеграм, бот заносил эту инфу в базу в конкретный столбец?

    Вероника

    Спасибо за ответ) Правда код не работает, ну да ладно)

    Марина

    Слезно умоляю…. помогите реализовать сборку иерархии инлайн кнопок через базу данных, что бы мини конструктор кнопок получить 🙁

    Марина

    Мб неверно выразилась… 🙁

    Задача, сделать мини конструктор в браузере. То есть со страницы, можно собрать кнопки списоком с навигацией например Кнопки 1 -> Кнопки 2 -> запись
    То есть все как то должно лежать в БД, а c php страницы в браузере взаимодействовать

Добавить Комментарий