Drive2 Old Auto UnSubscriber

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

目前为 2021-10-20 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Drive2 Old Auto UnSubscriber
  3. // @namespace drive2.ru
  4. // @version 0.681
  5. // @description работает на стренице подписок на сашины. проврка на бывшие авто и взаимные подписки, автоматически отписывается от бывших авто и от машин чьи владельцы не во взаимной подписке.
  6. // @author joker ivan
  7. // @match https://www.drive2.ru/*/carsfollowing
  8. // @grant none
  9.  
  10. // ==/UserScript==
  11.  
  12. // находим секретные ключи для автоматических запросов
  13. var FCTX = document.querySelectorAll("input")[0].value;
  14. var tail = __d2_env.userId;
  15.  
  16. var pages = 1; // количество проверенных страниц
  17. var checked_cars = 0;
  18.  
  19. // методы для автоматических запросов
  20. var ajax = {};
  21. ajax.x = function () {
  22. if (typeof XMLHttpRequest !== 'undefined') {
  23. return new XMLHttpRequest();
  24. }
  25. var versions = [
  26. "MSXML2.XmlHttp.6.0",
  27. "MSXML2.XmlHttp.5.0",
  28. "MSXML2.XmlHttp.4.0",
  29. "MSXML2.XmlHttp.3.0",
  30. "MSXML2.XmlHttp.2.0",
  31. "Microsoft.XmlHttp"
  32. ];
  33.  
  34. var xhr;
  35. for (var i = 0; i < versions.length; i++) {
  36. try {
  37. xhr = new ActiveXObject(versions[i]);
  38. break;
  39. } catch (e) {
  40. }
  41. }
  42. return xhr;
  43. };
  44.  
  45. var ajax_status = 0;
  46. var request_in_process = false;
  47.  
  48. ajax.send = function (url, callback, method, data, async) {
  49. if (async === undefined) {
  50. async = true;
  51. }
  52. var x = ajax.x();
  53. x.open(method, url, async);
  54. x.onreadystatechange = function () {
  55. if (x.readyState == 4) {
  56. callback(x.responseText)
  57. }
  58. };
  59. if (method == 'POST') {
  60. x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  61. }
  62.  
  63. x.onload = function () {
  64. ajax_status = x.status;
  65. };
  66.  
  67. x.send(data)
  68. };
  69.  
  70. ajax.get = function (url, data, callback, async) {
  71. var query = [];
  72. for (var key in data) {
  73. query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
  74. }
  75. ajax.send(url + (query.length ? '?' + query.join('&') : ''), callback, 'GET', null, async)
  76. };
  77.  
  78. ajax.post = function (url, data, callback, async) {
  79. var query = [];
  80. for (var key in data) {
  81. query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
  82. }
  83. sleep(1000);
  84. ajax.send(url, callback, 'POST', query.join('&'), async)
  85. };
  86.  
  87. // ищем кнопки "страниц" и открываем их все пока получается
  88. function clickNext(){
  89. var nextClicked = false;
  90. var nextbutton = document.querySelectorAll("button.c-block__more");
  91.  
  92. if(nextbutton.length > 0){
  93. sleep(1000);
  94. document.querySelectorAll("button.c-block__more")[0].click();
  95. nextClicked = true;
  96. pages++;
  97. } else {
  98. console.log('not found - next btn');
  99. }
  100.  
  101. if (!nextClicked)
  102. {
  103. clearInterval(nIntervId);
  104. console.log('all pages opened');
  105. }
  106.  
  107. show_status();
  108.  
  109. ButtonClickAction();
  110. }
  111.  
  112.  
  113.  
  114. // паузы
  115. function sleep(milliseconds) {
  116. let timeStart = new Date().getTime();
  117. while (true) {
  118. let elapsedTime = new Date().getTime() - timeStart;
  119. if (elapsedTime > milliseconds) {
  120. break;
  121. }
  122. }
  123. }
  124.  
  125. var cars_unsubscribed = 0;
  126. var car_ids = []; // тут собираем ID машин которые отмечены как "бывшие"
  127. var check_users = [];
  128. var found_cars_count = 0;
  129.  
  130. var sIntervId = false;
  131. var cIntervId = false;
  132.  
  133. // отписаться от машинки
  134. function unsubscribe_car(car_id)
  135. {
  136. ajax.post('/ajax/subscription', {'_': "unsubscribe", 'type': "car", 'id': car_id, '.FCTX': FCTX}, function() {
  137. cars_unsubscribed++;
  138. console.log('cars unSubscribed: ' + cars_unsubscribed + ' / ' + found_cars_count);
  139. request_in_process = false;
  140.  
  141. // переотправляем в очередь запрос который не прошел
  142. if (ajax_status == 403)
  143. {
  144. car_ids.push(car_id);
  145. return;
  146. }
  147. show_status();
  148. });
  149. }
  150.  
  151. // рисуем статистику
  152. function show_status()
  153. {
  154. console.log('... [очередь: проверить на взаимность ' + check_users.length + ' машин, отписаться от ' + car_ids.length + ' машин] [проверено: ' + pages + ' страниц, ' + checked_cars + ' машин]');
  155.  
  156. if (document.getElementById('in-check-query') === null)
  157. {
  158. var infoBoxDiv = document.createElement ('div');
  159. infoBoxDiv.innerHTML = 'В очереди проверить на взаимность: <span id="in-check-query">0</span><br>'
  160. + 'В очереди на отписаться: <span id="in-subscribe-query">0</span><br>'
  161. + 'обработано: <span id="pages-in-work">0</span><br>';
  162. infoBoxDiv.setAttribute ('class', 'infoBoxDiv');
  163. document.querySelectorAll(".x-title-header")[0].appendChild (infoBoxDiv);
  164. sleep(1000);
  165. }
  166.  
  167. document.getElementById('in-check-query').innerHTML = check_users.length;
  168. document.getElementById('in-subscribe-query').innerHTML = car_ids.length;
  169. document.getElementById('pages-in-work').innerHTML = '[' + pages + ' страниц, ' + checked_cars + ' машин]';
  170.  
  171. if (car_ids.length > 0 && sIntervId == false)
  172. {
  173. sIntervId = setInterval(unSubs, 1000);
  174. console.log('запуск отписок от машин в крон');
  175. }
  176.  
  177. if (check_users.length > 0 && cIntervId == false)
  178. {
  179. cIntervId = setInterval(check_user, 1000);
  180. console.log('запуск проверок юзеров в крон');
  181. }
  182.  
  183. if (car_ids.length == 0 && sIntervId)
  184. {
  185. clearInterval(sIntervId); // завершаем цикл
  186. sIntervId = false;
  187. console.log('остановка отписок от машин в крон');
  188. }
  189.  
  190. if (check_users.length == 0 && cIntervId)
  191. {
  192. clearInterval(cIntervId);
  193. cIntervId = false;
  194. console.log('остановка проверок юзеров в крон');
  195. }
  196. }
  197.  
  198. // проверяем взаимную подписку у владельца
  199. function check_user()
  200. {
  201. var first = car_ids.length == 0;
  202.  
  203. if (request_in_process)
  204. {
  205. console.log('check_user - запросы заняты');
  206. return;
  207. }
  208.  
  209. var item = check_users.pop(); //{'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
  210. if (!item)
  211. {
  212. console.log('check_user - пусто в очереди');
  213. return;
  214. }
  215.  
  216. console.log('check_user - ' + item.user_id);
  217.  
  218. request_in_process = true;
  219.  
  220. ajax.get('/ajax/info/', {'type': item.user_type, 'id': item.user_id, 'tail': tail}, function(response) {
  221.  
  222. request_in_process = false;
  223. checked_cars++;
  224.  
  225. if (ajax_status != 200)
  226. {
  227. // глюки, проверим в другой раз значит
  228. return;
  229. }
  230.  
  231. var data = typeof response === 'string' ? JSON.parse(response) : response;
  232.  
  233. var user_not_subscribed = typeof data.html !== 'undefined' // с запросом вс ОК
  234. && (data.html.indexOf("назад") > -1 || data.html.indexOf("Сейчас") > -1) // на странице есть слово "назад" или "Сейчас" (когда последний раз был владелец)
  235. && data.html.indexOf("Подписан") === -1; // на странице нет слова "Подписан"
  236.  
  237. if (user_not_subscribed)
  238. {
  239. // не подписан, отписываемся от такого
  240. console.log('нет взаимной подписки', item.car_id);
  241. car_ids.push(item.car_id);
  242.  
  243. if (first && sIntervId == false)
  244. {
  245. sIntervId = setInterval(unSubs, 1000);
  246. console.log('запуск отписок от машин в крон');
  247. }
  248. } else {
  249. console.log('взаимная подписка имеется', item.car_id);
  250. }
  251.  
  252. show_status();
  253. });
  254. }
  255.  
  256. // собираем все машинки от которых нужно отписаться
  257. function ButtonClickAction ()
  258. {
  259.  
  260. console.log('ButtonClickAction');
  261.  
  262. var old; // признак что авто - бывшее
  263. var user;
  264. var user_type;
  265. var user_id;
  266. var car_id;
  267. var container;
  268.  
  269. var first = check_users.length == 0;
  270.  
  271. // собираем все контейнеры
  272. var list = document.querySelectorAll(".c-darkening-hover-container");
  273. var i = false;
  274. if (list.length > 0)
  275. {
  276. for(var c = 0; c < list.length; c++)
  277. {
  278. container = list[c];
  279.  
  280. i = container.querySelectorAll("button.c-button")[0];
  281.  
  282. if (i)
  283. {
  284. car_id = i.getAttribute('data-id');
  285.  
  286. // ищем не являемтся ли данные авто "бывшим"
  287. old = container.querySelectorAll(".c-car-title.c-link.c-link--gray")
  288. if (old.length)
  289. {
  290. // сразу отписываемся от авто
  291. console.log('обнаружена подписка на бывшее авто', car_id);
  292. car_ids.push(car_id);
  293. checked_cars++;
  294. } else {
  295. // проверяем взаимную подписку у владельца
  296. user = container.querySelectorAll("a.c-username")[0];
  297. //car_id = container.querySelectorAll("button.c-button--subs")[0].getAttribute('data-id');
  298. //check_user(user, car_id);
  299.  
  300. user_type = user.getAttribute('data-ihc-type');
  301. user_id = user.getAttribute('data-ihc-id');
  302. check_users.push({'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
  303. console.log('ставим на проверку юзера ' + user_id + ' с машинкой ' + car_id);
  304. }
  305. }
  306.  
  307. // чистим страничку для загрузки новых данных и чтоб DOM дерево не разрасталось
  308. container.remove();
  309. }
  310. }
  311.  
  312. found_cars_count = car_ids.length;
  313. show_status();
  314. }
  315.  
  316. // отписываемся от них
  317. function unSubs()
  318. {
  319. if (request_in_process)
  320. {
  321. console.log('unSubs - занято в очереди');
  322. return;
  323. }
  324.  
  325. var car_id = car_ids.pop();
  326. if (car_id)
  327. {
  328. console.log('unSubs - ' + car_id);
  329. request_in_process = true;
  330. unsubscribe_car(car_id);
  331. } else {
  332. console.log('unSubs - пусто в очереди');
  333. }
  334.  
  335. show_status();
  336. }
  337.  
  338. console.log('next btn search start');
  339. var nIntervId = setInterval(clickNext, 3000); // открываем все страницы и обрабатываем их
  340.  
  341. check_user();
  342. unSubs();