Drive2 Old Auto UnSubscriber

работает на стренице подписок на сашины. проврка на бывшие авто и взаимные подписки, автоматически отписывается от бывших авто и от машин чьи владельцы не во взаимной подписке.

当前为 2021-10-19 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Drive2 Old Auto UnSubscriber
// @namespace    drive2.ru
// @version      0.5
// @description  работает на стренице подписок на сашины. проврка на бывшие авто и взаимные подписки, автоматически отписывается от бывших авто и от машин чьи владельцы не во взаимной подписке.
// @author       joker ivan
// @match        https://www.drive2.ru/*/carsfollowing
// @grant        none

// ==/UserScript==

// находим секретные ключи для автоматических запросов
var FCTX = document.querySelectorAll("input")[0].value;
var tail = __d2_env.userId;

var pages = 1; // количество проверенных страниц
var checked_cars = 0;

// методы для автоматических запросов
var ajax = {};
ajax.x = function () {
    if (typeof XMLHttpRequest !== 'undefined') {
        return new XMLHttpRequest();
    }
    var versions = [
        "MSXML2.XmlHttp.6.0",
        "MSXML2.XmlHttp.5.0",
        "MSXML2.XmlHttp.4.0",
        "MSXML2.XmlHttp.3.0",
        "MSXML2.XmlHttp.2.0",
        "Microsoft.XmlHttp"
    ];

    var xhr;
    for (var i = 0; i < versions.length; i++) {
        try {
            xhr = new ActiveXObject(versions[i]);
            break;
        } catch (e) {
        }
    }
    return xhr;
};

var ajax_status = 0;
var request_in_process = false;

ajax.send = function (url, callback, method, data, async) {
    if (async === undefined) {
        async = true;
    }
    var x = ajax.x();
    x.open(method, url, async);
    x.onreadystatechange = function () {
        if (x.readyState == 4) {
            callback(x.responseText)
        }
    };
    if (method == 'POST') {
        x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    }

    x.onload = function () {
        ajax_status = x.status;
    };

    x.send(data)
};

ajax.get = function (url, data, callback, async) {
    var query = [];
    for (var key in data) {
        query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
    }
    ajax.send(url + (query.length ? '?' + query.join('&') : ''), callback, 'GET', null, async)
};

ajax.post = function (url, data, callback, async) {
    var query = [];
    for (var key in data) {
        query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
    }
    sleep(1000);
    ajax.send(url, callback, 'POST', query.join('&'), async)
};

// ищем кнопки "страниц" и открываем их все пока получается
function clickNext(){
    var nextClicked = false;
    var nextbutton = document.querySelectorAll("button.c-block__more");
    if(nextbutton.length > 0){
        sleep(1000);
        document.querySelectorAll("button.c-block__more")[0].click();
        nextClicked = true;
        pages++;
    } else {
        console.log('not found - next btn');
    }

    if (!nextClicked)
    {
        clearInterval(nIntervId);
        console.log('all pages opened');
    }

    if (car_ids.length > 0 && sIntervId == false)
    {
        sIntervId = setInterval(unSubs, 1000);
    }

    ButtonClickAction();
}

// паузы
function sleep(milliseconds) {
    let timeStart = new Date().getTime();
    while (true) {
        let elapsedTime = new Date().getTime() - timeStart;
        if (elapsedTime > milliseconds) {
            break;
        }
    }
}

var cars_unsubscribed = 0;
var car_ids = []; // тут собираем ID машин которые отмечены как "бывшие"
var check_users = [];
var found_cars_count = 0;

// отписаться от машинки
function unsubscribe_car(car_id)
{
    ajax.post('/ajax/subscription', {'_': "unsubscribe", 'type': "car", 'id': car_id, '.FCTX': FCTX}, function() {
        cars_unsubscribed++;
        console.log('cars unSubscribed: ' + cars_unsubscribed + ' / ' + found_cars_count);
        request_in_process = false;

        // переотправляем в очередь запрос который не прошел
        if (ajax_status == 403)
        {
            car_ids.push(car_id);
            return;
        }
        show_status();
    });
}

// рисуем статистику
function show_status()
{
    console.log('... [очередь: проверить на взаимность ' + check_users.length + ' машин, отписаться от ' + car_ids.length + ' машин] [проверено: ' + pages + ' страниц, ' + checked_cars + ' машин]');

    if (document.getElementById('in-check-query') === null)
    {
        var infoBoxDiv = document.createElement ('div');
        infoBoxDiv.innerHTML = 'В очереди проверить на взаимность: <span id="in-check-query">0</span><br>'
                + 'В очереди на отписаться: <span id="in-subscribe-query">0</span><br>'
                + 'обработано: <span id="pages-in-work">0</span><br>';
        infoBoxDiv.setAttribute ('class', 'infoBoxDiv');
        document.querySelectorAll(".l-page-header")[0].appendChild (infoBoxDiv);
        sleep(1000);
    }

    document.getElementById('in-check-query').innerHTML = check_users.length;
    document.getElementById('in-subscribe-query').innerHTML = car_ids.length;
    document.getElementById('pages-in-work').innerHTML = '[' + pages + ' страниц, ' + checked_cars + ' машин]';

    if (car_ids.length > 0 && sIntervId == false)
    {
        sIntervId = setInterval(unSubs, 1000);
    }

    if (check_users.length > 0 && cIntervId == false)
    {
        cIntervId = setInterval(check_user, 1000);
    }
}

// проверяем взаимную подписку у владельца
function check_user()
{
    if (request_in_process)
    {
        return;
    }

    var item = check_users.pop(); //{'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
    if (!item)
    {
        return;
    }

    request_in_process = true;
    ajax.get('/ajax/info/', {'type': item.user_type, 'id': item.user_id, 'tail': tail}, function(response) {

        request_in_process = false;
        checked_cars++;

        if (ajax_status != 200)
        {
            // глюки, проверим в другой раз значит
            return;
        }

        var data = typeof response === 'string' ? JSON.parse(response) : response;

        var user_not_subscribed = typeof data.html !== 'undefined' // с запросом вс ОК
           && (data.html.indexOf("назад") > -1 || data.html.indexOf("Сейчас") > -1) // на странице есть слово "назад" или "Сейчас" (когда последний раз был владелец)
           && data.html.indexOf("Подписан") === -1; // на странице нет слова "Подписан"

        if (user_not_subscribed)
        {
            // не подписан, отписываемся от такого
            console.log('нет взаимной подписки', item.car_id);
            car_ids.push(item.car_id);
        }

        show_status();
    });
}

// собираем все машинки от которых нужно отписаться
function ButtonClickAction () {

    var old; // признак что авто - бывшее
    var user;
    var user_type;
    var user_id;
    var car_id;
    var container;

    // собираем все контейнеры
    var list = document.querySelectorAll(".c-darkening-hover-container");
    if (list.length > 0)
    {
        for(var c = 0; c < list.length; c++)
        {
            container = list[c];
            car_id = container.querySelectorAll(".c-car-card-sa__subscribe button")[0].getAttribute('data-id');

            // ищем не являемтся ли данные авто "бывшим"
            old = container.querySelectorAll(".c-car-title.c-link.c-link--gray")
            if (old.length)
            {
                // сразу отписываемся от авто
                console.log('обнаружена подписка на бывшее авто', car_id);
                car_ids.push(car_id);
                checked_cars++;
            } else {
                // проверяем взаимную подписку у владельца
                user = container.querySelectorAll(".c-username")[0];
                car_id = container.querySelectorAll(".c-car-card-sa__subscribe button")[0].getAttribute('data-id');
                //check_user(user, car_id);

                user_type = user.getAttribute('data-ihc-type');
                user_id = user.getAttribute('data-ihc-id');

                check_users.push({'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
            }

            // чистим страничку для загрузки новых данных и чтоб DOM дерево не разрасталось
            container.remove();
        }
    }

    found_cars_count = car_ids.length;

    if (car_ids.length > 0 && sIntervId == false)
    {
        sIntervId = setInterval(unSubs, 1000);
    }

}

// отписываемся от них
function unSubs()
{
    if (request_in_process)
    {
        return;
    }

    request_in_process = true;
    var car_id = car_ids.pop();
    if (car_id)
    {
        unsubscribe_car(car_id);
    } else { // если закончился список на отписку 
        if (check_users.length < 1) { // а также список на проверку
            if (sIntervId)
            {
                clearInterval(sIntervId); // завершаем цикл
            }
            if (cIntervId)
            {
                clearInterval(cIntervId);
            }
        }
    }
}

console.log('next btn search start');
var nIntervId = setInterval(clickNext, 3000); // открываем все страницы и обрабатываем их
var sIntervId = false;
var cIntervId = setInterval(check_user, 1000);