Drive2 Old Auto UnSubscriber

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

目前為 2021-10-19 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Drive2 Old Auto UnSubscriber
// @namespace    drive2.ru
// @version      0.51
// @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");
    var i = false;
    if (list.length > 0)
    {
        for(var c = 0; c < list.length; c++)
        {
            container = list[c];

            i = container.querySelectorAll(".c-car-card-sa__subscribe button");

            if (i)
            {
                car_id = i.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);