Skip to content

Instantly share code, notes, and snippets.

@diego-mi
Last active March 14, 2022 21:31
Show Gist options
  • Save diego-mi/453fbfcc8307e682b4d9885efa354636 to your computer and use it in GitHub Desktop.
Save diego-mi/453fbfcc8307e682b4d9885efa354636 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Zodiacs auto run race
// @namespace https://gist.github.com/diego-mi/453fbfcc8307e682b4d9885efa354636
// @version 0.12
// @description Zodiacs auto run race
// @author DiegoMi
// @match https://v2.zodiacs.me
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// Variaveis para guardar informacoes dos carros
const htmlElements = {
carListItemsElements: null
}
// Variaveis para encontrar elementos no html
const QuerySelector_CarList = '.car-list';
const QuerySelector_CarItem = `${QuerySelector_CarList} .item`;
const QuerySelector_CarSelectedExpiredMessage = `.select-car .selected .text-red`;
const QuerySelector_CarSelectedStartRaceButton = `#root > section > section > div > div > div > div > div.selected.content.mb-1.text-center.p-3.shadowed > div > div.mt-3 > div.custom-btn.btn-green`;
const QuerySelector_CarSelectedStartRaceQuickRaceButton = `#root > section > section > div > div > div > div > div.selected.content.mb-1.text-center.p-3.shadowed > div > div.mt-3 > div.custom-btn.btn-yellow`;
const QuerySelector_CarSelectedStartCheckResultButton = `#root > section > section > div > div > div > div > div > div > div.mt-3 > div`;
const QuerySelector_CarSelectedStartCheckResultQuickRaceButton = `#root > section > section > div > div > div.ant-card.ant-card-bordered.select-car > div > div > div > div.mt-3 > div.custom-btn.btn-yellow.mt-3`;
const QuerySelector_CarSelectedRacesCounter = `#root > section > section > div > div > div > div > div.selected.content.mb-1.text-center.p-3.shadowed > div > div.d-flex.d-row > div:nth-child(2) > div:nth-child(4)`;;
const QuerySelector_CarSelectedStars = `#root > section > section > div > div > div.ant-card.ant-card-bordered.select-car > div > div > div > div.d-flex.d-row > div:nth-child(2) > div:nth-child(2) > span svg`;
const QuerySelector_ModalQuickRaceConfirmButton = `body > div:nth-child(7) > div > div.ant-modal-wrap.ant-modal-confirm-centered.ant-modal-centered > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button.ant-btn.ant-btn-success`;
const QuerySelector_ModalQuickRaceResultButton = `/html/body/div/section/section/div/div/div/div/div/div/div[4]/div`;
const QuerySelector_ModalResult = `body > div:nth-child(7) > div > div.ant-modal-wrap.ant-modal-confirm-centered.ant-modal-centered > div > div.ant-modal-content > div > div`;
const QuerySelector_ModalResultQuickRace = `body > div:nth-child(9) > div > div.ant-modal-wrap.ant-modal-confirm-centered.ant-modal-centered > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button`;
const QuerySelector_ModalResultClaimButton = `${QuerySelector_ModalResult} .ant-btn-success`;
const QuerySelector_ModalResultClaimQuickRaceButton = `body > div:nth-child(7) > div > div.ant-modal-wrap.ant-modal-confirm-centered.ant-modal-centered > div > div.ant-modal-content > div > div > div.ant-modal-confirm-btns > button > span`;
const QuerySelector_AmountCoin = `#root > section > header > div > div > div:nth-child(1) > span > b`;
let amountCoinInitial = 0;
let amountCoinInitialCurrentCar = 0;
let carsResult = [];
let currentCar = null;
const delayDefault = 50;
const delayDefaultRace = 28000;
let maxRacePerDay = 0;
const runAsQuickRace = true;
/**
* HELPERS
*/
async function WaitForElement(selector) {
while (document.querySelector(selector) === null) {
await new Promise( resolve => requestAnimationFrame(resolve) )
}
await new Promise(resolve => setTimeout(resolve, delayDefault));
return document.querySelector(selector);
}
async function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
function CarResult (carIndex, starsCar = 1) {
this.index = carIndex;
this.amountEarned = 0;
this.stars = starsCar;
this.races = 0;
this.expired = false;
this.raced = false;
this.addRace = () => this.races++;
this.setStars = function (stars) { this.stars = stars;}
this.setIndex = function (index) { this.index = index;}
this.setAmountEarned = function (amountEarned) { this.amountEarned = amountEarned;}
this.setAsExpired = function () { this.expired = true;}
this.setAsRaced = function () { this.raced = true;}
}
const GetRealIndex = (carIndex) => carIndex + 1;
/**
* END HELPERS
*/
async function GetAmoutCoinInitial () {
await WaitForElement(QuerySelector_AmountCoin);
amountCoinInitial = document.querySelector(QuerySelector_AmountCoin).textContent;
}
async function GetAmoutCoinInitialCurrentCar (carIndex) {
await WaitForElement(QuerySelector_AmountCoin);
amountCoinInitialCurrentCar = document.querySelector(QuerySelector_AmountCoin).textContent;
}
async function GetAmoutCoinFinal () {
await WaitForElement(QuerySelector_AmountCoin);
const amount = document.querySelector(QuerySelector_AmountCoin).textContent;
alert(`Amount earned: ${amountCoinInitial - amount}`);
}
async function GetAmoutCoinFinalCurrentCar (carIndex) {
await WaitForElement(QuerySelector_AmountCoin);
const amount = document.querySelector(QuerySelector_AmountCoin).textContent;
const amountEarned = amount - amountCoinInitialCurrentCar;
currentCar.setAmountEarned(amountEarned);
}
async function GetStarsCarSelected () {
const stars = document.querySelectorAll(QuerySelector_CarSelectedStars);
currentCar.setStars(stars.length);
}
async function GetCars () {
await WaitForElement(QuerySelector_CarItem);
htmlElements.carListItemsElements = document.querySelectorAll(QuerySelector_CarItem);
if (htmlElements.carListItemsElements.length === 0) return console.log("Car Items not found");
return console.log(`Car Items found: ${htmlElements.carListItemsElements.length}`);
}
async function DoRaces() {
for(let carIndex = 0; carIndex < htmlElements.carListItemsElements.length; carIndex++) {
currentCar = new CarResult(carIndex);
await selectCarListItemByIndex(carIndex);
await GetStarsCarSelected();
await getMaxRaceCount();
if (await isCarExpiredByIndex(carIndex)) {
currentCar.setAsExpired();
} else {
await DoAllRacesOfCarByIndex(carIndex);
await delay(delayDefault);
}
await GetAmoutCoinFinalCurrentCar();
carsResult.push(currentCar);
await AddHtml();
}
}
async function getMaxRaceCount() {
const raceInformationText = document.querySelector(QuerySelector_CarSelectedRacesCounter).textContent;
const splitedString = raceInformationText.split('/');
maxRacePerDay = splitedString[1];
}
async function DoAllRacesOfCarByIndex(carIndex) {
await GetAmoutCoinInitialCurrentCar(carIndex);
const racesCount = runAsQuickRace ? 1 : maxRacePerDay;
for(let raceCount = 0; raceCount <= racesCount; raceCount++) {
if (await isCarRacedByIndex(carIndex)) {
currentCar.setAsRaced();
await AddHtml();
break;
} else {
await DoRaceByIndex(carIndex);
await GetCars();
await selectCarListItemByIndex(carIndex);
}
}
console.log(`carsResult`, carsResult);
}
async function DoRaceByIndex(carIndex) {
await startRace();
await waitForResult();
await checkResult();
await waitForModalResult();
await claimResult();
currentCar.addRace();
await delay(delayDefault * 2);
}
async function selectCarListItemByIndex(carIndex) {
htmlElements.carListItemsElements[carIndex].click();
await delay(delayDefault);
}
async function isCarExpiredByIndex(carIndex) {
return document.querySelector(QuerySelector_CarSelectedExpiredMessage) !== null;
}
async function isCarRacedByIndex() {
return document.querySelector(QuerySelector_CarSelectedRacesCounter).textContent.indexOf(`${maxRacePerDay}/${maxRacePerDay}`) > -1;
}
async function startRace() {
runAsQuickRace ? await startRaceQuickRace() : await startRaceDefault();
}
async function startRaceDefault() {
document.querySelector(QuerySelector_CarSelectedStartRaceButton).click();
}
async function startRaceQuickRace() {
console.log('startRaceQuickRace');
document.querySelector(QuerySelector_CarSelectedStartRaceQuickRaceButton).click();
await delay(300);
await WaitForElement(QuerySelector_ModalQuickRaceConfirmButton);
document.querySelector(QuerySelector_ModalQuickRaceConfirmButton).click();
await delay(600);
}
async function waitForResult() {
await delay(300);
runAsQuickRace ? await waitForResultQuickRace() : await waitForResultDefault();
await delay(300);
}
async function waitForResultDefault() {
await delay(delayDefaultRace);
await WaitForElement(QuerySelector_CarSelectedStartCheckResultButton);
}
async function waitForResultQuickRace() {
console.log('waitForResultQuickRace');
await delay(600);
await WaitForElement(QuerySelector_CarSelectedStartCheckResultQuickRaceButton);
}
async function checkResult() {
runAsQuickRace ? await checkResultQuickRace() : await checkResultDefault();
}
async function checkResultDefault() {
try {
await delay(delayDefault);
document.querySelector(QuerySelector_CarSelectedStartCheckResultButton).click();
} catch(e) {
await waitForResult();
await checkResult();
}
}
async function checkResultQuickRace() {
console.log('checkResultQuickRace');
try {
await delay(delayDefault * 2);
document.querySelector(QuerySelector_CarSelectedStartCheckResultQuickRaceButton).click();
} catch(e) {
console.log('checkResultQuickRace error', e);
await waitForResult();
await checkResult();
}
}
async function waitForModalResult() {
runAsQuickRace ? await waitForModalResultQuickRace() : await waitForModalResultDefault();
}
async function waitForModalResultDefault() {
await WaitForElement(QuerySelector_ModalResult);
}
async function waitForModalResultQuickRace() {
await WaitForElement(QuerySelector_ModalResultClaimQuickRaceButton);
}
async function claimResult() {
runAsQuickRace ? await claimResultQuickRace() : await claimResultDefault();
}
async function claimResultDefault() {
await delay(delayDefault);
document.querySelector(QuerySelector_ModalResultClaimButton).click();
}
async function claimResultQuickRace() {
console.log('claimResultQuickRace');
await delay(300);
document.querySelector(QuerySelector_ModalResultClaimQuickRaceButton).click();
await delay(delayDefault * 4);
console.log('claimedResultQuickRace');
}
async function AddHtml() {
try {
var rowRemove = document.querySelector(".result-list");
rowRemove.remove();
} catch (e) {
}
const row = document.createElement('div');
row.classList.add('ant-row', 'result-list');
const rowTitle = document.createElement('h2');
rowTitle.classList.add('text-orange','ant-col', 'ant-col-24');
rowTitle.textContent = `Your Results`;
row.appendChild(rowTitle);
const div1 = document.createElement('div');
div1.classList.add('ant-col','ant-col-10','p-3');
const div2 = document.createElement('div');
div2.classList.add('ant-card','ant-card-bordered','my-car','text-center');
const div3 = document.createElement('div');
div3.classList.add('ant-card-body');
const div4 = document.createElement('div');
div4.classList.add('user-car','text-center');
const div5 = document.createElement('div');
div5.classList.add('content','attrs','mt-3','shadowed');
carsResult.forEach(async (item, index) => {
div5.appendChild(await AddText(`Car ${GetRealIndex(index)} ${item.stars}stars races ${item.races}/${maxRacePerDay} earned:`, `${parseFloat(item.amountEarned).toFixed(2)}`));
})
div4.appendChild(div5);
div3.appendChild(div4);
div2.appendChild(div3);
div1.appendChild(div2);
row.appendChild(div1);
document.querySelector('.main-content').prepend(row);
}
async function AddText(title, text) {
const divContent = document.createElement('div');
divContent.classList.add('d-flex','justify-content-between');
const spanTitle = document.createElement('span');
spanTitle.innerHTML = title;
const spanText = document.createElement('span');
spanText.textContent = text ;
divContent.appendChild(spanTitle);
divContent.appendChild(spanText);
return divContent;
}
/**
* INICIALIZACAO
*/
async function Init() {
await GetCars();
await GetAmoutCoinInitial();
await DoRaces();
await GetAmoutCoinFinal();
console.log(`carsResult`, carsResult);
}
Init();
})();
@diego-mi
Copy link
Author

v0.2 - corrigido bug que nao esperava a conclusao da corrida

@diego-mi
Copy link
Author

v0.3

  • corrigido dependencia do ingles para recuperar quantas corridas o carro fez
  • adicionado forma de recuperar pela tela a quantidade de corridas

@diego-mi
Copy link
Author

v0.4~v0.8

  • Adicionado forma de mostrar os resultados por carros
  • Melhorado gestao de espera de "aparecimento" de html na tela para diminuir o tempo total gasto
  • Fix: bug que nao esperava a corrida acontecer e ja tentava verificar o resultado causando erro e para total do script
  • Fix: atualizacao pos lançamento do quick race que confundia o bot pois o botao de quick race tem mesma .class do verificar resultado

@diego-mi
Copy link
Author

v.10 adicionado quick-race como opção alterando a variavel runAsQuickRace

@diego-mi
Copy link
Author

v.11

  • fix bug de pular log do primeiro carro
  • melhorado gestao de espera por elemento no quick-race

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment