Як я отримав прихованих друзів від теорії до практики

Добрий день, хабравчане! У цьому пості я постараюся вам розповісти як я отримав список прихованих друзів у знайомої вконтакте.

Зміст

  • I. Трохи теорії
  • II. Практика і реалізація на javascript
  • Висновок


I. Трохи теорії

Думаю ви всі чули про функції приховування друзів (Рис. 1.1). Прихованих друзів можна переглянути іншим користувачам, для яких користувач, приховував друзів, обмежив доступ до його прихованим друзям.

image
Рисунок 1.1 — Приховані друзі

Не один клієнтський метод API вконтакте не повертає список прихованих друзів у користувача, але повертає список друзів. Якщо припустити, що у цієї людини по мимо прихованих друзів, так само є і не приховані, то ми можемо запросити список його друзів. Після цього у кожного одного користувача запросити друзів (Маємо: ід користувача, масив його друзів, масив друзів). Припустимо в друзях у друзів повинен бути наш користувач, хоча б у одного. Тоді ми запитаємо у кожного друга список друзів і перевіримо наявність у друзів нашого користувача, якщо він є в друзях, значить у нашого користувача в друзях теж є він (Рис. 1.2). Після того як ми знайшли всіх друзів нашого користувача ми повинні бінарну різниця множин (Рис. 1.3), безлічі повернутого друзів з VK API і знайденого через друзів.

image
Рисунок 1.2 — Алгоритм пошуку прихованих друзів

image
Рисунок 1.3 — Бінарна різниця множин

II. Практика і реалізація на javascript

На практиці не все так просто! Щоб пройтися по всім друзям користувача піде дуже багато часу, тим більш що API VK нас обмежив до 3 запитів в секунду. Я вирішив не проходиться по всім друзям, а тільки по одному якого виберу сам.

Для початку поставимо розмітку HTML (Наприклад у файл index.html):
<html lang="ru">
<head>
<script src="http://vkontakte.ua/js/api/openapi.js" type="text/javascript"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</head>
<body>
<div id="info"></div>
<div id="result"></div>
<script src="js/hiddenfriends.js" type="text/javascript"></script>
</body>
</html>


Наступним етапом створимо файл hiddenfriends.js і кинемо в папку js.
Пройдемо ініціалізацію:
// Сюди вкажемо ID своїх додатків створених з підтримкою OpenApi VK
var id_app= [2866099, 4195289, 4195287, 4195284, 4161477, 4161462, 4149350, 4149349, 4149336, 2394133, 3043953];
var apiID_index = Math.floor(Math.random() * (id_app.length));
VK.init({
apiId: id_app[apiID_index]
});

var user_id_global = 0;
var user_friends = [];

// Додаємо користувача і одержуємо інформацію про нього і його друзів
addUser(250185983);

// Масив ID користувачів яких ми обрали (Вони повинні бути хоч якось пов'язані з нашим користувачем)
var id = [22429423];


Додамо функцію додавання користувача та запуску роботи:
function addUser(user_id)
{
VK.Api.call('users.get', {user_ids: user_id, fields: 'photo_50', v: '5.27'}, function® {
if(r.response) {
$('#info').html('<img src="" alt="" class="img-responsive"/>' + r.response[0].first_name + '' + r.response[0].last_name + '<br/>');
VK.Api.call('friends.get', {user_id: user_id, v: '3.0', order: 'random'}, function® {
if(r.response) {
// Отримуємо список друзів рекурсією
get_friends_friends(r.response, 0, user_id);
$('#info').append('<br/>Друзів: ' + r.response.length);
}
});
}
});
}


Додамо функцію отримання друзів:
// index - індекс поточного користувача, items - масив друзів нашого користувача
function get_friends_friends(items, index, user_id) {
if (index < id.length) {
VK.Api.call('friends.get', {user_id: id[index], v: '3.0'}, function® {
if(r.response) {
// Отримуємо список друзів друзів друзів і шукаємо там нашого користувача
get_friends_friends_friends(r.response, items, user_id, 0, index);
} else get_friends_friends(items, index + 1, user_id);
});
} else {
// Різниця масивів - приховані друзі
var hidden = diff_array(user_friends, items);
if (hidden.length > 0) {
$('#result').append('<br/><br/>Приховані друзі: ' + hidden.join());
$('#result').append('<br/><br/>Прихованих друзів: ' + hidden.length);
} else {
$('#result').append('Прихованих друзів не знайдено!');
}
}
}


// friend_items - список друзів друзів, items - список друзів, index_top - поточний друг, index - один одного
function get_friends_friends_friends(friend_items, items, user_id, index, index_top) {
$('#result').html(index + ' з ' + friend_items.length + '<br/>');
if (friend_items.length > index) {
if (user_friends.join().indexOf(friend_items[index]) == -1) {
VK.Api.call('friends.get', {user_id: friend_items[index], v: '3.0'}, function® {
if(r.response) {
if (r.response.join().indexOf(user_id) > -1) {
user_friends[user_friends.length] = friend_items[index];
if (items.join().indexOf(friend_items[index]) == -1) 
$('#info').append('<br/><br/>Знайдено прихований один: ' + friend_items[index]);
}
// Отримуємо список друзів друзів друзів і шукаємо там нашого користувача
setTimeout(function() { 
get_friends_friends_friends(friend_items, items, user_id, index + 1, index_top);
}, 400);
} else get_friends_friends_friends(friend_items, items, user_id, index + 1, index_top);
});
}
} else {
// Перехід до наступного користувача
get_friends_friends(items, index_top + 1, user_id);
}
}


Так само додамо функцію бінарної різниці масивів:
function diff_array(array_1, array_2)
{
var count = 0, result = [];
for (var i = 0; i < array_1.length; i++)
{
var j = 0, k = 0;
while (array_2[j] !== array_1[ i ] && j < array_2.length) 
j++;
while (result[k] !== array_1[ i ] && k < count) 
k++;
if (j == array_2.length && k == count) 
result[count++] = array_1[ i ];
}
return result;
}


Результат:

Висновок

У висновку хотілося б сказати що в практичній версії код влаштований так що легко змінити на те щоб пробігати по всім друзям, але дивіться самі я чекав 6 годин, щоб переглянути своїх прихованих друзів (приховував для тіста 30 друзів з 313). Тут можна подивитися приклад.

js/hiddenfriends.js

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.