您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
работает на стренице подписок на сашины. проврка на бывшие авто и взаимные подписки, автоматически отписывается от бывших авто и от машин чьи владельцы не во взаимной подписке.
当前为
// ==UserScript== // @name Drive2 Old Auto UnSubscriber // @namespace drive2.ru // @version 0.78 // @description работает на стренице подписок на сашины. проврка на бывшие авто и взаимные подписки, автоматически отписывается от бывших авто и от машин чьи владельцы не во взаимной подписке. // @author drive2 lover // @match https://www.drive2.ru/*/carsfollowing // @match https://www.drive2.com/*/carsfollowing // @license MIT // @grant none // ==/UserScript== let tail = ''; let fctx = ''; const MY_CARS_KEY = 'my_cars'; const myCars = localStorage.getItem(MY_CARS_KEY) ? JSON.parse(localStorage.getItem(MY_CARS_KEY)) : false; // Создаем блок статистики const statsDiv = document.createElement('div'); statsDiv.style.position = 'fixed'; statsDiv.style.top = '0'; statsDiv.style.left = '0'; statsDiv.style.backgroundColor = '#333'; statsDiv.style.color = '#fff'; statsDiv.style.padding = '15px'; statsDiv.style.margin = '10px'; statsDiv.style.zIndex = '1000'; document.body.appendChild(statsDiv); const unsubscribeCheckboxDiv = document.createElement('div'); const unsubscribeCheckbox = document.createElement('input'); unsubscribeCheckbox.type = 'checkbox'; unsubscribeCheckbox.checked = true; unsubscribeCheckbox.id='unsubscribe-checkbox'; const unsubscribeLabel = document.createElement('label'); unsubscribeLabel.textContent = ' Отписываться от авто'; unsubscribeLabel.style.marginRight = '10px'; unsubscribeLabel.setAttribute('for', 'unsubscribe-checkbox'); const hideOldCarsCheckboxDiv = document.createElement('div'); const hideOldCarsCheckbox = document.createElement('input'); hideOldCarsCheckbox.type = 'checkbox'; hideOldCarsCheckbox.checked = true; hideOldCarsCheckbox.id = 'hide-old-cars-checkbox'; const hideOldCarsLabel = document.createElement('label'); hideOldCarsLabel.textContent = ' Скрывать старые авто'; hideOldCarsLabel.style.marginRight = '10px'; hideOldCarsLabel.setAttribute('for', 'hide-old-cars-checkbox'); const checkButton = document.createElement('button'); checkButton.innerText = 'Проверить'; checkButton.style.marginTop = '10px'; checkButton.style.padding = '5px 10px'; checkButton.style.backgroundColor = '#007bff'; checkButton.style.color = '#fff'; checkButton.style.border = 'none'; checkButton.style.borderRadius = '5px'; checkButton.style.cursor = 'pointer'; unsubscribeCheckboxDiv.appendChild(unsubscribeCheckbox); unsubscribeCheckboxDiv.appendChild(unsubscribeLabel); statsDiv.appendChild(unsubscribeCheckboxDiv); hideOldCarsCheckboxDiv.appendChild(hideOldCarsCheckbox); hideOldCarsCheckboxDiv.appendChild(hideOldCarsLabel); statsDiv.appendChild(hideOldCarsCheckboxDiv); statsDiv.appendChild(checkButton); let stats = { pages: 0, totalBlocks: 0, processedBlocks: 0, removedBlocks: 0, unsubscribedBlocks: 0, oldSubscribedBlocks: 0 }; const updateStats = () => { statsDiv.innerHTML = `<div> Страниц пройдено: ${stats.pages}<br> Иконок авто в очереди: ${stats.totalBlocks}<br> Обработано: ${stats.processedBlocks}<br> Отписались автоматом: ${stats.unsubscribedBlocks}<br> Подписан на старые авто: ${stats.oldSubscribedBlocks} </div>`; statsDiv.appendChild(unsubscribeCheckboxDiv); statsDiv.appendChild(hideOldCarsCheckboxDiv); statsDiv.appendChild(checkButton); }; updateStats(); // Функция для поиска и клика по кнопке "Загрузить еще" const clickMoreButton = async () => { const button = document.querySelector('button.x-box-more'); if (button) { stats.pages++; console.log('Загружаем страницу ' + stats.pages); button.click(); if (!localStorage.getItem(MY_CARS_KEY)) { const response = await fetch('/my/r/'); const html = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const cars = []; doc.querySelectorAll('.c-car-draglist__item .c-car-card__caption a').forEach(car => { if (!car.classList.contains('x-secondary-color')) { const id = car.href.match(/\/(\d+)\//)[1]; cars.push({ id, name: car.textContent.trim() }); } }); localStorage.setItem(MY_CARS_KEY, JSON.stringify(cars)); } updateStats(); await new Promise(resolve => setTimeout(resolve, 3000)); processBlocks(); } else { console.log('Кнопка не найдена, продолжаем проверку...'); } }; const unsubscribeCar = async (id) => { const url = '/ajax/subscription'; const data = { _: 'unsubscribe', type: 'car', id: id, '.FCTX': fctx }; try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams(data).toString() }); if (response.ok) { const result = await response.json(); console.log('Ответ сервера:', result); } else { console.error('Ошибка запроса:', response.status); } } catch (error) { console.error('Ошибка выполнения POST-запроса:', error); } }; const processBlocks = async () => { const blocks = document.querySelectorAll('.c-car-card-sa'); updateStats(); for (const block of blocks) { const titleElement = block.querySelector('.c-car-title'); stats.totalBlocks = document.querySelectorAll('.c-car-card-sa').length; // Если чекбокс скрытия старых авто включен и блок старый – пропускаем или удаляем if (titleElement.classList.contains('x-secondary-color')) { stats.oldSubscribedBlocks++; stats.processedBlocks++; if (hideOldCarsCheckbox.checked) { block.remove(); stats.removedBlocks++; } updateStats(); continue; } const subscribeButton = block.querySelector('subscribe-button'); const userId = block.querySelector('a.c-username')?.getAttribute('data-ihc-token'); if (!userId) continue; // Делаем GET-запрос для проверки подписки const response = await fetch(`https://www.drive2.com/_api/hovercards/${userId}?tail=${tail}`); const data = await response.json(); const followedCarIds = data?.subscriptions?.followedCars?.map(car => { const match = car.url.match(/\/(\d+)\//); return match ? match[1] : null; }).filter(Boolean); const myCarIds = myCars.map(car => car.id); const hasMyCar = followedCarIds ? followedCarIds.some(carId => myCarIds.includes(carId)) : false; if (hasMyCar) { console.log('Блок содержит одну из моих машин, пропускаем.'); } else { console.log('Блок не содержит моих машин.'); if (unsubscribeCheckbox.checked) { unsubscribeCar(subscribeButton.getAttribute('uid')); stats.unsubscribedBlocks++; } } // Удаляем блок, если он не содержит мою машину block.remove(); stats.removedBlocks++; stats.processedBlocks++; updateStats(); // Ждём 1 секунду перед обработкой следующего блока await new Promise(resolve => setTimeout(resolve, 2000)); } clickMoreButton(); }; checkButton.addEventListener('click', processBlocks); function init_me() { // находим секретные ключи для автоматических запросов if (window.d2Env) { tail = window.d2Env.userId; fctx = window.d2Env.formContext['.FCTX']; } else { alert('обновите версию скрипта!'); return; } } init_me();