Gotta go fast - PPM Autographs

Go, go, go, go, go, go, go Gotta go fast Gotta go fast Gotta go faster, faster, faster, faster, faster! Sonic X

// ==UserScript==
// @name        Gotta go fast - PPM Autographs
// @namespace   Violentmonkey Scripts
// @author      Drinkwater
// @license     MIT
// @match       https://*.popmundo.com/World/Popmundo.aspx/Character/Items/*
// @grant       none
// @version     1.4
// @description Go, go, go, go, go, go, go Gotta go fast Gotta go fast Gotta go faster, faster, faster, faster, faster! Sonic X
// ==/UserScript==

(function () {
    'use strict';
let timeInFirstCollect = 0;
let firstBookTimestamp = null;
let minuteDelay = 5; // Delay padrão de 5 minutos
  let remainingDelay = 0;
let firstBookId = 0;
let indexPeopleBloc = 0;
let fixedBookIds = [];
let isProcessingBlock = false; // Para evitar múltiplas chamadas ao temporizador


    // Função para coletar as pessoas dentro do contexto do iframe
    async function getPeopleToCollect(iframe) {
        let iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
        let people = [];

        let initialPeopleTable = iframeDocument.querySelector('#tablepeople');

        // Check the #ctl00_cphLeftColumn_ctl00_chkAutograph checkbox
        let autographCheckbox = iframeDocument.querySelector('#ctl00_cphLeftColumn_ctl00_chkAutograph');
        if (autographCheckbox) {
            autographCheckbox.checked = true;
        }

        // Uncheck other checkboxes
        let otherCheckboxes = [
            '#ctl00_cphLeftColumn_ctl00_chkOnline',
            '#ctl00_cphLeftColumn_ctl00_chkGame',
            '#ctl00_cphLeftColumn_ctl00_chkRelationships'
        ];

        otherCheckboxes.forEach(selector => {
            let checkbox = iframeDocument.querySelector(selector);
            if (checkbox && checkbox.checked) {
                checkbox.checked = false;
            }
        });

        // Trigger the filter button click
        let filterButton = iframeDocument.querySelector('#ctl00_cphLeftColumn_ctl00_btnFilter');
        if (filterButton) {
            filterButton.click();
        } else {
            throw new Error("Filter button not found.");
        }

        // Check every second if the people table has updated
        return new Promise((resolve) => {
            let interval = setInterval(() => {
                let newIframeDocument = iframe.contentDocument || iframe.contentWindow.document;
                let newPeopleTable = newIframeDocument.querySelector('#tablepeople');

                if (newPeopleTable && newPeopleTable !== initialPeopleTable) {
                    clearInterval(interval); // Stop checking

                    // Collect data from the new table
                    Array.from(newPeopleTable.querySelectorAll('tbody tr')).forEach(row => {
                        let characterLink = row.querySelector('a');
                        let statusText = row.querySelectorAll('td')[1]?.textContent.trim();
                        let status = (!statusText || statusText === "Online") ? "Disponível" : "Ocupado";

                        if (status === "Disponível" && characterLink) {
                            people.push({
                                name: characterLink.textContent,
                                id: characterLink.href.split('/').pop(),
                                status: status
                            });
                        }
                    });

                    resolve(people); // Resolve the Promise with available people
                }
            }, 1000);
        });
    }


    // Função para criar o iframe e garantir que ele esteja completamente carregado
    async function createIframe() {
        let domain = window.location.hostname;
        let path = '/World/Popmundo.aspx/City/PeopleOnline/';
        let url = 'https://' + domain + path;

        // Cria o iframe
        let iframe = document.createElement('iframe');
        iframe.src = url;
        iframe.style.display = 'none';
        document.body.appendChild(iframe);

        // Retorna o iframe, mas garante que ele esteja carregado antes de usá-lo
        return new Promise((resolve, reject) => {
            iframe.onload = function () {
                resolve(iframe);
            };
            iframe.onerror = function () {
                reject('Erro ao carregar o iframe');
            };
        });
    }

    // Função para logar dados
    let LOG_INDEX = 0;
    function log(data) {
        if (window.parent === window) {
            jQuery("#logs-autografos").append(`<tr class="${LOG_INDEX % 2 == 0 ? "odd" : "even"}"><td>${data}</td></tr>`);
            LOG_INDEX++;
        }
    }


    async function goToLocation(iframe, charId, charName) {
        let iframeActualHost = iframe.contentWindow.location.host;
        let domain = iframeActualHost;
        let path = `/World/Popmundo.aspx/Character/${charId}`;
        let url = 'https://' + domain + path;

        // Carrega a primeira URL e espera carregar
        iframe.src = url;
        await waitForIframeLoad(iframe);

        let iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

        // Tenta acessar o link de interação
        let locationLink = iframeDocument.querySelector('#ctl00_cphRightColumn_ctl00_lnkInteract')?.href || iframeDocument.querySelector('#ctl00_cphRightColumn_ctl00_btnInteract')?.href;
        if (!locationLink) {
            let characterPresentation = iframeDocument.querySelector('.characterPresentation');
            if (characterPresentation) {
                let links = characterPresentation.querySelectorAll('a');
                if (links.length > 0) {
                    let lastLink = links[links.length - 1];
                    let href = lastLink.getAttribute('href');
                    let locationId = href.split('/').pop();
                }
                if (!locationId) {
                    log(`Talvez ${charName} não está mais na cidade, ou algo aconteceu!`);
                    return;
                }
                locationLink = `https://${domain}/World/Popmundo.aspx/Locale/MoveToLocale/${locationId}/${charId}`;
            }
        }

        // Remove o domínio, mantendo apenas a parte a partir de /World/
        let relativePath = locationLink.includes('/World/') ? locationLink.split('/World/')[1] : null;
        if (!relativePath) {
            log('Algo de errado não está certo! Mas continuamos !');
            return;
        }

        // Cria a nova URL com o caminho relativo
        let newUrl = 'https://' + iframe.contentWindow.location.host + '/World/' + relativePath;
        log(`Movendo até o local de <b>${charName}</b>`);
        iframe.src = newUrl;

        // Aguarda o segundo carregamento do iframe
        await waitForIframeLoad(iframe);
    }

    // Função para aguardar o carregamento do iframe
    function waitForIframeLoad(iframe) {
        return new Promise((resolve) => {
            iframe.onload = function () {
                resolve();
            };
        });
    }

async function getBookIds(iframe, person) {
    let iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
    let bookIds = [];

    let select = jQuery(iframeDocument).find('#ctl00_cphTopColumn_ctl00_ddlUseItem');
    if (select.length === 0) {
        log(`Aparentemente <b>${person.name}</b> não está mais disponível ou não deixa usar itens`);
        await new Promise(resolve => setTimeout(resolve, 1000));
        return [];
    }

    jQuery(iframeDocument).find('#ctl00_cphTopColumn_ctl00_ddlUseItem option').each(function () {
        let optionText = jQuery(this).text().trim();
        let optionValue = jQuery(this).val();

        if (optionText === 'Livro de autógrafos' || optionText === 'Autograph book') {
            bookIds.push(optionValue);

            if (firstBookId === 0) {
                firstBookId = optionValue;
            }
        }
    });

    return bookIds;
}



async function collectAutograph(iframe, bookId, person, isLastPersonInBlock = false) {
    let iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

    let select = iframeDocument.querySelector('#ctl00_cphTopColumn_ctl00_ddlUseItem');
    if (!select || select.length === 0) {
        return;
    }
    select.value = bookId;

    if (bookId === firstBookId && !firstBookTimestamp) {
        firstBookTimestamp = Date.now();
        log(`Primeiro uso do livro às: ${new Date(firstBookTimestamp).toLocaleTimeString()}`);
    }

    let submitButton = iframeDocument.querySelector('#ctl00_cphTopColumn_ctl00_btnUseItem');
    if (!submitButton) {
        log(`Não foi possível encontrar o botão de uso do item para <b>${person.name}</b>`);
        return;
    }

    submitButton.click();
    await waitForIframeLoad(iframe);

    // Na última pessoa, calcular o delay restante baseado no primeiro uso do livro
    if (isLastPersonInBlock && firstBookTimestamp) {
        let elapsedTime = Math.floor((Date.now() - firstBookTimestamp) / 60000);
        remainingDelay = Math.max(0, minuteDelay - elapsedTime);  // Armazenar o delay calculado

        log(`Tempo decorrido desde o primeiro uso: ${elapsedTime} minutos.`);
        log(`Delay restante para o próximo bloco: ${remainingDelay} minutos.`);

        if (!isProcessingBlock) {
            isProcessingBlock = true;  // Prevenir múltiplas chamadas
            await startDelayTimer(remainingDelay);  // Usar o delay atualizado
            isProcessingBlock = false;
        }

        // Resetar o timestamp para o próximo bloco
        firstBookTimestamp = null;
    }
}

function startDelayTimer(minutes) {
    let timerMessage = jQuery('#timer-message');
    let totalSeconds = minutes * 60;

    return new Promise((resolve) => {
        const interval = setInterval(() => {
            let minutesLeft = Math.floor(totalSeconds / 60);
            let secondsLeft = totalSeconds % 60;

            timerMessage.text(`Esperando: ${minutesLeft} minutos e ${secondsLeft} segundos restantes...`);

            if (totalSeconds <= 0) {
                clearInterval(interval);
                timerMessage.text('Continuando a coleta de autógrafos...');
                setTimeout(() => timerMessage.text(''), 2000); // Limpa a mensagem após 2 segundos
                resolve();
            }

            totalSeconds--;
        }, 1000);
    });
}



    jQuery(document).ready(function () {
        jQuery('#checkedlist').before('<div class="box" id="autografos-box"><h2>Coletar Autógrafos</h2></div>');
        jQuery('#autografos-box').append('<p>O script usará todos os livros do seu inventário, para coletar autógrafos de popstars presentes na cidade!</p>');
        jQuery('#autografos-box').append('<p class="actionbuttons"> <input type="button" name="btn-iniciar-coleta" value="Iniciar" id="inicar-coleta" class="rmargin5"></p>');
        jQuery('#autografos-box').append('<div id="timer-message" style="font-weight: bold; color: red;"></div>');
        jQuery('#autografos-box').append('<table id="logs-autografos" class="data dataTable"></table>');
        jQuery('#logs-autografos').append('<tbody><tr><th>Logs</th></tr></tbody>');

        let bookAmount;
        const bookElement = jQuery('#checkedlist a:contains("Livro de autógrafos")');
        if (bookElement.length > 0) {
            const bookQuantity = bookElement.closest('td').find('em').text().trim();
            if (bookQuantity.startsWith('x')) {
                bookAmount = parseInt(bookQuantity.substring(1));
                log(`Quantidade de livros de autógrafos encontrada: ${bookAmount}`);
            } else {
                log('Nenhuma quantidade de livros de autógrafos encontrada.');
            }
        } else {
            log('Nenhum Livro de autógrafos encontrado.');
        }


let bookIndex = 0; // Inicia o índice do livro

jQuery('#inicar-coleta').click(async function () {
        try {
            jQuery('#inicar-coleta').prop('disabled', true);
            jQuery('#inicar-coleta').prop('value', 'Coletando Autografos...');
            let iframe = await createIframe();
            let peopleAvailable = await getPeopleToCollect(iframe);

            if (peopleAvailable.length > 0) {
                let peopleProcessed = 0;

                for (const person of peopleAvailable) {
                    await goToLocation(iframe, person.id, person.name);
                    let bookIds = await getBookIds(iframe, person);

                    if (bookIds.length > 0) {
                        log(`Coletando autógrafo de <b>${person.name}</b> usando livro ID: ${bookIds[bookIndex]}`);

                        // Verifica se é a última pessoa do bloco para checar o delay
                        let isLastPersonInBlock = (peopleProcessed + 1 === bookAmount);
                        await collectAutograph(iframe, bookIds[bookIndex], person, isLastPersonInBlock);

                        bookIndex = (bookIndex + 1) % bookIds.length;
                        peopleProcessed++;

                        // Se processarmos bookAmount de pessoas, usar o `remainingDelay`
                        if (peopleProcessed >= bookAmount && !isProcessingBlock) {
                            log(`Esperando ${remainingDelay} minutos para processar o próximo conjunto de pessoas...`);
                            await startDelayTimer(remainingDelay);  // Usar o delay calculado
                            peopleProcessed = 0; // Resetar o contador
                        }
                    }
                }
            } else {
                log('Nenhuma pessoa disponível encontrada.');
            }
        } catch (error) {
            console.error('Erro:', error);
            log('Erro durante a execução do script.');
        }
    });
    });

})();