NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Слежка за своими ботами в ВКонтакте
// @namespace http://tampermonkey.net/
// @version 0.5
// @description Добавляет в меню группы ботов + при нажании на F2 в чате показывает какими ботами пользовался пользователь
// @author Flyink13
// @match https://vk.com/*
// @grant none
// ==/UserScript==
(function() {
var autoupdate = []; // Автообновление счетчиков
setInterval(autoupdate.map(x => x()), 10000);
// Стили для аватарок
document.head.appendChild(document.createElement("style")).innerHTML = `
.l_comm .left_icon{
width: 24px !important;
margin: 2px 8px 2px 3px !important;
border-radius: 100% !important;
height: 24px !important;
}
`;
function addGroups(gids) { // Функция добавления групп в меню
// Ищем группу в меню для копирования
var groups = document.getElementsByClassName("l_comm");
if (!groups.length) return;
var last_group = groups[groups.length - 1];
// Ищем сепаратор для разделения меню
var insert_before = document.getElementsByClassName("more_div");
if (!insert_before.length) return;
insert_before = insert_before[insert_before.length - 1];
var insert_after = insert_before.parentNode.insertBefore(insert_before.cloneNode(true), insert_before.nextSibling.nextSibling);
// Вставляем группы
gids.filter(x => /бот|bot/i.test(x.name) && x.is_closed < 2).map(function(g) {
var new_group = last_group.cloneNode(true); // Клонируем группу для копирования
new_group = last_group.parentNode.insertBefore(new_group, insert_after.nextSibling); // Вставляем в меню
var counter = new_group.querySelector(".left_count_wrap > span"); // Счетчик
var name = new_group.querySelector(".left_label"); // Имя
var left_icon = new_group.querySelector(".left_icon"); // Иконка
new_group.firstChild.href = "/" + g.screen_name; // Изменяем ссылку на группу
counter.parentNode.href = counter.href = "/gim" + g.id; // Изменяем ссылку на личку группы в счетчике
counter.parentElement.removeAttribute("onclick"); // Удаляем onclick
counter.parentElement.onclick = () => 0;
counter.onclick = onClickCounter.bind(this, g.id); // Добавляем фичи при клике на счетчик
counter.parentNode.classList.remove("left_void"); // Делаем видимость счетчика
counter.parentNode.style.opacity = "0.5"; // и прозрачность
counter.textContent = "L"; // Ставим статус Loading в счетчик
counter.classList.remove("left_count_sign"); // Убираем "+"
counter.onmouseenter = // Обновление счетчика при наведении мышки
getInfo.bind(this, g.screen_name, function (m) {
counter.parentNode.style.opacity = m ? "1" : "0.2";
counter.textContent = m;
});
autoupdate.push(counter.onmouseenter); // Добавляем в Автообновление счетчиков
counter.onmouseenter(); // Обновляем
// Ставим имя группы
name.textContent = g.name;
// Ставим аватарку вместо иконки
left_icon.style.background = "url(" + g.photo_100 + ") no-repeat center/contain";
});
}
function onClickCounter(start, event) {
var id = prompt("id", location.search); // Спрашиваем куда переходить
if(id === null) return nav.link("gim" + start, event); // Если не сказали, то в список диалогов
nav.link("gim" + start + id, event); // Открываем если сказали куда
cancelEvent(event);
return false;
}
function getInfo(gid, cb, ignore_cart) {
if(!ignore_cart) return getInfo.cart.push([gid, cb, 1]); // Добавляем в очередь запросов
if(parseInt(localStorage["gid" + gid]) > Date.now()) // Если открыто в другой вкладке, и запрос был менее 10 секунд назад
return cb(localStorage["gid" + gid].split(":")[1] * 1); // то отдаем то что было
var xhr = new XMLHttpRequest();
xhr.open("GET", "/al_profile.php?al=-1&__query=" + gid, true); // Открываем группу
xhr.onload = function() {
xhr = xhr.responseText;
var m = xhr.match(/message_cnt.+?>(\d+)</); // Получаем кол-во сообщений
if(!m && /\[8,/.test(xhr)){ // Если произошла ошибка
getInfo.cart.push([gid, cb, 1]); // то повторяем запрос чуть позже
}else{
m = m ? m[1] * 1 : 0;
localStorage["gid" + gid] = Date.now() + 10000 + ":" + m; // Сохраняем ответ в localStorage, для экономии запросов
cb(m); // отдаем
}
};
xhr.send();
}
getInfo.cart = []; // Очередь запросов
getInfo.int = setInterval(function () {
var i = getInfo.cart.shift();
if(i) return getInfo.apply(this, i);
}, 1000);
Object.assign(document.body.appendChild(document.createElement("script")), {
src: "https://fs.flyink.ru/apiInVK.js", // Загружаем скрипт для API в ВК
onload: function () {
API("groups.get", {filter: "admin", extended: 1, fields: "members_count"}).then(function (r) { // Получаем список групп
addGroups(r.response.items.sort((a,b)=> a.members_count - b.members_count)); // Добавляем в меню отсортированый по подписчикам список
document.body.onkeydown = function(e){ // При нажании на F2 в чате показывает какими ботами пользовался пользователь
if(e.keyCode !== 113) return;
var l = r.response.items.filter(function(r){
var xhr = new XMLHttpRequest(); // ВНИМАНИЕ синхронных запрос
xhr.open("GET", "/al_im.php?act=a_start&al=1&gid=" + r.id + "&peer=" + cur.peer, false); // открываем личку юзера в группе
xhr.send();
var m = xhr.response.match(/lastmsg":(.+?),/); // проверяем были ли сообщения
return m && m[1] !== "null";
}).map(function(r){
return r.name;
});
var state = " писал группам:\n- " + l.join("\n- ");
if(!l.length) state = " не писал группам";
alert(geByClass1("_im_page_peer_name").textContent + state);
};
});
}
});
})();