Доступ из бота к музыке VK

Новиков М.Г.
29.03.2016

К сожалению, начиная с 16 декабря 2016 года публичный API для работы с аудиозаписями закрыт.

Подробности тут: https://vk.com/dev/audio_api.

Данная статья осталась для истории

 

В связи с войной правообладателей против пиратов, музыки в свободном доступе практически не осталось. Даже социальная сеть «ВКонтакте», видимо под давлением Роскомнадзора, сильно усложнила доступ через свой API к содержащейся внутри сети музыки. По крайней мере, у меня не получилось получить доступ к музыкальным произведениям без нескольких ступеней авторизации, которые я опишу ниже.

Итак, давайте сделаем бота, который бы выдавал первые десять ссылок на композиции, скажем, Pink Floyd. Наш бот будет чисто демонстрационным, поэтому мы не будем оснащать его каким бы то ни было дополнительным функционалом. Будет продемонстрирован лишь способ подключения. Подразумевается, что вы уже умеете писать боты, заготовка кода бота у вас уже сделана, подключена к самому боту через WebHook, и маркер доступа у вас сохранён.

Создание приложения в VK

Для доступа к музыке нужен будет ваш аккаунт во «ВКонтакте». Для начала создадим внутри аккаунта собственное приложение, которое будет мостиком между ботом и музыкальными ресурсами:

  1. Входим в «Приложения → Управление → Создать приложение».
  2. В верхнее поле вводим любое название, выбраем «Standalone-приложение» и нажимаем кнопку «Подключить приложение».
  3. На запрос сайта отправим код на свой мобильный телефон и введём его в предложенное поле подтверждения.
  4. Перейдём в настройки и скопируем себе содержимое полей «ID приложения» и «Защищенный ключ».

Всё, внутри аккаунта больше ничего не трогаем. Мостик мы сделали.

Создание кода бота

Теперь переходим к коду бота. Будем писать на PHP. Нам потребуется небольшой вспомогательный класс. Скачаем его с GitHub. Разместим скаченную папку VK в корне сайта рядом с основным файлом кода бота.

Откроем файл кода бота и начинаем с подключения скаченных классов. В итоге ваш код должен начинаться так:

<meta charset="utf-8">
<?php
error_reporting(E_ALL);
require_once('VK/VK.php');
require_once('VK/VKException.php');

Выполнение кода начнём с получения команды, введённой боту, и вызова процедуры, которая будет обрабатывать эту команду:

$content = file_get_contents("php://input"); // Получим то, что передано скрипту ботом
$update = json_decode($content, true);       // и распарсим.
if (!$update) { exit; } // Если полученные данные не могут быть декодированы, выйдем сразу.
// Если среди пришедших данных есть сообщение, вызовем функцию обработки
if (isset($update["message"])) {
  processMessage($update["message"]);
}

Надеюсь, определения маркера бота, выданный вам во время WebHook'а и URL для обращений к API бота у вас уже прописаны:

define('BOT_TOKEN', '111111111:AAAAAaa1aa1a1aaa1AaAAAAAAaaAAaAAaaA'); // Маркер бота
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');      // URL к Bot API

Пока всё, как обычно. Функция обработки введённых пользователем команд стандартна:

function processMessage($message) {
// разборка пришедшего сообщения
$message_id = $message['message_id']; // Идентификатор сообщения
$chat_id = $message['chat']['id']; // Идентификатор чата
// Если есть текст сообщения
if (isset($message['text'])) {
  // В зависимости от команды выполняем те или иные действия
  switch($text) {
    case ('/m1'):
      get_VK_ACCESS_CODE($chat_id);
      break;
    case ('/m2'):
      function get_VK_ACCESS_TOKEN($chat_id);
      break;
    case ('/m3'):
      get_m($chat_id);
      break;
    default:
      file_get_contents(API_URL."sendmessage?chat_id=".$chat_id."&text=".'Неизвестная команда');
      break;
    }
  } else {
    file_get_contents(API_URL."sendmessage?chat_id=".$chat_id."&text=".'Спасибо, но я понимаю только текстовые команды!';
  }
}

В функции обработки мы предусмотрели три команды (/m1, /m2 и /m3), две первых из которых нам понадобятся для получения кодов доступа к нашему приложению во «ВКонтакте». После получения кодов доступа можно будет их удалить.

Итак, вначале нам понадобится код доступа к приложению. Для его получения пишем первую функцию для команды /m1:

define('APP_ID', '1111111');                  // ID приложения
define('API_SECRET', '11aAAaa1lAAA1A1aAAAA'); // Защищённый ключ

function get_VK_ACCESS_CODE($chat_id) {
  // Создаём объект VK:
  $vk = new VK\VK(APP_ID, API_SECRET);
  // Получить код авторизации
  try {
    $authorize_url = $vk->getAuthorizeURL('offline, audio');
  } catch (VK\VKException $error) {
    file_get_contents(API_URL."sendmessage?chat_id=".$chat_id."&text=".'Ошибка: '.$error->getMessage());
  }
  // Ввести $authorize_url в браузер и получить код из параметра code вернувшейся браузерной строки
  file_get_contents(API_URL."sendmessage?chat_id=".$chat_id."&text=".'Перейдите по URL для получения кода авторизации: '.$authorize_url);
}

В определения define забиваем наши данные, полученные после создания приложения.

Вторая функция для команды /m2, нужна для получения маркера доступа к приложению. Она будет выглядеть так:

define('VK_ACCESS_CODE', 'aa111111a111a11111'); // Код доступа из параметра code вернувшейся браузерной строки

function get_VK_ACCESS_TOKEN($chat_id) {
  // Создаём объект VK:
  $vk = new VK\VK(APP_ID, API_SECRET);
  // Получить маркер доступа
  try {
    $access_token = $vk->getAccessToken(VK_ACCESS_CODE);
  } catch (VK\VKException $error) {
  file_get_contents(API_URL."sendmessage?chat_id=".$chat_id."&text=".'Ошибка: '.$error->getMessage());
  }
  // Вывести его в бот
  file_get_contents(API_URL."sendmessage?chat_id=".$chat_id."&text=".'Маркер доступа: '.$access_token['access_token']);
}

Определение VK_ACCESS_CODE пока не задаём.

Третья функция для команды /m3, будет искать и выдавать нам список найденных композиций:

define('VK_ACCESS_TOKEN', 'aa111aa11111a1a11aaa11aa11aa11aa1a1aa1111111a111aa11aa1aa1aa111aaa1a11aa111111a111111'); // Маркер доступа

function get_m($chat_id) {
  $vk = new VK\VK(APP_ID, API_SECRET, VK_ACCESS_TOKEN);
  $resp = $vk->api('audio.search', array(
    'q' => 'Pink Floyd',    // сам запрос
    'auto_complete' => '1', // автоисправление ("Еру Иуфедуы" → The Beatles)
    'sort' => '2',          // сортировка - по популярности
    'count' => '10',        // количество результатов в ответе
    'offset' => '0',        // смещение для постраничного отображения
    'lang' => 'ru',         // результат выдать по возможности по русски
    'v' => '5.50'           // Использовать свежую версию API
  ));
  $count = $resp['response']['count'];
  foreach ($resp['response']['items'] as $value) {
    $title = encod($value['title']);
    $url = encod($value['url']);
    $artist = encod($value['artist']);
    file_get_contents(API_URL."sendmessage?chat_id=".$chat_id."&text=".'Найдено: '.$count.' шт.: '.$artist.' - '.$title.' - '.$url);
  }
}

Определение VK_ACCESS_TOKEN пока тоже не вписываем — оно нам ещё неизвестно.

Получение кодов доступа

Закачиваем код бота на сервер, открываем бот в мессенджере, и вводим ему команду /m1. В ответ бот выдаёт нам ссылку. Нажимаем на неё. Открывается браузер. Находим в строке адреса код авторизации (параметр code), и не мешкая вставляем его в определение VK_ACCESS_CODE.

Срок действия этого кода ограничен по времени, поэтому быстро сохраняем изменения и закачиваем обновлённый код бота на сервер. Затем переходим к боту, и вводим команду /m2. В ответ бот выдаёт нам маркер доступа. Теперь уже можем не торопиться, маркер доступа действует без ограничений. Вставляем маркер в определение VK_ACCESS_TOKEN.

Закачиваем обновлённый код на сервер, переходим к боту, и вводим команду /m3. Если ошибок в коде мы не допустили, бот вернёт нам первые 10 композиций Pink Floyd. Теперь можем убрать лишние команды, функции и потерявшее актуальность определение VK_ACCESS_CODE.

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

Сообщите мне, если в коде обнаружите ошибку! Также буду рад любым советам.