Drive2 Old Auto UnSubscriber

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

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

  1. // ==UserScript==
  2. // @name Drive2 Old Auto UnSubscriber
  3. // @namespace drive2.ru
  4. // @version 0.66
  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 == false)
  171. {
  172. sIntervId = setInterval(unSubs, 1000);
  173. console.log('запуск отписок от машин в крон');
  174. }
  175.  
  176. if (check_users.length > 0 && cIntervId == false)
  177. {
  178. cIntervId = setInterval(check_user, 1000);
  179. console.log('запуск проверок юзеров в крон');
  180. }
  181.  
  182. if (car_ids.length == 0 && sIntervId)
  183. {
  184. clearInterval(sIntervId); // завершаем цикл
  185. sIntervId = false;
  186. console.log('остановка отписок от машин в крон');
  187. }
  188.  
  189. if (check_users.length == 0 && cIntervId)
  190. {
  191. clearInterval(cIntervId);
  192. cIntervId = false;
  193. console.log('остановка проверок юзеров в крон');
  194. }
  195. }
  196.  
  197. // проверяем взаимную подписку у владельца
  198. function check_user()
  199. {
  200. var first = car_ids.length == 0;
  201.  
  202. if (request_in_process)
  203. {
  204. console.log('check_user - запросы заняты');
  205. return;
  206. }
  207.  
  208. var item = check_users.pop(); //{'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
  209. if (!item)
  210. {
  211. console.log('check_user - пусто в очереди');
  212. return;
  213. }
  214.  
  215. console.log('check_user - ' + item.user_id);
  216.  
  217. request_in_process = true;
  218. ajax.get('/ajax/info/', {'type': item.user_type, 'id': item.user_id, 'tail': tail}, function(response) {
  219.  
  220. request_in_process = false;
  221. checked_cars++;
  222.  
  223. if (ajax_status != 200)
  224. {
  225. // глюки, проверим в другой раз значит
  226. return;
  227. }
  228.  
  229. var data = typeof response === 'string' ? JSON.parse(response) : response;
  230.  
  231. var user_not_subscribed = typeof data.html !== 'undefined' // с запросом вс ОК
  232. && (data.html.indexOf("назад") > -1 || data.html.indexOf("Сейчас") > -1) // на странице есть слово "назад" или "Сейчас" (когда последний раз был владелец)
  233. && data.html.indexOf("Подписан") === -1; // на странице нет слова "Подписан"
  234.  
  235. if (user_not_subscribed)
  236. {
  237. // не подписан, отписываемся от такого
  238. console.log('нет взаимной подписки', item.car_id);
  239. car_ids.push(item.car_id);
  240.  
  241. if (first && sIntervId == false)
  242. {
  243. sIntervId = setInterval(unSubs, 1000);
  244. console.log('запуск отписок от машин в крон');
  245. }
  246. }
  247.  
  248. show_status();
  249. });
  250. }
  251.  
  252. // собираем все машинки от которых нужно отписаться
  253. function ButtonClickAction ()
  254. {
  255.  
  256. console.log('ButtonClickAction');
  257.  
  258. var old; // признак что авто - бывшее
  259. var user;
  260. var user_type;
  261. var user_id;
  262. var car_id;
  263. var container;
  264.  
  265. var first = check_users.length == 0;
  266.  
  267. // собираем все контейнеры
  268. var list = document.querySelectorAll(".c-darkening-hover-container");
  269. var i = false;
  270. if (list.length > 0)
  271. {
  272. for(var c = 0; c < list.length; c++)
  273. {
  274. container = list[c];
  275.  
  276. i = container.querySelectorAll("button.c-button")[0];
  277.  
  278. if (i)
  279. {
  280. car_id = i.getAttribute('data-id');
  281.  
  282. // ищем не являемтся ли данные авто "бывшим"
  283. old = container.querySelectorAll(".c-car-title.c-link.c-link--gray")
  284. if (old.length)
  285. {
  286. // сразу отписываемся от авто
  287. console.log('обнаружена подписка на бывшее авто', car_id);
  288. car_ids.push(car_id);
  289. checked_cars++;
  290. } else {
  291. // проверяем взаимную подписку у владельца
  292. user = container.querySelectorAll("a.c-username")[0];
  293. //car_id = container.querySelectorAll("button.c-button--subs")[0].getAttribute('data-id');
  294. //check_user(user, car_id);
  295.  
  296. user_type = user.getAttribute('data-ihc-type');
  297. user_id = user.getAttribute('data-ihc-id');
  298. check_users.push({'user_type':user_type, 'user_id':user_id, 'car_id': car_id});
  299. console.log('ставим на проверку юзера ' + user_id + ' с машинкой ' + car_id);
  300. }
  301. }
  302.  
  303. // чистим страничку для загрузки новых данных и чтоб DOM дерево не разрасталось
  304. container.remove();
  305. }
  306.  
  307.  
  308. if (first && cIntervId == false)
  309. {
  310. cIntervId = setInterval(check_user, 1000);
  311. console.log('запуск проверок юзеров в крон');
  312. }
  313. }
  314.  
  315. found_cars_count = car_ids.length;
  316. show_status();
  317. }
  318.  
  319. // отписываемся от них
  320. function unSubs()
  321. {
  322. if (request_in_process)
  323. {
  324. console.log('unSubs - занято в очереди');
  325. return;
  326. }
  327.  
  328. request_in_process = true;
  329. var car_id = car_ids.pop();
  330. if (car_id)
  331. {
  332. console.log('unSubs - ' + car_id);
  333. unsubscribe_car(car_id);
  334. } else {
  335. console.log('unSubs - пусто в очереди');
  336. }
  337.  
  338. show_status();
  339. }
  340.  
  341. console.log('next btn search start');
  342. var nIntervId = setInterval(clickNext, 3000); // открываем все страницы и обрабатываем их
  343.  
  344. check_user();
  345. unSubs();