astars.club Auto Helper

хелпер который помогает определить популярность карты на сайте astars.club

当前为 2025-01-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name astars.club Auto Helper
  3. // @namespace astars.club
  4. // @version 2.62
  5. // @description хелпер который помогает определить популярность карты на сайте astars.club
  6. // @author astars lover
  7. // @match https://astars.club/*
  8. // @license MIT
  9. // @grant none
  10.  
  11. // ==/UserScript==
  12.  
  13. const DELAY = 500; // Задержка между запросами в миллисекундах (по умолчанию 0,5 секунды) не менять чтоб не делать избыточную нагрузку на сайт
  14.  
  15. const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  16.  
  17. async function getCount(cardId, type) {
  18. let count = 0;
  19. let needResponse = await fetch(`https://astars.club/cards/${cardId}/users/${type}/`);
  20. if (needResponse.status === 502) {
  21. console.error("Ошибка 502: Остановка выполнения скриптов.");
  22. throw new Error("502 Bad Gateway");
  23. }
  24. let needHtml = '';
  25. let needDoc = '';
  26. if (needResponse.ok) {
  27. needHtml = await needResponse.text();
  28. needDoc = new DOMParser().parseFromString(needHtml, 'text/html');
  29. count = needDoc.querySelectorAll('.profile__friends-item').length;
  30. } else {
  31. return count;
  32. }
  33.  
  34. const pagination = needDoc.querySelector('.pagination__pages');
  35. if (pagination && count >= 50) {
  36. const lastPageNum = pagination.querySelector('a:last-of-type');
  37. const totalPages = lastPageNum ? parseInt(lastPageNum.innerText, 10) : 1;
  38. if (totalPages > 1) {
  39. count = (totalPages - 1) * 50;
  40. }
  41. needResponse = await fetch(`https://astars.club/cards/${cardId}/users/${type}/page/${totalPages}`);
  42. if (needResponse.status === 502) {
  43. console.error("Ошибка 502: Остановка выполнения скриптов.");
  44. throw new Error("502 Bad Gateway");
  45. }
  46. if (needResponse.ok) {
  47. needHtml = await needResponse.text();
  48. needDoc = new DOMParser().parseFromString(needHtml, 'text/html');
  49. count += needDoc.querySelectorAll('.profile__friends-item').length;
  50. }
  51. }
  52.  
  53. return count;
  54. }
  55.  
  56. async function updateCardInfo(cardId, element) {
  57. if (!cardId || !element) {
  58. console.log(cardId, 'updateCardInfo error');
  59. return;
  60. }
  61.  
  62. try {
  63. console.log(`Обработка карточки с ID: ${cardId}`);
  64.  
  65. await sleep(DELAY);
  66.  
  67. // Получение количества "Желающих"
  68. let needCount = await getCount(cardId, 'need');
  69.  
  70. await sleep(DELAY);
  71.  
  72. // Получение количества "Готовых поменять"
  73. let tradeCount = await getCount(cardId, 'trade');
  74.  
  75. await sleep(DELAY);
  76.  
  77. // Получение популярности и ранга
  78. const popularityResponse = await fetch(`https://astars.club/cards/${cardId}/users/`);
  79. if (popularityResponse.status === 502) {
  80. console.error("Ошибка 502: Остановка выполнения скриптов.");
  81. throw new Error("502 Bad Gateway");
  82. }
  83.  
  84. let popularityCount = 0;
  85. let rankText = '';
  86. if (popularityResponse.ok) {
  87. const popularityHtml = await popularityResponse.text();
  88. const popularityDoc = new DOMParser().parseFromString(popularityHtml, 'text/html');
  89.  
  90. const rankElement = popularityDoc.querySelector('.anime-cards__rank');
  91. if (rankElement) {
  92. rankText = rankElement.textContent.trim();
  93. }
  94.  
  95. popularityCount = popularityDoc.querySelectorAll('.card-show__owner').length;
  96.  
  97. const pagination = popularityDoc.querySelector('.pagination__pages');
  98. if (pagination) {
  99. const lastPageNum = pagination.querySelector('a:last-of-type');
  100. const totalPages = lastPageNum ? parseInt(lastPageNum.innerText, 10) : 1;
  101. if (totalPages > 1 && popularityCount >= 35) {
  102. popularityCount = (totalPages - 1) * 35;
  103. const needResponse = await fetch(`https://astars.club/cards/${cardId}/users/page/${lastPageNum}`);
  104. if (needResponse.status === 502) {
  105. console.error("Ошибка 502: Остановка выполнения скриптов.");
  106. throw new Error("502 Bad Gateway");
  107. }
  108. if (needResponse.ok) {
  109. popularityCount += (new DOMParser().parseFromString(await needResponse.text(), 'text/html')).querySelectorAll('.card-show__owner').length;
  110. }
  111. }
  112. }
  113. }
  114.  
  115. // Очистка старой информации
  116. element.querySelector('.link-icon')?.remove();
  117.  
  118. // Добавление новой информации
  119. const icon = document.createElement('div');
  120. icon.className = 'link-icon';
  121. icon.style.position = 'absolute';
  122. icon.style.top = '10px';
  123. icon.style.right = '10px';
  124. icon.style.backgroundColor = 'rgba(0, 0, 0, 0.6)';
  125. icon.style.color = '#05ed5b';
  126. icon.style.padding = '5px';
  127. icon.style.borderRadius = '5px';
  128. icon.style.fontSize = '8px';
  129. icon.innerHTML = `Ранг: ${rankText}<br>Уже имеют: ${popularityCount}<br>Хотят получить: ${needCount}<br>Готовы поменять: ${tradeCount}`;
  130.  
  131. element.style.position = 'relative';
  132. element.appendChild(icon);
  133.  
  134. console.log(cardId, '- ok');
  135.  
  136. } catch (error) {
  137. console.error(`Ошибка обработки карты ${cardId}:`, error);
  138. // Остановка выполнения скриптов
  139. throw error;
  140. }
  141. }
  142.  
  143. function removeAllLinkIcons() {
  144. const linkIcons = document.querySelectorAll('.link-icon');
  145. linkIcons.forEach(icon => icon.remove());
  146. }
  147.  
  148. async function processCards() {
  149. removeAllLinkIcons();
  150.  
  151. const cards = document.querySelectorAll('.lootbox__card, .anime-cards__item, .trade__inventory-item, .trade__main-item');
  152.  
  153. console.log(cards.length, 'cards found');
  154.  
  155. for (const card of cards) {
  156.  
  157. if (card.classList.contains('trade__inventory-item--lock')) {
  158. console.log('Пропускаем карту с классом trade__inventory-item--lock');
  159. continue; // Пропускаем эту карту
  160. }
  161.  
  162. let cardId = card.getAttribute('card-id') || card.getAttribute('data-card-id') || card.getAttribute('data-id');
  163. const href = card.getAttribute('href');
  164.  
  165. if (href) {
  166. let cardIdMatch = href.match(/\/cards\/(\d+)\/users\//);
  167. console.log(cardIdMatch);
  168. if (cardIdMatch) {
  169. cardId = cardIdMatch[1];
  170. }
  171. }
  172. if (cardId) {
  173. await updateCardInfo(cardId, card).catch(error => {
  174. console.error("Остановка из-за критической ошибки:", error.message);
  175. return;
  176. });
  177. } else {
  178. console.log(cardId, 'cardId not found');
  179. console.log(card);
  180. }
  181.  
  182. if (card.classList.contains('lootbox__card')) {
  183. card.addEventListener('click', removeAllLinkIcons);
  184. }
  185. }
  186. }
  187.  
  188. function addUpdateButton() {
  189. if (!document.querySelector('#fetchLinksButton')) {
  190. const button = document.createElement('button');
  191. button.id = 'fetchLinksButton';
  192. button.innerText = 'Обновить инфу';
  193. button.style.position = 'fixed';
  194. button.style.top = '37%';
  195. button.style.right = '-50px';
  196. button.style.zIndex = '1000';
  197. button.style.backgroundColor = '#007bff';
  198. button.style.color = '#fff';
  199. button.style.border = 'none';
  200. button.style.borderRadius = '5px';
  201. button.style.padding = '10px 15px';
  202. button.style.cursor = 'pointer';
  203. button.style.boxShadow = '0 2px 5px rgba(0, 0, 0, 0.2)';
  204. button.style.transform = 'rotate(90deg)';
  205. button.addEventListener('click', processCards);
  206. document.body.appendChild(button);
  207. }
  208. }
  209.  
  210. function clearIcons() {
  211. $('.card-notification')?.first()?.click();
  212. }
  213.  
  214. function startPing() {
  215. setInterval(() => {
  216. // Получаем значение из глобальной переменной
  217. const userHash = window.dle_login_hash;
  218.  
  219. if (!userHash) {
  220. console.error("Переменная dle_login_hash не определена.");
  221. return;
  222. }
  223.  
  224. // Определяем текущий домен
  225. const currentDomain = window.location.origin;
  226.  
  227. // Формируем URL с учетом userHash
  228. const url = `${currentDomain}/engine/ajax/controller.php?mod=user_count_timer&user_hash=${userHash}`;
  229.  
  230. // Выполняем GET-запрос
  231. fetch(url)
  232. .then(response => {
  233. if (!response.ok) {
  234. throw new Error(`HTTP error! Status: ${response.status}`);
  235. }
  236. return response.json(); // Если ответ в формате JSON
  237. })
  238. .then(data => {
  239. console.log("Данные получены:", data); // Обрабатываем полученные данные
  240. })
  241. .catch(error => {
  242. console.error("Ошибка при выполнении запроса:", error);
  243. });
  244. }, 10000); // Интервал проверки — 10 сек
  245. }
  246.  
  247. function checkCard() {
  248. setInterval(() => {
  249. const today = new Date().toISOString().split('T')[0];
  250. const localStorageKey = `checkCardStopped_${today}`;
  251.  
  252. if (localStorage.getItem(localStorageKey)) {
  253. console.log("Проверка карты уже остановлена на сегодня.");
  254. return;
  255. }
  256.  
  257. // Получаем значение из глобальной переменной
  258. const userHash = window.dle_login_hash;
  259.  
  260. if (!userHash) {
  261. console.error("Переменная dle_login_hash не определена.");
  262. return;
  263. }
  264.  
  265. // Определяем текущий домен
  266. const currentDomain = window.location.origin;
  267.  
  268. // Формируем URL с учетом userHash
  269. const url = `${currentDomain}/engine/ajax/controller.php?mod=reward_card&action=check_reward&user_hash=${userHash}`;
  270. // Выполняем GET-запрос
  271. fetch(url)
  272. .then(response => {
  273. if (!response.ok) {
  274. throw new Error(`HTTP error! Status: ${response.status}`);
  275. }
  276. return response.json(); // Если ответ в формате JSON
  277. })
  278. .then(data => {
  279. if (data.stop_reward === "yes") {
  280. console.log("Проверка карт остановлена:", data.reason);
  281. localStorage.setItem(localStorageKey, "true");
  282. return;
  283. }
  284. if (!data.cards || !data.cards.owner_id) {
  285. return;
  286. }
  287. const ownerId = data.cards.owner_id;
  288. console.log("owner_id получен:", ownerId); // Выводим owner_id
  289.  
  290. const url = `${currentDomain}/engine/ajax/controller.php?mod=cards_ajax`;
  291.  
  292. // Подготавливаем параметры запроса
  293. const postData = new URLSearchParams({
  294. action: "take_card",
  295. owner_id: ownerId
  296. });
  297.  
  298. // Выполняем POST-запрос
  299. fetch(url, {
  300. method: "POST",
  301. headers: {
  302. "Content-Type": "application/x-www-form-urlencoded"
  303. },
  304. body: postData.toString() // Передаём параметры в виде строки
  305. })
  306. .then(response => {
  307. if (!response.ok) {
  308. throw new Error(`HTTP error! Status: ${response.status}`);
  309. }
  310. return response.json(); // Если ответ в формате JSON
  311. })
  312. .then(data => {
  313. console.log("Данные получены:", data); // Обрабатываем полученные данные
  314. })
  315. .catch(error => {
  316. console.error("Ошибка при выполнении запроса:", error);
  317. });
  318. })
  319. .catch(error => {
  320. console.error("Ошибка при выполнении запроса:", error);
  321. });
  322.  
  323. }, 10000); // Интервал проверки — 10 сек
  324. }
  325.  
  326. (function() {
  327. 'use strict';
  328.  
  329. setInterval(clearIcons, 2000);
  330. startPing();
  331. checkCard();
  332.  
  333. addUpdateButton();
  334. })();