Greasy Fork is available in English.
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.3
// @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 timeInLastCollect = 0;
let firstBookTimestamp = null;
let minuteDelay = 5; // Delay padrão de 5 minutos
let firstBookId = 0;
let indexPeopleBloc = 0;
let fixedBookIds = [];
// 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);
if (isLastPersonInBlock && firstBookTimestamp) {
let elapsedTime = Math.floor((Date.now() - firstBookTimestamp) / 60000);
let remainingDelay = Math.max(0, minuteDelay - elapsedTime);
log(`Tempo decorrido desde o primeiro uso: ${elapsedTime} minutos.`);
log(`Delay restante para o próximo bloco: ${remainingDelay} minutos.`);
await startDelayTimer(remainingDelay);
// 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);
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, aguardar o delay
if (peopleProcessed >= bookAmount) {
log(`Esperando ${minuteDelay} minutos para processar o próximo conjunto de pessoas...`);
await startDelayTimer(minuteDelay);
peopleProcessed = 0; // Resetar o contador
timeInFirstCollect = null; // Resetar o horário inicial para o próximo bloco
}
}
}
} else {
log('Nenhuma pessoa disponível encontrada.');
}
} catch (error) {
console.error('Erro:', error);
log('Erro durante a execução do script.');
}
});
// Função para exibir o temporizador de feedback visual
async 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;
// Atualiza a mensagem do temporizador
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); // Atualiza a cada segundo
});
}
});
})();