Пишем 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);
}
});
Всем Спасибо, подписывайтесь, делайте репосты, ставьте голос!