您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
хелпер который помогает определить популярность карты на сайте astars.club
当前为
// ==UserScript== // @name animestars Auto Helper // @namespace animestars.org // @version 3.03 // @description хелпер который помогает определить популярность карты на сайте astars.club // @author astars lover // @match https://astars.club/* // @match https://asstars1.astars.club/* // @match https://animestars.org/* // @match https://as1.astars.club/* // @match https://asstars.tv/* // @license MIT // @grant none // ==/UserScript== const DELAY = 500; // Задержка между запросами в миллисекундах (по умолчанию 0,5 секунды) не менять чтоб не делать избыточную нагрузку на сайт const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); let cardCounter = 0; async function getCount(cardId, type) { // Определяем текущий домен const currentDomain = window.location.origin; let count = 0; let needResponse = await fetch(`${currentDomain}/cards/${cardId}/users/${type}/`); if (needResponse.status === 502) { console.error("Ошибка 502: Остановка выполнения скриптов."); throw new Error("502 Bad Gateway"); } let needHtml = ''; let needDoc = ''; if (needResponse.ok) { needHtml = await needResponse.text(); needDoc = new DOMParser().parseFromString(needHtml, 'text/html'); count = needDoc.querySelectorAll('.profile__friends-item').length; } else { return count; } const pagination = needDoc.querySelector('.pagination__pages'); if (pagination && count >= 50) { const lastPageNum = pagination.querySelector('a:last-of-type'); const totalPages = lastPageNum ? parseInt(lastPageNum.innerText, 10) : 1; if (totalPages > 1) { count = (totalPages - 1) * 50; } needResponse = await fetch(`${currentDomain}/cards/${cardId}/users/${type}/page/${totalPages}`); if (needResponse.status === 502) { console.error("Ошибка 502: Остановка выполнения скриптов."); throw new Error("502 Bad Gateway"); } if (needResponse.ok) { needHtml = await needResponse.text(); needDoc = new DOMParser().parseFromString(needHtml, 'text/html'); count += needDoc.querySelectorAll('.profile__friends-item').length; } } return count; } async function updateCardInfo(cardId, element) { // Определяем текущий домен const currentDomain = window.location.origin; if (!cardId || !element) { console.log(cardId, 'updateCardInfo error'); return; } try { console.log(`Обработка карточки с ID: ${cardId}`); await sleep(DELAY); // Получение количества "Желающих" let needCount = await getCount(cardId, 'need'); await sleep(DELAY); // Получение количества "Готовых поменять" let tradeCount = await getCount(cardId, 'trade'); await sleep(DELAY); // Получение популярности и ранга const popularityResponse = await fetch(`${currentDomain}/cards/${cardId}/users/`); if (popularityResponse.status === 502) { console.error("Ошибка 502: Остановка выполнения скриптов."); throw new Error("502 Bad Gateway"); } let likes = 0; let dislikes = 0; let popularityCount = 0; let rankText = ''; if (popularityResponse.ok) { const popularityHtml = await popularityResponse.text(); const popularityDoc = new DOMParser().parseFromString(popularityHtml, 'text/html'); const rankElement = popularityDoc.querySelector('.anime-cards__rank'); if (rankElement) { rankText = rankElement.textContent.trim(); } checkGiftCard(popularityDoc); // ищем небесный камень заодно // anime url const animeUrl = popularityDoc.querySelector('.card-show__placeholder')?.href; if (animeUrl) { try { const response = await fetch(animeUrl); if (!response.ok) { throw new Error(`Ошибка HTTP: ${response.status}`); } const htmlText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(htmlText, 'text/html'); likes = parseInt(doc.querySelector('[data-likes-id]')?.textContent?.trim(), 10); dislikes = parseInt(doc.querySelector('[data-dislikes-id]')?.textContent?.trim(), 10); checkGiftCard(doc); // ищем небесный камень заодно } catch (error) { console.error('Ошибка при загрузке страницы:', error); } } popularityCount = popularityDoc.querySelectorAll('.card-show__owner').length; const pagination = popularityDoc.querySelector('.pagination__pages'); if (pagination) { const lastPageNum = pagination.querySelector('a:last-of-type'); const totalPages = lastPageNum ? parseInt(lastPageNum.innerText, 10) : 1; if (totalPages > 1 && popularityCount >= 35) { popularityCount = (totalPages - 1) * 35; const needResponse = await fetch(`${currentDomain}/cards/${cardId}/users/page/${totalPages}`); if (needResponse.status === 502) { console.error("Ошибка 502: Остановка выполнения скриптов."); throw new Error("502 Bad Gateway"); } if (needResponse.ok) { const lastPageDoc = new DOMParser().parseFromString(await needResponse.text(), 'text/html'); checkGiftCard(lastPageDoc); // ищем небесный камень заодно popularityCount += lastPageDoc.querySelectorAll('.card-show__owner').length; } } } } // Очистка старой информации element.querySelector('.link-icon')?.remove(); // Добавление новой информации const icon = document.createElement('div'); icon.className = 'link-icon'; icon.style.position = 'absolute'; icon.style.top = '10px'; icon.style.right = '10px'; icon.style.backgroundColor = 'rgba(0, 0, 0, 0.6)'; icon.style.color = '#05ed5b'; icon.style.padding = '5px'; icon.style.borderRadius = '5px'; icon.style.fontSize = '8px'; const anime = likes && dislikes ? `<br>аниме: +${likes} / -${dislikes}` : ''; icon.innerHTML = `Ранг: ${rankText}<br>имеют: ${popularityCount}<br>хотят: ${needCount}<br>не хотят: ${tradeCount}` + anime; element.style.position = 'relative'; element.appendChild(icon); } catch (error) { console.error(`Ошибка обработки карты ${cardId}:`, error); // Остановка выполнения скриптов throw error; } } function removeAllLinkIcons() { const linkIcons = document.querySelectorAll('.link-icon'); linkIcons.forEach(icon => icon.remove()); } function getCardsOnPage() { return Array.from( document.querySelectorAll('.lootbox__card, .anime-cards__item, .trade__inventory-item, .trade__main-item, .card-filter-list__card, .deck__item, .history__body-item, .history__body-item, .card-show__placeholder') ).filter(card => card.offsetParent !== null); } async function processCards() { removeMatchingWatchlistItems(); removeAllLinkIcons(); const cards = getCardsOnPage(); let counter = cards.length; if (!counter) { return; } let buttonId = 'processCards'; startAnimation(buttonId); updateButtonCounter(buttonId, counter); for (const card of cards) { if (card.classList.contains('trade__inventory-item--lock')) { continue; // Пропускаем эту карту } let cardId = card.getAttribute('card-id') || card.getAttribute('data-card-id') || card.getAttribute('data-id'); const href = card.getAttribute('href'); if (href) { let cardIdMatch = href.match(/\/cards\/(\d+)\/users\//); if (cardIdMatch) { cardId = cardIdMatch[1]; } } if (cardId) { await updateCardInfo(cardId, card).catch(error => { console.error("Остановка из-за критической ошибки:", error.message); return; }); card.style.border = '2px solid ' + (card.classList.contains('anime-cards__owned-by-user') ? 'rgb(255 0 0)' : '#217412'); counter--; updateButtonCounter(buttonId, counter); } else { console.log(cardId, 'cardId not found'); } if (card.classList.contains('lootbox__card')) { card.addEventListener('click', removeAllLinkIcons); } } stopAnimation(buttonId); } function removeMatchingWatchlistItems() { const watchlistItems = document.querySelectorAll('.watchlist__item'); if (watchlistItems.length == 0) { return; } watchlistItems.forEach(item => { const episodesText = item.querySelector('.watchlist__episodes')?.textContent.trim(); if (episodesText) { const matches = episodesText.match(/[\d]+/g); if (matches) { const currentEpisode = parseInt(matches[0], 10); const totalEpisodes = parseInt(matches.length === 4 ? matches[3] : matches[1], 10); if (currentEpisode === totalEpisodes) { item.remove(); console.log(`Удалён блок: ${item}`); } } } }); if (watchlistItems.length) { DLEPush?.info('Из списка удалены просмотренные аниме. В списке осталось ' + document.querySelectorAll('.watchlist__item').length + ' записей.'); } } function startAnimation(id) { $('#' + id + ' span:first').css('animation', 'rotateIcon 2s linear infinite'); } function stopAnimation(id) { $('#' + id + ' span:first').css('animation', ''); } function getButton(id, className, percent, text, clickFunction) { const button = document.createElement('button'); button.id = id; button.title = text; button.style.position = 'fixed'; button.style.top = percent + '%'; button.style.right = '1%'; button.style.zIndex = '1000'; button.style.backgroundColor = '#007bff'; button.style.color = '#fff'; button.style.border = 'none'; button.style.borderRadius = '5px'; button.style.padding = '10px 15px'; button.style.cursor = 'pointer'; button.style.boxShadow = '0 2px 5px rgba(0, 0, 0, 0.2)'; const icon = document.createElement('span'); icon.className = 'fal fa-' + className; icon.style.display = 'inline-block'; button.appendChild(icon); const info = document.createElement('span'); info.id = id + '_counter'; info.className = 'guest__notification'; info.style.display = 'none'; button.appendChild(info); button.addEventListener('click', clickFunction); return button; } function updateButtonCounter(id, counter) { let c = $('#' + id + '_counter'); c.css('display', counter > 0 ? 'flex' : 'none'); c.text(counter); } function addUpdateButton() { if (!document.querySelector('#fetchLinksButton')) { document.body.appendChild(getButton('processCards', 'rocket', 37, 'Сравнить карточки', processCards)); let cards = getCardsOnPage(); if (cards.length && isMyCardPage()) { document.body.appendChild(getButton('readyToCharge', 'circle-check', 50, 'Готов поменять карточки', readyToCharge)); } } } function isMyCardPage() { const regex = /^\/user\/[^/\s]+\/cards(\/page\/\d+\/)?$/; return regex.test(window.location.pathname); } // Использование if (checkCurrentPage()) { console.log("Страница соответствует /user/{username}/cards/ или /user/{username}/cards/page/{num}/"); } else { console.log("Это не целевая страница."); } async function readyToCharge() { DLEPush.info('Отмечаем все карты на странице как: "Готов обменять" кроме тех что на обмене и заблокированных'); let cards = getCardsOnPage(); DLEPush.info('Карт на странице: ' + cards.length); let counter = cards.length; let buttonId = 'readyToCharge'; startAnimation(buttonId); updateButtonCounter(buttonId, counter); cardCounter = 0; for (const card of cards) { if (card.classList.contains('trade__inventory-item--lock')) { continue; } let cardId = card.getAttribute('card-id') || card.getAttribute('data-card-id') || card.getAttribute('data-id'); const href = card.getAttribute('href'); if (href) { let cardIdMatch = href.match(/\/cards\/(\d+)\/users\//); if (cardIdMatch) { cardId = cardIdMatch[1]; } } if (cardId) { await readyToChargeCard(cardId); counter--; card.style.border = '2px solid ' + (card.classList.contains('anime-cards__owned-by-user') ? 'rgb(255 0 0)' : '#217412'); updateButtonCounter(buttonId, counter); } } DLEPush.info('Отправили на обмен ' + cardCounter + ' карточек на странице'); stopAnimation(buttonId); } const readyToChargeCard = async (cardId) => { await sleep(DELAY * 2); const url = '/engine/ajax/controller.php?mod=trade_ajax'; const data = { action: 'propose_add', type: 1, card_id: cardId, user_hash: dle_login_hash }; try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams(data).toString() }); if (response.status === 502) { console.error("Ошибка 502: Остановка выполнения скриптов."); throw new Error("502 Bad Gateway"); } if (response.ok) { const data = await response.json(); if (data.error) { if (data.error == 'Слишком часто, подождите пару секунд и повторите действие') { await readyToChargeCard(cardId); return; } } if ( data.status == 'added' ) { cardCounter++; return; } if ( data.status == 'deleted' ) { await readyToChargeCard(cardId); return; } cardCounter++; //console.log('Ответ сервера:', data); } else { console.error('Ошибка запроса:', response.status); } } catch (error) { console.error('Ошибка выполнения POST-запроса:', error); } }; // Анимация вращения в CSS const style = document.createElement('style'); style.textContent = ` @keyframes rotateIcon { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; document.head.appendChild(style); function clearIcons() { $('.card-notification:first')?.click(); } function autoRepeatCheck() { clearIcons(); checkGiftCard(document); // блочим воспроизведение звуков при получении карты Audio.prototype.play = function() { return new Promise(() => {}); // Возвращаем promise, чтобы не было ошибок }; } async function checkGiftCard(doc) { const button = doc.querySelector('#gift-icon'); if (!button) return; const giftCode = button.getAttribute('data-code'); if (!giftCode) return false; try { const response = await fetch('/engine/ajax/controller.php?mod=gift_code_game', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ code: giftCode, user_hash: dle_login_hash }) }); const data = await response.json(); if (data.status === 'ok') { DLEPush.info(data.text); button.remove(); } } catch (error) { console.error('Ошибка при проверке подарочной карты:', error); } } function startPing() { // Получаем значение из глобальной переменной const userHash = window.dle_login_hash; if (!userHash) { console.error("Переменная dle_login_hash не определена."); return; } // Определяем текущий домен const currentDomain = window.location.origin; // Формируем URL с учетом userHash const url = `${currentDomain}/engine/ajax/controller.php?mod=user_count_timer&user_hash=${userHash}`; // Выполняем GET-запрос fetch(url) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.json(); // Если ответ в формате JSON }) .then(data => { // console.log("Данные получены:", data); // Обрабатываем полученные данные }) .catch(error => { console.error("Ошибка при выполнении запроса:", error); }); } function checkNewCard() { const currentDateTime = new Date(); // Получаем значение из глобальной переменной const userHash = window.dle_login_hash; if (!userHash) { console.error("Переменная dle_login_hash не определена."); return; } const localStorageKey = 'checkCardStopped' + window.dle_login_hash; // Формат YYYY-MM-DDTHH if (localStorage.getItem(localStorageKey) === currentDateTime.toISOString().slice(0, 13)) { console.log("Проверка карты уже остановлена на текущий час."); return; } // Определяем текущий домен const currentDomain = window.location.origin; // Формируем URL с учетом userHash const url = `${currentDomain}/engine/ajax/controller.php?mod=reward_card&action=check_reward&user_hash=${userHash}`; // Выполняем GET-запрос fetch(url) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.json(); // Если ответ в формате JSON }) .then(data => { if (data.stop_reward === "yes") { console.log("Проверка карт остановлена на текущий час:", data.reason); localStorage.setItem(localStorageKey, currentDateTime.toISOString().slice(0, 13)); return; } if (!data.cards || !data.cards.owner_id) { return; } const ownerId = data.cards.owner_id; console.log("owner_id получен:", ownerId); // Выводим owner_id if ( data.cards.name ) { DLEPush?.info('Получена новая карта "' + data.cards.name + '"'); } const url = `${currentDomain}/engine/ajax/controller.php?mod=cards_ajax`; // Подготавливаем параметры запроса const postData = new URLSearchParams({ action: "take_card", owner_id: ownerId }); // Выполняем POST-запрос fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: postData.toString() // Передаём параметры в виде строки }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.json(); // Если ответ в формате JSON }) .then(data => { console.log("Данные получены:", data); // Обрабатываем полученные данные }) .catch(error => { console.error("Ошибка при выполнении запроса:", error); }); }) .catch(error => { console.error("Ошибка при выполнении запроса:", error); }); } (function() { 'use strict'; setInterval(autoRepeatCheck, 2000); setInterval(startPing, 31000); setInterval(checkNewCard, 10000); addUpdateButton(); $('#tg-banner').remove(); localStorage.setItem('notify18', 'closed'); localStorage.setItem('hideTelegramAs', 'true'); $('div .pmovie__related a.glav-s:first')?.click()?.remove(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址