animestars Auto Helper

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

Versão de: 11/02/2025. Veja: a última versão.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         animestars Auto Helper
// @namespace    animestars.org
// @version      3.14
// @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;

const cardClasses = '.remelt__inventory-item, .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';

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;
}

function addCheckMark(element) {
    if (!element) return;
    const checkMark = document.createElement('i');
    checkMark.classList.add('fas', 'fa-check', 'div-marked');
    checkMark.style.position = 'absolute';
    checkMark.style.bottom = '5px';
    checkMark.style.left = '5px';
    checkMark.style.background = 'green';
    checkMark.style.color = 'white';
    checkMark.style.borderRadius = '50%';
    checkMark.style.padding = '5px';
    checkMark.style.fontSize = '16px';
    checkMark.style.width = '24px';
    checkMark.style.height = '24px';
    checkMark.style.display = 'flex';
    checkMark.style.alignItems = 'center';
    checkMark.style.justifyContent = 'center';
    element.classList.add('div-checked');
    if (window.getComputedStyle(element).position === 'static') {
        element.style.position = 'relative';
    }
    element.appendChild(checkMark);
}

async function iNeedCard(cardId) {
    await sleep(DELAY * 2);
    const url = '/engine/ajax/controller.php?mod=trade_ajax';
    const data = {
        action: 'propose_add',
        type: 0,
        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;
                } else {
                    DLEPush?.info(data.error);
                }
            }
            if ( data.status == 'added' ) {
                cardCounter++;
                return;
            }
            if ( data.status == 'deleted' ) {
                await iNeedCard(cardId);
                return;
            }
            cardCounter++;
        } else {
            console.error('Ошибка запроса:', response.status);
        }
    } catch (error) {
        console.error('Ошибка выполнения POST-запроса:', error);
    }
}

async function loadCard(cardId) {
    const cacheKey = 'cardId: ' + cardId;
    let card = await getCard(cacheKey) ?? {};
    if (Object.keys(card).length) {
        return card;
    }

    // console.log(`Обработка карточки с ID: ${cardId}`);
    const currentDomain = window.location.origin;
    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();
        }
        await checkGiftCard(popularityDoc); // ищем небесный камень заодно
        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');
                    await checkGiftCard(lastPageDoc); // ищем небесный камень заодно
                    popularityCount += lastPageDoc.querySelectorAll('.card-show__owner').length;
                }
            }
        }
    }

    card = {likes: likes, dislikes: dislikes, rankText: rankText, popularityCount: popularityCount, needCount: needCount, tradeCount: tradeCount};

    if (card.likes || card.dislikes) {
        await cacheCard(cacheKey, card)
    }

    return card;
}

async function updateCardInfo(cardId, element) {
    if (!cardId || !element) {
        console.log(cardId, 'updateCardInfo error');
        return;
    }
    try {
        const card = await loadCard(cardId);
        console.log(card);

        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 = card.likes && card.dislikes ? `<br>аниме: +${card.likes} / -${card.dislikes}` : '';
        icon.innerHTML = `Ранг: ${card.rankText}<br>имеют: ${card.popularityCount}<br>хотят: ${card.needCount}<br>отдают: ${card.tradeCount}` + anime;
        element.style.position = 'relative';
        element.appendChild(icon);
    } catch (error) {
        console.error(`Ошибка обработки карты ${cardId}:`, error);
        throw error;
    }
}

function clearMarkFromCards() {
    cleanByClass('div-marked');
}

function removeAllLinkIcons() {
    cleanByClass('link-icon');
}

function cleanByClass(className) {
    const list = document.querySelectorAll('.' + className);
    list.forEach(item => item.remove());
}

function getCardsOnPage() {
    return Array.from(
        document.querySelectorAll(cardClasses)
    ).filter(card => card.offsetParent !== null);
}

async function processCards() {

    if (isCardRemeltPage()) {
        const storedData = JSON.parse(localStorage.getItem('animeCardsData')) || {};
        if (Object.keys(storedData).length < 1) {
            await readyRemeltCards();
            return;
        }
    }

    removeMatchingWatchlistItems();
    removeAllLinkIcons();
    clearMarkFromCards();

    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') || card.classList.contains('remelt__inventory-item--lock')) {
            continue;
        }
        let cardId = await getCardId(card);
        if (cardId) {
            await updateCardInfo(cardId, card).catch(error => {
                console.error("Остановка из-за критической ошибки:", error.message);
                return;
            });
            addCheckMark(card);
            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')) {
        let cards = getCardsOnPage();

        document.body.appendChild(getButton('processCards', 'rocket', 37, 'Сравнить карточки', processCards));

        if (!cards.length) {
            return
        }

        if (isMyCardPage()) {
            document.body.appendChild(getButton('readyToCharge', 'circle-check', 50, '"Готов поменять" на все карточки', readyToCharge));
        }

        if (isAnimePage()) {
            document.body.appendChild(getButton('iNeedAllThisCards', 'search', 50, '"Хочу карту" на все карточки', iNeedAllThisCards));
        }

        if (isCardRemeltPage()) {
            document.body.appendChild(getButton('readyRemeltCards', 'yin-yang', 50, 'закешировать карточки', readyRemeltCards));
            const storedData = JSON.parse(localStorage.getItem('animeCardsData')) || {};
            updateButtonCounter('readyRemeltCards', Object.keys(storedData).length);
        }
    }
}

function isMyCardPage() {
    return (/^\/user\/(.*)\/cards(\/page\/\d+\/)?/).test(window.location.pathname)
}

function isCardRemeltPage() {
    return (/^\/cards_remelt\//).test(window.location.pathname)
}

function isAnimePage() {
    return $('#anime-data').length > 0;
}

async function readyRemeltCards() {
    DLEPush.info('Кеширую все карты так как иначе на этой странице не получится их определить рейтинги');
    // получить все карты пользователя и запомнить ассоциации номеров карт в локальный кеш
    const linkElement = document.querySelector('a.button.button--left-icon.mr-3');
    const href = linkElement ? linkElement.href : null;
    if (!href) {
        return;
    }
    removeMatchingWatchlistItems();
    removeAllLinkIcons();
    clearMarkFromCards();
    const cards = getCardsOnPage();
    let counter = cards.length;
    if (!counter) {
        return;
    }
    let buttonId = 'readyRemeltCards';
    startAnimation(buttonId);
    updateButtonCounter(buttonId, 0);
    await scrapeAllPages(href, buttonId);
    stopAnimation(buttonId);
}

async function scrapeAllPages(firstPageHref, buttonId) {
    const response = await fetch(firstPageHref);
    if (!response.ok) {
        throw new Error(`Ошибка HTTP: ${response.status}`);
    }
    const firstPageDoc = new DOMParser().parseFromString(await response.text(), 'text/html');
    const pagination = firstPageDoc.querySelector('#pagination');
    if (!pagination) {
        console.log('Пагинация не найдена');
        return;
    }
    let storedData = JSON.parse(localStorage.getItem('animeCardsData')) || {};
    const titleElement = firstPageDoc.querySelector('h1.secondary-title.text-center');
    if (titleElement) {
        const match = titleElement.textContent.match(/\((\d+)\s*шт\.\)/);
        const cardsCount = match ? parseInt(match[1], 10) : -1;
        if (cardsCount == Object.keys(storedData).length) {
            DLEPush.info('На данный момент в кеше карточек ровно столько же сколько в профиле пользователя');
            return;
        }
    }

    // Получаем ссылку на последнюю страницу
    const lastPageLink = pagination.querySelector('a:last-of-type');
    if (!lastPageLink) {
        console.log('Последняя страница не найдена');
        return;
    }
    const lastPageNumber = parseInt(lastPageLink.textContent.trim(), 10);
    if (isNaN(lastPageNumber)) {
        console.log('Не удалось определить номер последней страницы');
        return;
    }
    updateButtonCounter(buttonId, lastPageNumber);
    // console.log(`Обнаружено страниц: ${lastPageNumber}`);
    // clear data
    localStorage.removeItem('animeCardsData');
    storedData = JSON.parse(localStorage.getItem('animeCardsData')) || {};
    // Функция для обработки карточек на странице
    async function processCardsToLocalstorage(doc, pageNum) {
        const cards = doc.querySelectorAll('.anime-cards__item');
        cards.forEach(card => {
            const cardId = card.getAttribute('data-id');
            const ownerId = card.getAttribute('data-owner-id');
            const name = card.getAttribute('data-name');
            const rank = card.getAttribute('data-rank');
            const animeLink = card.getAttribute('data-anime-link');
            const image = card.getAttribute('data-image');
            const ownerKey = 'o_' + ownerId;
            if (!ownerId || !cardId) return;
            if (!storedData[ownerKey]) {
                storedData[ownerKey] = []; // Если ключа нет, создаем пустой массив
            }
            storedData[ownerKey].push({ cardId, name, rank, animeLink, image, ownerId });
        });
        // console.log(`Обработано ${cards.length} карточек на странице: ` + pageNum + ', всего к сохранению: ' + Object.keys(storedData).length);
    }

    async function fetchPage(url) {
        try {
            const response = await fetch(url);
            if (!response.ok) throw new Error(`Ошибка загрузки страницы ${url}`);
            return await response.text();
        } catch (error) {
            console.error(error);
            return null;
        }
    }

    processCardsToLocalstorage(firstPageDoc, 1);
    updateButtonCounter(buttonId, lastPageNumber);

    if (lastPageNumber > 1) {
        const parser = new DOMParser();
        for (let i = 2; i <= lastPageNumber; i++) {
            const pageUrl = lastPageLink.href.replace(/page\/\d+/, `page/${i}`);
            // console.log(`Загружаем страницу ${i}: ${pageUrl}`);
            const pageHTML = await fetchPage(pageUrl);
            if (pageHTML) {
                processCardsToLocalstorage(parser.parseFromString(pageHTML, 'text/html'), i);
            }
            await new Promise(resolve => setTimeout(resolve, 3000)); // Ждем 3 секунды между запросами
            updateButtonCounter(buttonId, lastPageNumber - i);
        }
    }

    // console.log('Данные сохранены в localStorage');
    localStorage.setItem('animeCardsData', JSON.stringify(storedData));
    updateButtonCounter(buttonId, Object.keys(storedData).length);

    document.body.appendChild(getButton('processCards', 'rocket', 37, 'Сравнить карточки', processCards));
    await processCards();
}

async function iNeedAllThisCards() {
    let cards = getCardsOnPage();
    DLEPush.info('Отметить "Хочу карточку" на все ' + cards.length + ' карточек на странице');

    let counter = cards.length;
    let buttonId = 'iNeedAllThisCards';
    startAnimation(buttonId);
    updateButtonCounter(buttonId, counter);
    clearMarkFromCards();

    cardCounter = 0;
    for (const card of cards) {
        if (card.classList.contains('anime-cards__owned-by-user')) {
            counter--;
            updateButtonCounter(buttonId, counter);
            continue;
        }
        let cardId = await getCardId(card);
        if (cardId) {
            await iNeedCard(cardId).catch(error => {
                console.error("Остановка из-за критической ошибки:", error.message);
                return;
            });
            addCheckMark(card);
            counter--;
            updateButtonCounter(buttonId, counter);
        } else {
            console.log(cardId, 'cardId not found');
        }
    }
    stopAnimation(buttonId);
}

async function getCardId(card) {
    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) {
        // проверяем что в локально нет такого номера
        console.log('проверка в хранилище номера карты ' + cardId);
        const cardByOwner = await getFirstCardByOwner(cardId);
        // console.log('localStorage', cardByOwner);
        if (cardByOwner) {
            cardId = cardByOwner.cardId;
        }
    }
    return cardId;
}

async function getFirstCardByOwner(ownerId) {
    const storedData = JSON.parse(localStorage.getItem('animeCardsData')) || {};
    const key = 'o_' + ownerId;

    return storedData[key] && storedData[key].length > 0 ? storedData[key][0] : null;
}

async function readyToCharge() {
    DLEPush.info('Отмечаем все карты на странице как: "Готов обменять" кроме тех что на обмене и заблокированных');
    let cards = getCardsOnPage();
    // DLEPush.info('Карт на странице: ' + cards.length);

    let counter = cards.length;
    let buttonId = 'readyToCharge';
    startAnimation(buttonId);
    updateButtonCounter(buttonId, counter);
    clearMarkFromCards();

    cardCounter = 0;
    for (const card of cards) {
        if (card.classList.contains('trade__inventory-item--lock')) {
            continue;
        }
        let cardId = await getCardId(card);
        if (cardId) {
            await readyToChargeCard(cardId);
            counter--;
            addCheckMark(card);
            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(() => {});
    };
}

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);
    });
}

async function setCache(key, data, ttlInSeconds) {
    const expires = Date.now() + ttlInSeconds * 1000; // Устанавливаем срок хранения
    const cacheData = { data, expires };
    localStorage.setItem(key, JSON.stringify(cacheData));
}

async function getCache(key) {
    const cacheData = JSON.parse(localStorage.getItem(key));
    if (!cacheData) return null; // Если данных нет
    if (Date.now() > cacheData.expires) {
        localStorage.removeItem(key); // Если срок истёк, удаляем
        return null;
    }
    return cacheData.data;
}

async function cacheCard(key, data) {
    await setCache(key, data, 86400); // Записываем данные на 24 часа (86400 секунд)
}

async function getCard(key) {
    return await getCache(key); // Записываем данные на 24 часа (86400 секунд)
}

function addClearButton() {
    const filterControls = document.querySelector('.card-filter-form__controls');
    if (!filterControls) {
        return;
    }
    const inputField = filterControls.querySelector('.card-filter-form__search');
    if (!inputField) {
        return;
    }
    const searchButton = filterControls.querySelector('.tabs__search-btn');
    if (!searchButton) {
        return;
    }
    inputField.addEventListener('keydown', function (event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            searchButton.click();
        }
    });
    const clearButton = document.createElement('button');
    clearButton.innerHTML = '<i class="fas fa-times"></i>'; // Иконка Font Awesome
    clearButton.classList.add('clear-search-btn'); // Добавляем класс для стилизации
    clearButton.style.margin = '5px';
    clearButton.style.position = 'absolute';
    clearButton.style.padding = '10px';
    clearButton.style.background = 'red';
    clearButton.style.color = 'white';
    clearButton.style.border = 'none';
    clearButton.style.cursor = 'pointer';
    clearButton.style.fontSize = '14px';
    clearButton.style.borderRadius = '5px';
    clearButton.addEventListener('click', function () {
        inputField.value = '';
        searchButton.click();
    });
    inputField.style.marginLeft = '30px';
    inputField.parentNode.insertBefore(clearButton, inputField);
}

function updateTradeLinks() {
    const match = window.location.pathname.match(/^\/cards\/(\d+)\/users\/trade\/$/);
    if (!match) {
        return;
    }

    const titleElement = document.querySelector('h2.secondary-title.text-center a[href^="/cards/"]');
    if (!titleElement) {
        return;
    }

    const cardName = titleElement.textContent.trim(); // Название карты
    const userLinks = document.querySelectorAll('a.profile__friends-item[data-user-id]');
    if (userLinks.length === 0) {
        return;
    }
    const encodedCardName = encodeURIComponent(cardName);
    userLinks.forEach(link => {
        const userHref = link.getAttribute('href');
        if (userHref) {
            const newHref = `https://asstars.tv${userHref}cards/?search=${encodedCardName}`;
            link.setAttribute('href', newHref);
        }
    });
    console.log("✅ Все ссылки обновлены!");
}

(function() {
    'use strict';

    setInterval(autoRepeatCheck, 2000);
    setInterval(startPing, 31000);
    setInterval(checkNewCard, 10000);

    addUpdateButton();
    updateTradeLinks();
    addClearButton();

    $('#tg-banner').remove();
    localStorage.setItem('notify18', 'closed');
    localStorage.setItem('hideTelegramAs', 'true');
    $('div .pmovie__related a.glav-s:first')?.click()?.remove();
})();