Пишем Telegram бота на JavaScript. Часть 4. Работа с API VK


 Первый пост: Пишем Telegram бота на JavaScript. Вводная  

 Второй пост:  Пишем Telegram бота на JavaScript. Часть 2. Курс биткоина 

 Третий пост: Пишем Telegram бота на JavaScript. Часть 3. Рефакторинг и логирование

В данном уроке я хотел бы показать как работает связка телеграм бота с api VK.com. Сегодня попробуем вытащить случайные фотографии по определённым запросам.

Заготовка

Для начала давайте возьмём нашу заготовку основанную на предыдущих постах, предварительно установив пакет: npm i vksdk -D

var TelegramBot = require('node-telegram-bot-api');
var request = require('request');
var VK = require('vksdk');
var fs = require('fs');
 
var opts = {
  reply_markup: JSON.stringify({
    keyboard: [
      []
    ],
    resize_keyboard: true
  })
};
 
var APPCONFIG = {
  token: '271342174:AAFY4-V7TY7Ux5V7liK_TpdmFM7W87TzTuM',
  botConfig: {
    polling: true
  }
};
var bot = new TelegramBot(APPCONFIG.token, APPCONFIG.botConfig);
bot.on('text', function(msg) {
var messageChatId = msg.chat.id;
var messageText = msg.text;
 
  switch (messageText) {
    case '/start':
      bot.sendMessage(messageChatId, 'Добро пожаловать, ну hello world', opts);
      break;
    default:
      bot.sendMessage(messageChatId, 'Я внимательно слушаю', opts);
  }
});

Теперь нам нужно создать приложение в VK, для этого идём на страницу создания и вбиваем название, выбор Standalone,  в настройках получим ID и ключ. Запишем эти настройки в создании экземпляра объекта VK: 

var vk = new VK({
  'appId' : 6072631,
  'appSecret' : 'LUPf8c6xoUVTiQtzmL82',
  'language' : 'ru'
});

Давайте поменяем клавиатуру:

 var opts = {
  reply_markup: JSON.stringify({
    keyboard: [
      ['? Прислать открытку из Петербурга']
    ],
    resize_keyboard: true
  })
};

Реализация выборки через API

Следующим шагом нам нужно записать важную системную функцию, в которой мы сделаем запрос к апи, в котором выберем все фотографии по коорбинатам и слову "Петербург", ограничим вывод до 900 штук и в радиусе от точки до 6 километров, при успешном запросе запустим колбек, иначе вытащим ошибку и выйдем в меню:

function getVKGeoPhotos(messageChatId, opts, callback) {
  vk.request('photos.search', {
      'q' : 'Петербург',
      'lat' : '59.9343533',
      'long': '30.3353828',
      'sort': 0,
      'count': 900,
      'radius': 6000,
      'version':'5.50'
    },
    function (_o) {
      if(_o.response.items.length > 1) {
        callback(_o.response.items);
      }else{
        bot.sendMessage(messageChatId, "Упс, ничего не найдено", opts);
      }
    }
  );
};

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

function randd(items_count, vkResponse){
  var randomId = getRandomInt(0, items_count-1);
  var photoCaption = vkResponse[randomId].text;
 
  if(photoCaption != ''){
    if(photoCaption.match(/работа|cm|tfp|лет|см|полумарафон|модель|медаль|марафон|диплом|конкурс|мужское|жеснкое|обмен|меняю|обменяю|заказы|рост|цена|пересыл|ремонт|личку|куплю|макияж|рублей|руб|размер|услуги|тонировка|туфли|джинсы|штаны|футболка|продаю|продам|покупка|звоните|сдам|сниму/gi)) {
      return randd(items_count, vkResponse);
    }else{
      return [photoCaption, randomId];
    }
  }else{
    return [photoCaption, randomId];
  }
};

Здесь нам понадобится еще одна вспомогательная, генератор случайного числа:

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
};

В секции отработки меню запишем новый обработчик: case  '? Прислать открытку из Петербурга':
В нём и вызовем getVKGeoPhotos:

getVKGeoPhotos(messageChatId, opts, function(vkResponse) {
        var items_count = vkResponse.length;
        var responseArr = randd(items_count, vkResponse);
        var img;
        if("photo_604" in vkResponse[responseArr[1]]) {
          img = request(vkResponse[responseArr[1]].photo_604);
        } else if ("photo_807" in vkResponse[responseArr[1]]) {
          img = request(vkResponse[responseArr[1]].photo_807);
        } else if ("photo_130" in vkResponse[responseArr[1]]){
          img = request(vkResponse[responseArr[1]].photo_130);
        } else {
          bot.sendMessage(messageChatId, "Упс, не найдено подходящего размера", opts);
        }
 
        if(vkResponse[responseArr[1]].text.length < 190) {
          opts.caption = vkResponse[responseArr[1]].text + '\r\n/live';
        }else{
          opts.caption = 'Отлично! Давай еще загрузим!\r\n/live';
        }
 
        bot.sendPhoto(messageChatId, img, opts);
      });

Здесь мы делаем запрос и отправляем ответ в наш фильтр randd, получив  ответ выберем фото, оптимальная 604, но в массиве не всегда есть такой вариант размера, пришлось подстроиться под остальные. Описание тоже иной раз интересно почитать, так что и его запишем и отошлём в сообщении. 

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

var TelegramBot = require('node-telegram-bot-api');
var request = require('request');
var VK = require('vksdk');
var fs = require('fs');
 
var opts = {
  reply_markup: JSON.stringify({
    keyboard: [
      ['? Прислать открытку из Петербурга']
    ],
    resize_keyboard: true
  })
};
var APPCONFIG = {
  token: '271342174:AAFY4-V7TY7Ux5V7liK_TpdmFM7W87TzTuM',
  botConfig: {
    polling: true
  }
};
var bot = new TelegramBot(APPCONFIG.token, APPCONFIG.botConfig);
var vk = new VK({
  'appId' : 5352252,
  'appSecret' : 'Ub6ERVfRIzd8OMSx12to',
  'language' : 'ru'
});
 
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
};
function getVKGeoPhotos(messageChatId, opts, callback) {
  vk.request('photos.search', {
      'q' : 'Петербург',
      'lat' : '59.9343533',
      'long': '30.3353828',
      'sort': 0,
      'count': 900,
      'radius': 6000,
      'version':'5.50'
    },
    function (_o) {
      if(_o.response.items.length > 1) {
        callback(_o.response.items);
      }else{
        bot.sendMessage(messageChatId, "Упс, ничего не найдено", opts);
      }
    }
  );
};
function randd(items_count, vkResponse){
  var randomId = getRandomInt(0, items_count-1);
  var photoCaption = vkResponse[randomId].text;
 
  if(photoCaption != ''){
    if(photoCaption.match(/работа|cm|tfp|лет|см|полумарафон|модель|медаль|марафон|диплом|конкурс|мужское|жеснкое|обмен|меняю|обменяю|заказы|рост|цена|пересыл|ремонт|личку|куплю|макияж|рублей|руб|размер|услуги|тонировка|туфли|джинсы|штаны|футболка|продаю|продам|покупка|звоните|сдам|сниму/gi)) {
      return randd(items_count, vkResponse);
    }else{
      return [photoCaption, randomId];
    }
  }else{
    return [photoCaption, randomId];
  }
};
 
bot.on('text', function(msg) {
var messageChatId = msg.chat.id;
var messageText = msg.text;
 
  switch (messageText) {
    case '/start':
      bot.sendMessage(messageChatId, 'Добро пожаловать, ну hello world', opts);
      break;
    case '? Прислать открытку из Петербурга':
      getVKGeoPhotos(messageChatId, opts, function(vkResponse) {
        var items_count = vkResponse.length;
        var responseArr = randd(items_count, vkResponse);
        var img;
        if("photo_604" in vkResponse[responseArr[1]]) {
          img = request(vkResponse[responseArr[1]].photo_604);
        } else if ("photo_807" in vkResponse[responseArr[1]]) {
          img = request(vkResponse[responseArr[1]].photo_807);
        } else if ("photo_130" in vkResponse[responseArr[1]]){
          img = request(vkResponse[responseArr[1]].photo_130);
        } else {
          bot.sendMessage(messageChatId, "Упс, не найдено подходящего размера", opts);
          logging("logs/ResponsePhotoVkLog.log", vkResponse);
        }
 
        if(vkResponse[responseArr[1]].text.length < 190) {
          opts.caption = vkResponse[responseArr[1]].text + '\r\n/live';
        }else{
          opts.caption = 'Отлично! Давай еще загрузим!\r\n/live';
        }
 
        bot.sendPhoto(messageChatId, img, opts);
      });
      break;
    default:
      bot.sendMessage(messageChatId, 'Я внимательно слушаю', opts);
  }
});
 

Всем Спасибо, подписывайтесь, делайте репосты, ставьте голос!


Comments 1