// ==UserScript== // @name Rotator Speed // @namespace speed.satology // @version 1.1.9 // @author satology // @match https://*.speedsatoshi.com/faucet* // @match https://pepperlark.neocities.org/speedsatoshi.html // @match https://pepperlark.neocities.org/speedsatoshi.html/clearlog // @icon https://www.google.com/s2/favicons?sz=64&domain=speedsatoshi.com // @grant GM_setValue // @grant GM_getValue // @grant GM_addValueChangeListener // @description Claim from SpeedSatoshi's faucets // @downloadURL none // ==/UserScript== (function() { 'use strict'; const USE_LOG = true; // const TIMEOUT = 5 * 60 * 1000; const landing = 'https://pepperlark.neocities.org/speedsatoshi.html'; const wait = ms => new Promise(resolve => setTimeout(resolve, ms || 5000)); const btnSelector = '#claim'; let activation; let faucetList = [ { coin: 'BTC', url: 'www.speedsatoshi.com', enabled: true }, { coin: 'ETH', url: 'ethereum.speedsatoshi.com', enabled: true }, { coin: 'BNB', url: 'binance-coin.speedsatoshi.com', enabled: true }, { coin: 'BCH', url: 'bitcoin-cash.speedsatoshi.com', enabled: true }, { coin: 'LTC', url: 'litecoin.speedsatoshi.com', enabled: true }, { coin: 'TRX', url: 'tron.speedsatoshi.com', enabled: true }, { coin: 'DOGE', url: 'dogecoin.speedsatoshi.com', enabled: true }, { coin: 'DGB', url: 'digibyte.speedsatoshi.com', enabled: true } ]; let currentCoin = ''; let currentHost = (window.location.host == 'speedsatoshi.com' ? 'www.speedsatoshi.com' : window.location.host); let scrolled = false; let sent = false; class Logger { static log; static listening; static async write(msg) { if (!USE_LOG) { return; } if (Logger.log == []) { await Logger.load(); } if(msg) { let last = { ts: 0, msg: '' }; try { last = Logger.log[Logger.log.length - 1]; } catch (err) { } if (!last || last.msg != msg || Date.now() - last.ts > 20000) { Logger.log.push({ ts: Date.now(), msg: msg }); Logger.save(); } } } static clear() { Logger.log = []; Logger.save(); } static claimOkReader(name, old_value, new_value, remote) { if(remote) { let newClaim = JSON.parse(new_value); // hide previous claims and display the balance [...document.querySelectorAll('.coin-msg')].forEach( x => x.innerText= x.getAttribute('data-balance')); // msg holder let msgHolder = document.querySelector(`#${newClaim.coin}-msg`); if (msgHolder) { msgHolder.setAttribute('data-balance', newClaim.balance); msgHolder.innerText = newClaim.msg; } } } static refresh(name, old_value, new_value, remote) { if(remote) { Logger.log = JSON.parse(new_value); Logger.show(); } } static show() { if (!USE_LOG) { return; } if(!Logger.listening) { // document.querySelector('head').removeChild(document.querySelector('style')); let bodyElm = document.querySelector('body'); bodyElm.innerHTML = ''; let divElm = document.createElement('div'); // divElm.innerHTML = '
Click here to clear the log (only when not claiming)
'; let divHtml = 'First click here to sign up. Select the coins you want to claim, and press the button. It will only claim from selected faucets. Next, click or tap on the first faucet icon you selected.
Click here to clear the log (only when not claiming)
`; divElm.innerHTML = divHtml; bodyElm.appendChild(divElm); document.querySelector('#only-claims').onchange = function (event) { // agrega una function para cuando cambia el estado del checkbox let preElm = document.querySelector('#console-log'); // toma el elemento pre, que tiene todo el log if (event.target.checked) { // si el checkbox esta seleccionado... window.fullLog = preElm.innerHTML.split('con el log entero, uniendolo con
para hacer los saltos de linea } }; GM_addValueChangeListener("devlog", Logger.refresh); GM_addValueChangeListener("last_claim", Logger.claimOkReader); Logger.listening = true; } let logElm = document.querySelector('#console-log'); logElm.innerHTML = Logger.log.map( function (x) { let date = new Date(x.ts); return `${date.readable()} - ${x.msg}` }).join('
'); if (document.querySelector('#only-claims').checked) { // si esta filtrando... window.fullLog = logElm.innerHTML.split('
'); // guarda en una variable todo el log, en forma de array (para separarlo en lineas en base a
logElm.innerHTML = window.fullLog.filter( x => x.includes('Good job')).join('
'); // primero filtra para tomar solo las lineas/elementos del array que tienen 'Good Job', y luego une el resultado con
} logElm.scrollTop = logElm.scrollHeight; } static async load() { if (!USE_LOG) { return; } Logger.log = await GM_getValue('devlog'); if (Logger.log) { Logger.log = JSON.parse(Logger.log); } Logger.log = Logger.log ?? []; } static save() { GM_setValue('devlog', JSON.stringify(Logger.log)); } } class FaucetActivation { constructor() {} update() { let btnSave = document.querySelector('#save-faucets'); if (btnSave.innerText == 'Saving...') { let actives = [...document.getElementsByName('coins')]; actives = actives.filter(cb => cb.checked).map(cb => cb.value); faucetList.forEach( function (faucet, idx) { faucetList[idx].enabled = actives.findIndex(y => y == faucet.coin) > -1; }); this.save(); btnSave.innerText = 'Done! Please refresh'; return; } } async save() { GM_setValue('faucets', JSON.stringify(faucetList)); } async load() { let savedFaucetList = await GM_getValue('faucets'); if (savedFaucetList) { savedFaucetList = JSON.parse(savedFaucetList); faucetList.forEach( function (elm, idx) { faucetList[idx].enabled = savedFaucetList.findIndex(y => y.coin == elm.coin && y.enabled == true) > -1; }); // faucetList = JSON.parse(savedFaucetList); } Promise.resolve(true); } } function goNext() { let current = faucetList.findIndex( x => x.url == currentHost ); let nextEnabled = current + 1; while(nextEnabled < faucetList.length && !faucetList[nextEnabled].enabled) { nextEnabled++; } if(nextEnabled == faucetList.length) { nextEnabled = 0; while(nextEnabled < current && !faucetList[nextEnabled].enabled) { nextEnabled++; } } let links = document.querySelectorAll('#full td span a'); if (links.length != 8) { //something changed Logger.write(`GOTO Link not found. Using url.`); window.location.href = linkFor(faucetList[nextEnabled].url); } else { if (links.length >= nextEnabled) { links[nextEnabled].click(); Logger.write(`GOTO Link clicked`); return; } } } function linkFor(host) { return 'https://' + host + '/faucet/manual'; } function claimedOk() { //Good job! You claimed 0.0000000166 BTC from the faucet.
let elms = [...document.querySelectorAll('p.alert.alert-info.alert-padded')]; if (elms.length > 0) { let found = elms.find( x => x.innerText.includes('Good job') ); if (found) { Logger.write(`claimedOk returning true: ${found.innerText}`); // get balance let balance = document.querySelector('#balance'); balance = balance ? balance.innerText : '?'; let msg = balance ? `${found.innerText} You have ${balance} ${currentCoin}` : Logger.write(`${found.innerText}`); GM_setValue('last_claim', JSON.stringify({ coin: currentCoin, msg: msg, balance: balance})); return true; } } Logger.write(`claimedOk returning false`); return false; } function tokenError() { //Invalid token. Refresh the page and try again.
let elms = [...document.querySelectorAll('p.alert.alert-danger')]; if (elms.length > 0) { let found = elms.find( x => x.innerText.includes('Invalid token. Refresh') ); if (found) { Logger.write(`tokenError returning true: ${found.innerText}`); return true; } } Logger.write(`tokenError returning false`); return false; } async function isSolved() { Logger.write(`Waiting for captcha`); return wait().then( () => { let elm = document.querySelector('.h-captcha > iframe'); if (elm && elm.hasAttribute('data-hcaptcha-response') && elm.getAttribute('data-hcaptcha-response').length > 0) { Logger.write(`Captcha solved`); return Promise.resolve(true); } return isSolved(); }); } function scrollTo(elm) { Logger.write(`Scrolling to button`); if (typeof(elm) == 'string') { document.querySelectorAll(elm)[0].scrollIntoView(false); } else { elm.scrollIntoView(false); } } let looper, adsHandler; Logger.load().then( () => { activation = new FaucetActivation(); activation.load(); }).then( () => { if (window.location.href == landing) { Number.prototype.padIt = function () { return this.toString().padStart(2, '0'); } Date.prototype.readable = function () { return `${this.getDate().padIt()}/${(this.getMonth()+1).padIt()} ${this.getHours().padIt()}:${this.getMinutes().padIt()}:${this.getSeconds().padIt()}`; } Logger.show(); setInterval( () => { activation.update(); }, 10000); //setInterval( () => { Logger.show(); }, 15000); } else if (window.location.href == landing + '/clearlog') { document.querySelector('body').innerHTML = 'Please wait...'; Logger.clear(); setTimeout( () => { window.location.href = landing; }, 10000); } else { let current = faucetList.findIndex( x => x.url == currentHost ); if (!faucetList[current].enabled) { goNext(); return; } currentCoin = faucetList[current].coin; looper = setInterval( () => { if (claimedOk()) { Logger.write(`Moving to next faucet`); //go to next faucet clearInterval(looper); setTimeout( () => { goNext(); }, 3000); return; } if (tokenError()) { //refresh clearInterval(looper); setTimeout( () => { window.location.reload(); }, 3000); return; } if(!scrolled) { if(document.querySelector(btnSelector)) { scrollTo(btnSelector); scrolled = true; } else { Logger.write(`Claim button not found yet`); // claim button not found yet return; } } if (!sent) { clearInterval(looper); isSolved().then( () => { Logger.write(`Submiting`); document.querySelector(btnSelector).parentElement.submit(); sent = true; }); } }, 3214); } adsHandler = setInterval( () => { try { let elm = null; elm = document.querySelector('div[data-name="stitialer"]'); if (elm) { elm.nextSibling.click(); } elm = document.querySelector('.ex-over-btn'); if (elm) { elm.click(); } } catch (err) { } }, 10000); }); })();