您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Автокликер для добавления друзей ВК со страницы рекомендаций
// ==UserScript== // @namespace prolaps.ru // @name VK recomended friends auto clicker // @description Автокликер для добавления друзей ВК со страницы рекомендаций // @author L.A.P.S. Lab // @version 0.8 // @include https://vk.com/friends* // @match https://vk.com/friends?act=find // @License MIT // ==/UserScript== /* FEATURES: * 1. variable click interval delay * 2. click all links in random order **/ // Initial prefs const targetURL = "https://vk.com/friends?act=find"; const targetUiElementSelector = "span.vkuiButton__content"; const minTimeToClick = 10; const maxTimeToClick = 30; const autostart = false; let hotkeysUI = null; const tasks = []; const logs = []; // TODO следующий класс описан в соответствующем модуле const defaultConfig = {}; class HotkeysUI { #metaData = {}; constructor(config) { if (this.config === undefined) { this.config = defaultConfig; } else { this.config = config; } this.#metaData.listeners = []; this.activateKeyboardListener(); } activateKeyboardListener() { this.#metaData.listeners.push( window.addEventListener("keydown", (event) => { console.log("keyDown event..."); if (event.altKey && (event.key === "h" || event.key === "H")) { event.preventDefault(); console.log("[L.A.P.S. Lab] activate app by hotkey..."); app(); } }) ); } /** * удаляет все слушатели событий из #metadata.listeners */ deactivateListeners() { if (this.#metaData.listeners && this.#metaData.listeners.length > 0) { this.#metaData.listeners.forEach((listener) => { window.removeEventListener("keydown", listener); }); } } /** * удаляет все слушатели событий * потом будет удалять экземпляр класса */ kill() { this.deactivateListeners(); } } // TODO конец удаляемого класса /** * this function checks url * @returns true or false * * Проверка идет по вхождению подстроки в строку! */ const checkLocation = () => window.location.href.includes(targetURL) ? true : false; /** * This function does make standard timestamp string for all types of output **/ const getTimeStamp = () => new Date().toLocaleTimeString(); /** * this function does shuffle found links * @param {HTMLCollection} collection * @returns sorted collection in random order */ const shuffleData = (collection) => collection.sort((a, b) => Math.random() - 0.5); /** * this function does generate random interval in range of arguments * @param {number} min * @param {number} max * @returns value of timeout to make click in seconds */ const setRandomInterval = (min, max) => { return Math.floor(Math.random() * (max - min + 1) + min); }; /** * TODO не подставляется имя при формировании лог-строки по причине того, что референс гамно! Перепиши референс от кнопки - и тогда-то все и заработает, блэт! * я тут пошарил в консоли и нашарил такой референс: .parentElement.parentElement.children[2].children[0].textContent, но после того, * как я эту хню вставил в @logString вместо .name, всек хуям сломалось * @param {object} friend with "name" & "link" */ const clickThisLink = (friend) => { // do work friend.click(); // remove task from array tasks if (tasks.find((item) => item.name === friend.name) !== -1) { tasks.splice(tasks.indexOf(friend.name), 1); } // prepare log string const timestamp = getTimeStamp(); const logString = `(${logs.length + 1})Запрос в друзья отправлен: ${ friend.name } в ${timestamp}.`; // log string push console.info(logString); logs.push(logString); // end app if finished if (tasks.length === 0) { endApp(); } }; const prepareLogsParagraph = () => { let logsParagraph = new String(); logs.forEach((logItem) => { logsParagraph = logsParagraph + logItem + "\n"; }); logsParagraph += "-----------------------\nL.A.P.S. Lab: автокликер закончил работу. Для повторного запуска скрипта обновите страницу (CTRL+R)."; alert(logsParagraph); return logsParagraph; }; /** * This func does make clicks with timeout * @param {array} items * @param {number} timeout */ const clickItemWithTimeout = (item, timeout) => window.setTimeout(clickThisLink, timeout * 1000, item); const endApp = () => { console.info("L.A.P.S. Lab: завершение..."); console.info( "Удаление обработчиков событий клавиатуры...\n", (hotkeysUI.kill() && "Обработчики событий удалены.") || "hotkeysUI.kill() failed!" ); if (logs.length > 0) { prepareLogsParagraph(); logs.length = 0; } else { alert( `L.A.P.S. Lab: Логи автокликера не обнаружены.\nАвтокликер закончил работу. Для повторного запуска скрипта обновите страницу (CTRL+R).` ); } console.info( "L.A.P.S. Lab: автокликер закончил работу. Для повторного запуска скрипта обновите страницу." ); }; const makeWork = (data) => { let prevTimeoutSum = 0; let newTimeout = null; data.forEach((item) => { newTimeout = setRandomInterval(minTimeToClick, maxTimeToClick); clickItemWithTimeout(item, prevTimeoutSum + newTimeout); prevTimeoutSum += newTimeout; tasks.push(item.name); }); }; const app = () => { console.info( "L.A.P.S. Lab: запускаем автокликер для добавления друзей ВК..." ); // define & prepare data const alternativeFoundData = Array.from( document.querySelectorAll(targetUiElementSelector) ).filter( (elem) => elem.textContent.toLowerCase().includes("добавить") || elem.textContent.toLowerCase().includes("подписаться") ); console.log(`found ${alternativeFoundData.length} candidates to click`); const shuffledData = shuffleData(alternativeFoundData); // make work if (autostart) { makeWork(shuffledData); } else { const start = confirm( `L.A.P.S. Lab VK friends autoclicker:\n------------------------------------\nНайдено ${alternativeFoundData.length} рекомендаций. Добавить?` ); start ? makeWork(shuffledData) : endApp(); endApp(); } }; const activateExtensionOnLoad = () => { window.addEventListener("load", (event) => { hotkeysUI = new HotkeysUI(); console.log("EVENT: 'load'"); }); }; if (checkLocation()) { activateExtensionOnLoad(); }