您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Claim from SpeedSatoshi's faucets
当前为
// ==UserScript== // @name Rotator Speed // @namespace speed.satology // @version 1.1.4 // @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 // ==/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: 'DOGE', url: 'dogecoin.speedsatoshi.com', enabled: true }, { coin: 'TRX', url: 'tron.speedsatoshi.com', enabled: true }, { coin: 'DGB', url: 'digibyte.speedsatoshi.com', enabled: true } ]; 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 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 = '<p>Click <a href="' + landing + '/clearlog">here</a> to clear the log (only when not claiming)</p><pre style="height: 500px; position: relative; display: block; font-size: 87.5%; overflow: auto;" id="console-log"></pre><input type="checkbox" id="only-claims"><label for="only-claims">Only Claims</label>'; divElm.innerHTML = ''; faucetList.forEach( function (f, idx) { divElm.innerHTML += `<input type="checkbox" id="cbox-${f.coin}" name="coins" value="${f.coin}" ${(f.enabled ? 'checked' : '')}><label for="cbox-${f.coin}">${f.coin}</label><br>`; }); divElm.innerHTML += `<p style="text-align:justify;">First click <a href="https://ouo.io/uEK5QFX" target="_blank">here</a> 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.</p><div style="border:3px solid white;display:inline;"><button id="save-faucets" onclick="this.innerText='Saving...';">Save Faucets</button></div><br><p><a href="https://speedsatoshi.com/faucet/manual" target="_blank"><img name="btc" src="https://i.ibb.co/5WTcT60/logo.png" width="32px" height="32px"></a> - <a href="https://ethereum.speedsatoshi.com/faucet/manual" target="_blank"><img name="eth" src="https://i.ibb.co/80MLDkS/logo.png" width="32px" height="32px"></a> - <a href="https://binance-coin.speedsatoshi.com/faucet/manual" target="_blank"><img name="bnb" src="https://i.ibb.co/d2hZ16n/logo.png" width="32px" height="32px"></a> - <a href="https://bitcoin-cash.speedsatoshi.com/faucet/manual" target="_blank"><img name="bch" src="https://i.ibb.co/7zpd6yz/logo.png" width="32px" height="32px"></a> - <a href="https://litecoin.speedsatoshi.com/faucet/manual" target="_blank"><img name="ltc" src="https://i.ibb.co/VNLBwcf/logo.png" width="32px" height="32px"></a> - <a href="https://dogecoin.speedsatoshi.com/faucet/manual" target="_blank"><img name="doge" src="https://i.ibb.co/w6GPThJ/logo.png" width="32px" height="32px"></a> - <a href="https://tron.speedsatoshi.com/faucet/manual" target="_blank"><img name="trx" src="https://i.ibb.co/tPLPGkQ/logo.png" width="32px" height="32px"></a> - <a href="https://digibyte.speedsatoshi.com/faucet/manual" target="_blank"><img name="dgb" src="https://i.ibb.co/Hg1ZvJB/logo.png" width="32px" height="32px"></a></p><br><p>Click <a href="${landing}/clearlog">here</a> to clear the log (only when not claiming)</p><input type="checkbox" id="only-claims"><label for="only-claims">Only Claims</label><pre style="height: 500px; position: relative; display: block; font-size: 87.5%; overflow: auto;" id="console-log"></pre>`; 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('<br>'); // guarda en una variable todo el log, en forma de array (para separarlo en lineas en base a <br> preElm.innerHTML = window.fullLog.filter( x => x.includes('Good job')).join('<br>'); // primero filtra para tomar solo las lineas/elementos del array que tienen 'Good Job', y luego une el resultado con <br> } else { // si el checkbox no esta seleccionado preElm.innerHTML = window.fullLog.join('<br>'); // pisa el contenido de <pre> con el log entero, uniendolo con <br> para hacer los saltos de linea } }; GM_addValueChangeListener("devlog", Logger.refresh); 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('<br>'); if (document.querySelector('#only-claims').checked) { // si esta filtrando... window.fullLog = logElm.innerHTML.split('<br>'); // guarda en una variable todo el log, en forma de array (para separarlo en lineas en base a <br> logElm.innerHTML = window.fullLog.filter( x => x.includes('Good job')).join('<br>'); // primero filtra para tomar solo las lineas/elementos del array que tienen 'Good Job', y luego une el resultado con <br> } 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) { faucetList = JSON.parse(savedFaucetList); } Promise.resolve(true); } } function goNext() { let current = faucetList.findIndex( x => x.url == window.location.host ); 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() { // <p class="alert alert-info alert-padded" role="alert">Good job! You claimed 0.0000000166 BTC from the faucet.</p> 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}`); //save claimed return true; } } Logger.write(`claimedOk returning false`); return false; } function tokenError() { //<p class="alert alert-danger" role="alert">Invalid token. Refresh the page and try again.</p> 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 == window.location.host ); if (!faucetList[current].enabled) { goNext(); return; } 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( () => { 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(); } }, 10000); }); })();