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

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

Затем мы заходим в настройки сообщества и выбираем пункт «API usage» и нажимаем на кнопку «Create token».

image

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

image

И вот мы получили заветный токен. Его, кстати, нужно сохранить в надёжное место и никому не показывать. Теперь можно приступать к коду.

image

Мы будем писать код на языке PHP, поэтому можно скачать Visual Studio code или PHPStorm. В принципе, код можно писать и в блокноте, только это будет не удобно. После кода мы перейдём к дальнейшей настройке группы.

Итак, для начала нам нужно получить информацию о входящем сообщении и перевести её из формата JSON в понятный для PHP.

<?php
$data = json_decode(file_get_contents('php://input'));
?>

В переменной data теперь к нас находится массив с сообщением, ID пользователя и ID чата.
«А что за „json_decode(file_get_contents('php://input'))“, — спросите вы.

Начнём с этого момента:

file_get_contents('php://input')

Выражаясь, простым языком, мы спрашиваем у скрипта что у нас пришло на вход, то есть какой запрос отправил ВК. Ниже приведу пример такого запроса.

{"type":"message_new","object":{"date":1568464037,"from_id":450829055,"id":5400,"out":0,"peer_id":450829055,"text":"Тестовое сообщение.","conversation_message_id":1478,"fwd_messages":[],"important":false,"random_id":0,"attachments":[],"is_hidden":false},"group_id":171524656}

Думаю, легко понять что написано в запросе, если иметь минимальные знания в английском языке.

Ну а „json_decode()“ — функция, которая переводит вышеприведённый JSON в массив, с которым может работать PHP.

Теперь напишем код, который смотрит какое событие произошло, и если к нам пришло новое сообщение, то сравнивает сообщение, с теми, на которые у нас есть ответ и смотрит ID чата.

<?php
$data = json_decode(file_get_contents('php://input'));
switch ($data->type) {  
	case 'confirmation': 
		echo $confirmation_token; 
	break;  
		
	case 'message_new': 
		$message_text = $data -> object -> text;
		$message_text = $data -> object -> peer_id;
		if ($message_text == "привет"){
			// что-то происходит
		}
		if ($message_text == "пока"){
			// что-то происходит
		}
		echo 'ok';
	break;
}
?>

Теперь нам нужно как-то отвечать на эти сообщения. Для этого напишем простую функцию.

<?php
function vk_msg_send($peer_id,$text){
	$request_params = array(
		'message' => $text, 
		'peer_id' => $peer_id, 
		'access_token' => "TOKEN",
		'v' => '5.87' 
	);
	$get_params = http_build_query($request_params); 
	file_get_contents('https://api.vk.com/method/messages.send?'. $get_params);
}
?>

Что же тут происходит? Здесь мы строим запрос к API VK (документацию рекомендую почитать) с текстом сообщения, ID чата и токеном, который мы создали ранее, и отправляем его на сервер ВК.

Теперь соединим эти куски кода и напишем реакции бота на то или иное сообщение.

<?php
$confirmation_token = 'CONF_TOKEN'
function vk_msg_send($peer_id,$text){
	$request_params = array(
		'message' => $text, 
		'peer_id' => $peer_id, 
		'access_token' => "TOKEN",
		'v' => '5.87' 
	);
	$get_params = http_build_query($request_params); 
	file_get_contents('https://api.vk.com/method/messages.send?'. $get_params);
}
$data = json_decode(file_get_contents('php://input'));
switch ($data->type) {  
	case 'confirmation': 
		echo $confirmation_token; 
	break;  
		
	case 'message_new': 
		$message_text = $data -> object -> text;
		$chat_id = $data -> object -> peer_id;
		if ($message_text == "привет"){
			vk_msg_send($chat_id, "Привет, я бот, который говорит две фразы.");
		}
		if ($message_text == "пока"){
			vk_msg_send($chat_id, "Пока. Если захочешь с кем-то поговорить, то у тебя есть бот, который говорит две фразы.");
		}
		echo 'ok';
	break;
}
?>

«Хорошо, а зачем нам писать 'ok' после отправки сообщения?»

Так как мы будем использовать метод получения обновлений с названием Call Back API, то есть сам ВКонтакте нам будет говорить о новых сообщениях, то нам нужно сказать, что мы его услышали, иначе он будет нам повторять несколько раз.

Теперь перейдём к настройке группы.

Заходим в настройки и выбираем версию API 5.87 (можно, конечно, и более новые версии, но лучше иметь единство версий API).

image

Из этого же раздела берём строку, которую должен вернуть сервер, и подставляем её в переменную confirmation_token.

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

Потом выбираем о каких событиях в сообществе нам будет сообщать ВКонтакте. Нам нужны только входящие сообщения.

image

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

image

Так как это моя первая публикация на Хабре, я хочу получить замечания по статье и дальше только совершенствоваться.

Спасибо за прочтение.

Комментарии (11)


  1. HappyGroundhog
    23.09.2019 17:53

    У вас в чат-боте отсутствует какая-либо обработка ошибок, так что при первой же ошибке бот будет вести себя очень непредсказуемо)
    Upd. А версию API все же лучше выбирать из требуемого функционала и согласно описанию изменения версий, а то можно поймать очень необычное поведение, когда ВК в очередной раз, например, поломают клавиатуру для ботов.


    1. y_durov Автор
      23.09.2019 18:59

      -> Я написал пост для того, чтобы те люди, которые только начинают смогли понять, как всё это вообще работает. А так полностью согласен с вами.
      -> Имхо, 5.87 достаточно новая версия, но и не очень замороченная, как 5.101, к примеру, где в методе messages.send нужно ещё генерировать random_id


      1. HappyGroundhog
        23.09.2019 19:38

        А что сложного в генерации random_id? Все же контакт достаточно жестко отпиливает старый функционал и лучше новые вещи базировать на новом)
        Что касается «понятно новичкам» то это плохой паттерн… Новички просто всё скопипастят в «продакшн» и потом будут долго жаловаться на то, что у них это не работает. Очень не хватает предупреждения в конце не использовать это в продакшене)
        Статья как чуть более разжеванная документация хорошая, хотя, например, на домашней машинке с динамическим IP гораздо интереснее использовать LongPoll. И тестить проще в разы. Но там есть пара своих нюансов, хотя мой бот уже несколько месяцев оберегает наше сообщество от мошенников на LongPoll.
        Кстати, если не разбирать json руками, а использовать официальные SDK от VK, то жизнь заиграет новыми красками!


        1. y_durov Автор
          23.09.2019 20:05

          С этим полностью согласен, но перед применением SDK нужно понять как всё это работает. Да, SDK эффективнее, но, когда это является чёрным ящиком, не имеет смысла что либо делать без понятия азов.
          Да, я сам когда-то начинал с копипаста, но потом меня выбесило, что я ничего не понимаю и начал курить мануалы в огромных колличествах.
          И, думаю, что достаточно негативно скажется на карме, что начал публиковаться на хабре с PHP, а не с Python, да и вообще затронул тему ботов.


  1. tempick
    23.09.2019 18:01

    Но ведь это всё есть в официальной документации Вконтакте даже с примерами кода на PHP.


    1. y_durov Автор
      23.09.2019 19:22

      Да, конечно, есть. Однако, есть одно «но». В документации никто не переводит на язык, понятный новичкам и заваливают терминами. Я же старался провести некую ассоциацию с реальной жизнью, чтобы наглядно показать, что в программировании можно понять всё. К тому же, моя цель — заинтересовать людей и дать некий импульс к дальнейшему саморазвитию.


  1. tempick
    23.09.2019 18:09

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


    1. y_durov Автор
      23.09.2019 19:00

      Да, мой косяк. Постарался охватить больше техники, а формальность самую банальную забыл.


  1. sudden_death
    23.09.2019 22:17
    +1

    Пример с данными в JSON лучше писать в нормализованном виде, т.е. с табуляцией, так будет понятнее. Найти где нормализовать сможете, вбив в гугл json viewer и просмотрев первые ссылки.

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


  1. MHunterG
    24.09.2019 21:05

    Простите конечно, но статей «как сделать бота для вк» очень уж много, документация в самом вк очень понятная, а запросы к вк API не отличаются сложностью. Ведь это просто запросы. Единственная проблема которая может возникнуть с API вк (если ты хоть чуть чуть понимаешь как делать HTTP/HTTPS запросы на своем языке, а ведь тут PHP, а ни какой-нибудь C) это проблема составления этих самых вопросов, но в документации и многочисленных статьях все прекрасно объясняется. Зачем делать скриншоты на английском, а писать комментарии к коду на русском (сменить язык в вк очень легко)? Зачем показывать код, а за объяснениями отправлять к документации (причем в проблемном месте составления запросов)? Я честно не понимаю как эта статья вышла из песочницы.


    1. y_durov Автор
      24.09.2019 21:07

      Приму к сведению, и в дальнейшем буду расписывать проблематичные места подробнее.