Drive2 Old Auto UnSubscriber

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

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

  1. // ==UserScript==
  2. // @name Drive2 Old Auto UnSubscriber
  3. // @namespace drive2.ru
  4. // @version 0.61
  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. if(nextbutton.length > 0){
  92. sleep(1000);
  93. document.querySelectorAll("button.c-block__more")[0].click();
  94. nextClicked = true;
  95. pages++;
  96. } else {
  97. console.log('not found - next btn');
  98. }
  99.  
  100. if (!nextClicked)
  101. {
  102. clearInterval(nIntervId);
  103. console.log('all pages opened');
  104. }
  105.  
  106. show_status();
  107.  
  108. ButtonClickAction();
  109. }
  110.  
  111.  
  112.  
  113. // паузы
  114. function sleep(milliseconds) {
  115. let timeStart = new Date().getTime();
  116. while (true) {
  117. let elapsedTime = new Date().getTime() - timeStart;
  118. if (elapsedTime > milliseconds) {
  119. break;
  120. }
  121. }
  122. }
  123.  
  124. var cars_unsubscribed = 0;
  125. var car_ids = []; // тут собираем ID машин которые отмечены как "бывшие"
  126. var check_users = [];
  127. var found_cars_count = 0;
  128.  
  129. var sIntervId = false;
  130. var cIntervId = false;
  131.  
  132. // отписаться от машинки
  133. function unsubscribe_car(car_id)
  134. {
  135. ajax.post('/ajax/subscription', {'_': "unsubscribe", 'type': "car", 'id': car_id, '.FCTX': FCTX}, function() {
  136. cars_unsubscribed++;
  137. console.log('cars unSubscribed: ' + cars_unsubscribed + ' / ' + found_cars_count);
  138. request_in_process = false;
  139.  
  140. // переотправляем в очередь запрос который не прошел
  141. if (ajax_status == 403)
  142. {
  143. car_ids.push(car_id);
  144. return;
  145. }
  146. show_status();
  147. });
  148. }
  149.  
  150. // рисуем статистику
  151. function show_status()
  152. {
  153. console.log('... [очередь: проверить на взаимность ' + check_users.length + ' машин, отписаться от ' + car_ids.length + ' машин] [проверено: ' + pages + ' страниц, ' + checked_cars + ' машин]');
  154.  
  155. if (document.getElementById('in-check-query') === null)
  156. {
  157. var infoBoxDiv = document.createElement ('div');
  158. infoBoxDiv.innerHTML = 'В очереди проверить на взаимность: <span id="in-check-query">0</span><br>'
  159. + 'В очереди на отписаться: <span id="in-subscribe-query">0</span><br>'
  160. + 'обработано: <span id="pages-in-work">0</span><br>';
  161. infoBoxDiv.setAttribute ('class', 'infoBoxDiv');
  162. document.querySelectorAll(".x-title-header")[0].appendChild (infoBoxDiv);
  163. sleep(1000);
  164. }
  165.  
  166. document.getElementById('in-check-query').innerHTML = check_users.length;
  167. document.getElementById('in-subscribe-query').innerHTML = car_ids.length;
  168. document.getElementById('pages-in-work').innerHTML = '[' + pages + ' страниц, ' + checked_cars + ' машин]';
  169.  
  170. if (car_ids.length > 0 && !sIntervId)
  171. {
  172. sIntervId = setInterval(unSubs, 1000);
  173. }
  174.  
  175. if (check_users.length > 0 && !cIntervId)
  176. {
  177. cIntervId = setInterval(check_user, 1000);
  178. }
  179.  
  180. if (check_users.length == 0 && sIntervId)
  181. {
  182. clearInterval(sIntervId); // завершаем цикл
  183. }
  184.  
  185. if (car_ids.length == 0 && cIntervId)
  186. {
  187. clearInterval(cIntervId);
  188. }
  189. }
  190.  
  191. // проверяем взаимную подписку у владельца
  192. function check_user()
  193. {
  194. var first = car_ids.length == 0;
  195.  
  196. if (request_in_process)
  197. {
  198. return;
  199. }
  200.  
  201. var item = check_users.pop(); //{'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
  202. if (!item)
  203. {
  204. return;
  205. }
  206.  
  207. request_in_process = true;
  208. ajax.get('/ajax/info/', {'type': item.user_type, 'id': item.user_id, 'tail': tail}, function(response) {
  209.  
  210. request_in_process = false;
  211. checked_cars++;
  212.  
  213. if (ajax_status != 200)
  214. {
  215. // глюки, проверим в другой раз значит
  216. return;
  217. }
  218.  
  219. var data = typeof response === 'string' ? JSON.parse(response) : response;
  220.  
  221. var user_not_subscribed = typeof data.html !== 'undefined' // с запросом вс ОК
  222. && (data.html.indexOf("назад") > -1 || data.html.indexOf("Сейчас") > -1) // на странице есть слово "назад" или "Сейчас" (когда последний раз был владелец)
  223. && data.html.indexOf("Подписан") === -1; // на странице нет слова "Подписан"
  224.  
  225. if (user_not_subscribed)
  226. {
  227. // не подписан, отписываемся от такого
  228. console.log('нет взаимной подписки', item.car_id);
  229. car_ids.push(item.car_id);
  230.  
  231. if (first)
  232. {
  233. sIntervId = setInterval(unSubs, 1000);
  234. }
  235. }
  236.  
  237. show_status();
  238. });
  239. }
  240.  
  241. // собираем все машинки от которых нужно отписаться
  242. function ButtonClickAction () {
  243.  
  244. var old; // признак что авто - бывшее
  245. var user;
  246. var user_type;
  247. var user_id;
  248. var car_id;
  249. var container;
  250.  
  251. // собираем все контейнеры
  252. var list = document.querySelectorAll(".c-darkening-hover-container");
  253. var i = false;
  254. if (list.length > 0)
  255. {
  256. for(var c = 0; c < list.length; c++)
  257. {
  258. container = list[c];
  259.  
  260. i = container.querySelectorAll("button.c-button")[0];
  261.  
  262. if (i)
  263. {
  264. car_id = i.getAttribute('data-id');
  265.  
  266. // ищем не являемтся ли данные авто "бывшим"
  267. old = container.querySelectorAll(".c-car-title.c-link.c-link--gray")
  268. if (old.length)
  269. {
  270. // сразу отписываемся от авто
  271. console.log('обнаружена подписка на бывшее авто', car_id);
  272. car_ids.push(car_id);
  273. checked_cars++;
  274. } else {
  275. // проверяем взаимную подписку у владельца
  276. user = container.querySelectorAll("a.c-username")[0];
  277. //car_id = container.querySelectorAll("button.c-button--subs")[0].getAttribute('data-id');
  278. //check_user(user, car_id);
  279.  
  280. user_type = user.getAttribute('data-ihc-type');
  281. user_id = user.getAttribute('data-ihc-id');
  282. check_users.push({'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
  283. console.log('ставим на проверку юзера ' + user_id + ' с машинкой ' + car_id);
  284. }
  285. }
  286.  
  287. // чистим страничку для загрузки новых данных и чтоб DOM дерево не разрасталось
  288. container.remove();
  289. }
  290. }
  291.  
  292. found_cars_count = car_ids.length;
  293.  
  294. show_status();
  295. }
  296.  
  297. // отписываемся от них
  298. function unSubs()
  299. {
  300. if (request_in_process)
  301. {
  302. return;
  303. }
  304.  
  305. request_in_process = true;
  306. var car_id = car_ids.pop();
  307. if (car_id)
  308. {
  309. unsubscribe_car(car_id);
  310. }
  311.  
  312. show_status();
  313. }
  314.  
  315. console.log('next btn search start');
  316. var nIntervId = setInterval(clickNext, 3000); // открываем все страницы и обрабатываем их
  317.  
  318. check_user();
  319. unSubs();