Загрузка...

Market Utility Js script to automatically determine the convertibility of telegrams of gifts on the market

Thread in Extentions created by интернетангел Apr 13, 2025. (bumped Apr 24, 2025) 269 views

  1. интернетангел
    интернетангел Topic starter Apr 13, 2025 6 Mar 26, 2025
    Hey cuties! :duckwave:

    Во время продаже/покупки телеграм аккаунтов, полезно знать, возможно ли конвертировать подарки в звёзды. Телеграм запрещает конвертацию подарка в звёзды после 1 недели (7 дней) и из-за этого приходится считать, прошла ли неделя с даты получения подарка.

    С помощью моего скрипта подсчет будет происходить автоматом, и будет показыватся маленькая табличка снизу (смотреть фото)
    [IMG]


    1. Качаем расширение Tampermonkey с офицального сайта

    2. Копируем данный код:

    JS
    // ==UserScript==
    // @name LZT Market Gifts Checker
    // @namespace http://tampermonkey.net/
    // @version 1.7
    // @description Показывает информацию о возможности продажи подарков на LZT Market
    // @author [USER=9176347]интернетангел[/USER]
    // @match https://lzt.market/*
    // @icon [URL]https://www.google.com/s2/favicons?sz=64&domain=lzt.market[/URL]
    // @grant none
    // @run-at document-end
    // ==/UserScript==

    (function () {
    'use strict';

    const debug = false;

    function log(...args) {
    if (debug) {
    console.log(...args);
    }
    }

    log('[Telegram Gift Checker] Скрипт запущен');

    const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
    const processed = new Set();
    const processedGiftBlocks = new Set();

    const POSSIBLE_CARD_SELECTORS = [
    '.marketIndexItem',
    '.block-body .structItem',
    '.structItem--market',
    '.market-item',
    '[id^="marketItem--"]',
    '.market-list-item',
    '.account-item',
    '.structItem--item'
    ];

    const months = {
    'янв': 0, 'января': 0,
    'фев': 1, 'февраля': 1,
    'мар': 2, 'марта': 2,
    'апр': 3, 'апреля': 3,
    'май': 4, 'мая': 4,
    'июн': 5, 'июня': 5,
    'июл': 6, 'июля': 6,
    'авг': 7, 'августа': 7,
    'сен': 8, 'сентября': 8,
    'окт': 9, 'октября': 9,
    'ноя': 10, 'ноября': 10,
    'дек': 11, 'декабря': 11
    };

    const styles = `
    .gift-sell-status {
    display: block;
    text-align: center;
    padding: 4px;
    margin-top: 5px;
    border-radius: 4px;
    font-weight: bold;
    font-size: 12px;
    margin: 5px 0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    }
    .gift-sell-status.can-sell {
    background-color: rgba(0, 200, 0, 0.1);
    color: #00c000;
    }
    .gift-sell-status.cannot-sell {
    background-color: rgba(255, 0, 0, 0.1);
    color: #ff0000;
    }
    `;

    function injectStyles() {
    const styleEl = document.createElement('style');
    styleEl.textContent = styles;
    document.head.appendChild(styleEl);
    log('[Telegram Gift Checker] Стили добавлены');
    }

    function querySelectorMultiple(parent, selectors) {
    for (const selector of selectors) {
    const elements = parent.querySelectorAll(selector);
    if (elements && elements.length > 0) {
    log(`[Telegram Gift Checker] Найдены элементы по селектору: ${selector}`);
    return elements;
    }
    }
    return [];
    }

    function extractProductId(card) {
    if (card.id) {
    const match = card.id.match(/(?:marketItem--|item-|market-)(\d+)/);
    if (match && match[1]) return match[1];
    }

    const link = card.querySelector('a[href*="/market/"], a[href*="/accounts/"], a[href*="/item/"]');
    if (link) {
    const href = link.getAttribute('href');
    const match = href.match(/\/(\d+)\/?$/);
    if (match && match[1]) return match[1];
    }

    if (card.dataset.marketId) return card.dataset.marketId;
    if (card.dataset.itemId) return card.dataset.itemId;

    const anyLink = card.querySelector('a[href*="/"]');
    if (anyLink) {
    const href = anyLink.getAttribute('href');
    const match = href.match(/\/(\d+)\/?(?:\?|$)/);
    if (match && match[1]) return match[1];
    }

    return null;
    }

    function parseDate(title) {
    try {
    const regex = /(\d{1,2}) ([^ ]+) (\d{4}) в (\d{2}):(\d{2})/;
    const match = title.match(regex);
    if (!match) return null;

    const [, day, monRaw, year, hour, minute] = match;
    const mon = monRaw.toLowerCase();
    const monthNum = months[mon];
    if (monthNum === undefined) return null;

    return new Date(Date.UTC(+year, monthNum, +day, +hour - 3, +minute));
    } catch (e) {
    if (debug) console.error('[Telegram Gift Checker] Ошибка при парсинге даты:', e);
    return null;
    }
    }

    function hasNftInGiftBlock(giftBlock) {
    const textBlock = giftBlock.querySelector('.telegram_gifts_block_text');
    if (!textBlock) return false;

    const nftSpan = textBlock.querySelector('span.telegram_gifts_text_limited');
    if (!nftSpan) return false;

    return nftSpan.textContent === 'NFT';
    }

    function processGiftBlock(giftBlock, count) {
    if (!giftBlock || processedGiftBlocks.has(giftBlock)) return;

    if (!hasNftInGiftBlock(giftBlock)) {
    processedGiftBlocks.add(giftBlock);

    const existingStatus = giftBlock.querySelector('.gift-sell-status');
    if (existingStatus) {
    existingStatus.remove();
    }

    const sellStatus = document.createElement('div');
    sellStatus.className = `gift-sell-status ${count > 0 ? 'can-sell' : 'cannot-sell'}`;
    sellStatus.textContent = count > 0
    ? ` Можно продать (${count} шт.)`
    : ' Нельзя продать';

    giftBlock.appendChild(sellStatus);
    log('[Telegram Gift Checker] Индикатор добавлен к блоку подарков');
    } else {
    log('[Telegram Gift Checker] Блок содержит NFT, индикатор не добавляется');
    }
    }

    async function processAllGiftBlocks(doc = document) {
    const giftBlocks = doc.querySelectorAll('.telegram_gifts_block');
    log(`[Telegram Gift Checker] Найдено блоков подарков: ${giftBlocks.length}`);

    for (const giftBlock of giftBlocks) {
    if (processedGiftBlocks.has(giftBlock)) continue;

    const giftDates = giftBlock.querySelectorAll('.DateTime');
    log(`[Telegram Gift Checker] Найдено дат в блоке: ${giftDates.length}`);

    const now = Date.now();

    const convertibleGifts = Array.from(giftDates).filter(dt => {
    if (!dt.title && !dt.getAttribute('title')) return false;
    const titleText = dt.title || dt.getAttribute('title');
    const giftDate = parseDate(titleText);
    if (!giftDate) return false;
    return now - giftDate.getTime() <= SEVEN_DAYS_MS;
    });

    log(`[Telegram Gift Checker] Подарков, которые можно обменять: ${convertibleGifts.length}`);

    processGiftBlock(giftBlock, convertibleGifts.length);
    }
    }

    async function getConvertibleGiftsCount(url) {
    try {
    log(`[Telegram Gift Checker] Проверка подарков для ${url}`);
    const res = await fetch(url);
    const html = await res.text();
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, 'text/html');

    const giftBlocks = doc.querySelectorAll('.telegram_gifts_block');
    log(`[Telegram Gift Checker] Найдено блоков подарков на странице: ${giftBlocks.length}`);

    let allGiftDates = [];

    for (const block of giftBlocks) {
    const dates = block.querySelectorAll('.DateTime');
    allGiftDates = [...allGiftDates, ...dates];
    }

    if (allGiftDates.length === 0) {
    const allDateTimes = doc.querySelectorAll('.DateTime');
    log(`[Telegram Gift Checker] Найдено элементов .DateTime на странице: ${allDateTimes.length}`);
    allGiftDates = [...allDateTimes];
    }

    if (url === window.location.href && url.match(/\/\d+\/?$/)) {
    await processAllGiftBlocks(doc);
    }

    const now = Date.now();

    const convertibleGifts = allGiftDates.filter(dt => {
    if (!dt.title && !dt.getAttribute('title')) return false;
    const titleText = dt.title || dt.getAttribute('title');
    const giftDate = parseDate(titleText);
    if (!giftDate) return false;
    return now - giftDate.getTime() <= SEVEN_DAYS_MS;
    });

    log(`[Telegram Gift Checker] Найдено ${allGiftDates.length} подарков, из них ${convertibleGifts.length} можно обменять`);

    return convertibleGifts.length;
    } catch (e) {
    if (debug) console.error(`[Telegram Gift Checker] Ошибка при загрузке ${url}:`, e);
    return 0;
    }
    }

    async function processCard(card) {
    try {
    if (!card) {
    log('[Telegram Gift Checker] Пропуск карточки: элемент не существует');
    return;
    }

    if (card.classList.contains('PopupItemLink') && card.classList.contains('marketIndexItem')) {
    log('[Telegram Gift Checker] Пропуск карточки с классом PopupItemLink');
    return;
    }

    const productId = extractProductId(card);
    if (!productId) {
    log('[Telegram Gift Checker] Не удалось извлечь ID продукта:', card);
    return;
    }

    log(`[Telegram Gift Checker] Найден ID продукта: ${productId}`);

    if (processed.has(productId)) {
    log(`[Telegram Gift Checker] Продукт ${productId} уже обработан, пропускаем`);
    return;
    }

    processed.add(productId);
    log(`[Telegram Gift Checker] Обработка карточки ${productId}`);

    const href = `https://lzt.market/${productId}/`;
    const count = await getConvertibleGiftsCount(href);

    let giftContainer = null;
    const possibleContainers = [
    '.marketIndexItem--Bottom',
    '.structItem-cell--meta',
    '.structItem-minor',
    '.market-price',
    '.account-details',
    '.item-details',
    '.structItem-parts'
    ];

    for (const selector of possibleContainers) {
    const container = card.querySelector(selector);
    if (container) {
    giftContainer = container;
    log(`[Telegram Gift Checker] Найден контейнер по селектору: ${selector}`);
    break;
    }
    }

    if (!giftContainer) {
    log('[Telegram Gift Checker] Не найден подходящий контейнер, используем карточку');
    giftContainer = card;
    }

    const sellStatus = document.createElement('div');
    sellStatus.className = `gift-sell-status ${count > 0 ? 'can-sell' : 'cannot-sell'}`;
    sellStatus.textContent = count > 0
    ? ` Можно продать (${count} шт.)`
    : ' Нельзя продать';

    if (!giftContainer.querySelector('.gift-sell-status')) {
    giftContainer.appendChild(sellStatus);
    log(`[Telegram Gift Checker] Индикатор для ${productId} добавлен (${count > 0 ? 'можно продать' : 'нельзя продать'})`);
    } else {
    log(`[Telegram Gift Checker] Индикатор для ${productId} уже существует`);
    }
    } catch (e) {
    if (debug) console.error('[Telegram Gift Checker] Ошибка при обработке карточки:', e);
    }
    }

    async function checkAndProcessProductPage() {
    const productMatch = window.location.pathname.match(/\/(\d+)\/?$/);
    if (productMatch && productMatch[1]) {
    const productId = productMatch[1];
    log(`[Telegram Gift Checker] Обнаружена страница товара: ${productId}`);

    await processAllGiftBlocks();
    }
    }

    function observeNewCards() {
    try {
    log('[Telegram Gift Checker] Настройка наблюдателя за новыми элементами');

    const observer = new MutationObserver(mutations => {
    for (const mutation of mutations) {
    for (const node of mutation.addedNodes) {
    if (node.nodeType !== 1) continue;

    let foundCards = false;
    for (const selector of POSSIBLE_CARD_SELECTORS) {
    if (node.matches && node.matches(selector)) {
    if (node.classList.contains('PopupItemLink') && node.classList.contains('marketIndexItem')) {
    log('[Telegram Gift Checker] Пропуск новой карточки с классом PopupItemLink');
    foundCards = true;
    break;
    }

    log(`[Telegram Gift Checker] Обнаружена новая карточка с селектором ${selector}`);
    processCard(node);
    foundCards = true;
    break;
    }
    }

    if (!foundCards) {
    const newCards = querySelectorMultiple(node, POSSIBLE_CARD_SELECTORS);
    if (newCards && newCards.length) {
    log(`[Telegram Gift Checker] Обнаружено ${newCards.length} новых карточек внутри элемента`);
    for (const card of newCards) {
    if (card.classList.contains('PopupItemLink') && card.classList.contains('marketIndexItem')) {
    log('[Telegram Gift Checker] Пропуск вложенной карточки с классом PopupItemLink');
    continue;
    }
    processCard(card);
    }
    }
    }

    if (node.matches && node.matches('.telegram_gifts_block')) {
    log('[Telegram Gift Checker] Обнаружен новый блок подарков');
    processAllGiftBlocks();
    } else {
    const giftBlocks = node.querySelectorAll('.telegram_gifts_block');
    if (giftBlocks.length > 0) {
    log(`[Telegram Gift Checker] Обнаружено ${giftBlocks.length} новых блоков подарков внутри элемента`);
    processAllGiftBlocks();
    }
    }
    }
    }
    });

    observer.observe(document.body, {
    childList: true,
    subtree: true
    });

    log('[Telegram Gift Checker] Наблюдатель настроен');
    } catch (e) {
    if (debug) console.error('[Telegram Gift Checker] Ошибка при настройке наблюдателя:', e);
    }
    }

    async function processInitialCards() {
    try {
    const cards = querySelectorMultiple(document, POSSIBLE_CARD_SELECTORS);
    log(`[Telegram Gift Checker] Найдено ${cards.length} начальных карточек`);

    for (const card of cards) {
    if (card.classList.contains('PopupItemLink') && card.classList.contains('marketIndexItem')) {
    log('[Telegram Gift Checker] Пропуск начальной карточки с классом PopupItemLink');
    continue;
    }

    await processCard(card);
    await new Promise(r => setTimeout(r, 100));
    }

    log('[Telegram Gift Checker] Обработка начальных карточек завершена');
    } catch (e) {
    if (debug) console.error('[Telegram Gift Checker] Ошибка при обработке начальных карточек:', e);
    }
    }

    async function init() {
    log('[Telegram Gift Checker] Инициализация...');
    injectStyles();

    log('[Telegram Gift Checker] URL страницы:', window.location.href);

    await processAllGiftBlocks();

    if (window.location.pathname.match(/\/\d+\/?$/)) {
    await checkAndProcessProductPage();
    }

    await processInitialCards();

    observeNewCards();

    log('[Telegram Gift Checker] Инициализация завершена');

    setInterval(() => {
    processAllGiftBlocks();
    }, 5000);
    }

    setTimeout(init, 2000);

    window.addEventListener('load', () => {
    log('[Telegram Gift Checker] Событие load сработало');
    setTimeout(() => {
    processAllGiftBlocks();
    }, 1000);
    });
    })();
    3. В дешборде tampermonkey нажимаем на плюсик [IMG]

    4. Вставляем туда код

    5. Сохраняем файл (Ctrl + S)

    Готово! Теперь перейдите на страницу аккаунта телеграм и у подарков появится маленькая табличка
    Идея взята с темы https://lolz.live/threads/8549747/
     
Loading...
Top