// ==UserScript== // @name [satology] Auto Claim Multiple Faucets with Monitor UI // @description Automatic rolls and claims for 50+ crypto faucets/PTC/miners (Freebitco.in BTC, auto promo code for 16 CryptosFaucet, FaucetPay, StormGain, etc) // @description Claim free ADA, BNB, BCH, BTC, DASH, DGB, DOGE, ETH, FEY, LINK, LTC, NEO, SHIB, STEAM, TRX, USDC, USDT, XEM, XRP, ZEC, ETC // @version 3.0.57 // @author satology // @namespace satology.onrender.com // @homepage https://criptologico.com/tools/cc // @noframes // @grant GM_info // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant window.close // @grant GM_openInTab // @grant window.onurlchange // @connect criptologico.com // @note IMPORTANT // @note - To start the script you need to navigate to https://criptologico.com/tools/cc // @note - Each schedule will open it's own tab to allow multiclaiming // @icon https://www.google.com/s2/favicons?domain=criptologico.com // @require https://cdnjs.cloudflare.com/ajax/libs/nearest-color/0.4.4/nearestColor.js // @match https://app.stormgain.com/crypto-miner/ // @match https://app.freecardano.com/* // @match https://app.freebinancecoin.com/* // @match https://app.freebitcoin.io/* // @match https://app.freedash.io/* // @match https://app.free-doge.com/* // @match https://app.freeethereum.com/* // @match https://app.freecryptom.com/* // @match https://app.free-ltc.com/* // @match https://app.freeneo.io/* // @match https://app.freesteam.io/* // @match https://app.free-tron.com/* // @match https://app.freeusdcoin.com/* // @match https://app.freetether.com/* // @match https://app.freenem.com/* // @match https://app.freeshibainu.com/* // @match https://app.coinfaucet.io/* // @match https://app.freepancake.com/* // @match https://app.freematic.com/* // @match https://app.freebittorrent.com/* // @match https://app.freebfg.com/* // @match https://freebitco.in/* // @match https://faucetpay.io/* // @match https://bigbtc.win/* // @match https://www.bestchange.com/* // @match https://faucetok.net/* // @match https://betfury.io/boxes/all* // @match https://www.free-doge.io/ // @match https://www.free-doge.io/free/ // @match https://autofaucet.dutchycorp.space/login.php* // @match https://autofaucet.dutchycorp.space/roll.php* // @match https://autofaucet.dutchycorp.space/coin_roll.php* // @match https://express.dutchycorp.space/index.php* // @match https://express.dutchycorp.space/roll.php* // @match https://express.dutchycorp.space/coin_roll.php* // @match https://faucetcrypto.com/dashboard // @match https://faucetcrypto.com/task/faucet-claim // @match https://faucetcrypto.com/ptc/* // @match https://faucetcrypto.com/task/ptc-advertisement/* // @match https://faupig-bit.online/page/dashboard* // @match https://faupig-bit.online/account/login/not-logged-in // @match https://freegridco.in/* // @match https://james-trussy.com/* // @match https://www.only1024.com/f* // @match https://criptologico.com/tools/cc* // @match https://yescoiner.com/* // @match https://coindiversity.io/* // @match https://ltcfaucet.top/* // @match https://bnbfaucet.top/* // @match https://dogecoinfaucet.top/* // @match https://tronfaucet.top/* // @match https://ethfaucet.top/* // @match https://freebch.club/* // @match https://zecfaucet.net/* // @match https://faucet.monster/* // @match https://auto-crypto.ml/* // @match https://claimclicks.com/* // @match https://cryptoclicks.net/* // @match https://freeshiba.cf/* // @match https://auto-crypto.click/* // @downloadURL https://update.greasyfork.icu/scripts/425999/%5Bsatology%5D%20Auto%20Claim%20Multiple%20Faucets%20with%20Monitor%20UI.user.js // @updateURL https://update.greasyfork.icu/scripts/425999/%5Bsatology%5D%20Auto%20Claim%20Multiple%20Faucets%20with%20Monitor%20UI.meta.js // ==/UserScript== (function() { 'use strict'; const localeConfig = { setToEnglish: true, // will set the faucets to English stringSearches: { promoCodeAccepted: 'roll', promoCodeUsed: 'already used', promoCodeInvalid: ['not found', 'only alphanumeric'], promoCodeExpired: ['ended'] } }; const STATUS = { INITIALIZING: 0, IDLE: 1, CLAIMING: 2 }; const K = Object.freeze({ WebType: { UNDEFINED: 0, CRYPTOSFAUCETS: 1, STORMGAIN: 2, FREEBITCOIN: 3, FAUCETPAY: 4, FREELITECOIN: 5, FREEETHEREUMIO: 6, BAGIKERAN: 7, OKFAUCET: 8, BIGBTC: 9, BESTCHANGE: 10, KINGBIZ: 11, BFBOX: 13, FREEDOGEIO: 14, DUTCHYROLL: 15, FCRYPTO: 16, CPU: 17, CBG: 18, FPB: 19, G8: 20, FREEGRC: 21, HELI: 22, VIE: 23, O24: 24, YCOIN: 25, CDIVERSITY: 26, BSCADS: 27, CTOP: 28, AUTOCML: 29, CCLICKS: 30 }, CF: { UrlType: { HOME: 0, FREE: 1, CONTACTTWITTER: 2, PROMOTION: 3, STATS: 4, SETTINGS: 5, FREEROLLS: 6, LOGIN: 7, GAMES: 8, IGNORE: 99 }, PromoStatus: { NOCODE: 0, PENDING: 1, ACCEPTED: 2, USEDBEFORE: 3, INVALID: 4, UNKNOWNERROR: 5, EXPIRED: 6 }, }, RandomInteractionLevel: { NONE: 0, LOW: 1, MEDIUM: 2, HIGH: 3 }, Integers: { HS_26_IN_MILLISECONDS: 93600000, //Using 26 hs instead of 24hs HS_2_IN_MILLISECONDS: 7200000 //and 2hs gap retry when code is flagged as USEDBEFORE }, WalletType: { FP_USERNAME: 99, FP_MAIL: 100, FP_BTC: 101, FP_BNB: 102, FP_BCH: 103, FP_DASH: 104, FP_DGB: 105, FP_DOGE: 106, FP_ETH: 107, FP_FEY: 108, FP_LTC: 109, FP_TRX: 110, FP_USDT: 111, FP_ZEC: 112, FP_SOL: 113, FP_MATIC: 114, FP_XRP: 115, FP_ADA: 116, EC: 200, BTC: 1, LTC: 2 }, ErrorType: { ERROR: 0, TIMEOUT: 1, NEED_TO_LOGIN: 2, ROLL_ERROR: 3, CLICK_ROLL_ERROR: 4, LOGIN_ERROR: 5, CLAIM_ERROR: 6, ADDRESS_ERROR: 7, MIN_WITHDRAW_ERROR: 8, IP_BAN: 9, IP_RESTRICTED: 10, IP_ERROR: 11, FORCE_CLOSED: 12, NO_FUNDS: 13, VERIFY_EMAIL: 14, NO_ADDRESS: 15, FAUCET_EMPTY: 16 }, CMC: { MULT: '-1', BTC: '1', LTC: '2', XRP: '52', DOGE: '74', DGB: '109', DASH: '131', USDT: '825', XEM: '873', ETH: '1027', STEEM: '1230', NEO: '1376', ZEC: '1437', BCH: '1831', BNB: '1839', TRX: '1958', LINK: '1975', ADA: '2010', USDC: '3408', SOL: '5426', SHIB: '5994', FEY: '10361', BFG: '11038', CAKE: '7186', GRC: '833', MATIC: '3890', BABY: '10334', BTT: '16086', BSW: '10746', }, LOCATION: { UNKNOWN: 0, MANAGER: 1, SITE: 2 } }); let persistence, shared, manager, ui, CFPromotions, interactions, CFHistory, SiteProcessor, eventer; let uiRenderer; Element.prototype.isVisible = function() { return !!(this.offsetWidth||this.offsetHeight||this.getClientRects().length); }; Element.prototype.isUserFriendly = function(selector) { let e = selector ? this.querySelector(selector) : this; return e && e.isVisible() ? e : null; }; Document.prototype.isUserFriendly = Element.prototype.isUserFriendly; Number.prototype.toDate = function() { return new Date(this); }; Number.prototype.msToCountdown = function() { const remainingSeconds = Math.ceil(this / 1000); const hours = Math.floor(remainingSeconds / 3600).toString().padStart(2, '0'); const minutes = Math.floor((remainingSeconds % 3600) / 60).toString().padStart(2, '0'); const seconds = (remainingSeconds % 60).toString().padStart(2, '0'); return `${hours}:${minutes}:${seconds}`; }; String.prototype.clean = function() { let output = ""; for (let i = 0; i < this.length; i++) { if (this.charCodeAt(i) <= 127) { output += this.charAt(i); } } return output; }; String.prototype.formatUnicorn = function () { "use strict"; var str = this.toString(); if (arguments.length) { var t = typeof arguments[0]; var key; var args = ("string" === t || "number" === t) ? Array.prototype.slice.call(arguments) : arguments[0]; for (key in args) { str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]); } } return str; }; Array.prototype.shuffle = function () { let currentIndex = this.length, temporaryValue, randomIndex; while (0 !== currentIndex) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = this[currentIndex]; this[currentIndex] = this[randomIndex]; this[randomIndex] = temporaryValue; } return this; }; let helpers = { typer: function(inputElm, value) { let lastValue = inputElm.value; inputElm.value = value; let event = new Event('input', { bubbles: true }); event.simulated = true; let tracker = inputElm._valueTracker; if (tracker) { tracker.setValue(lastValue); } inputElm.dispatchEvent(event); }, hasValue: function (val) { return val !== null && val !== undefined; }, getTdPrintableTime: function (date = new Date()) { if (date != null) { return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2); } return ''; }, getPrintableTime: function (date = new Date()) { if (date == null) { return ''; } return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2) + ':' + ('0' + date.getSeconds()).slice(-2); }, getPrintableDateTime: function (date) { if (date != null) { return ('0' + date.getDate()).slice(-2) + '/' + ('0' + (date.getMonth() + 1)).slice(-2) + ' ' + ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2); } else { return ''; } }, getEnumText: function (enm, value) { return Object.keys(enm).find(key => enm[key] === value) || '_ERR'; }, randomMs: function (a, b){ return a + (b - a) * Math.random(); }, addMinutes: function(mins, date = new Date()) { return date.setMinutes(date.getMinutes() + +mins); }, addSeconds: function(secs, date = new Date()) { return date.setSeconds(date.getSeconds() + +secs); }, randomHexColor: function() { const hexChars = '0123456789abcdef'; let color = ''; for (let i = 0; i < 6; i++) { color += hexChars[Math.floor(Math.random() * hexChars.length)]; } return color; }, randomString: function(length) { let str = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; const charactersLength = characters.length; for (let i = 0; i < length; i++) { str += characters.charAt(Math.floor(Math.random() * charactersLength)); } return str; }, randomInt: function(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; }, addMs: function(ms, date = new Date()) { return date.setMilliseconds(date.getMilliseconds() + ms); }, getRandomMs: function(minute, rangeDiffInPercentage) { // Now will be a random value between minute and minute + rangeDiffPercentage%; Example if minute = 30 and rangeDiffPercentage = 5 => random in the range [30, 31.5] let msMin = minute * 60 * 1000; let msMax = msMin + rangeDiffInPercentage/100 * msMin; return helpers.randomMs(msMin, msMax); }, hsToMs: function(hours) { return hours * 60 * 60 * 1000; }, minToMs: function(min) { return min * 60 * 1000; }, getEmojiForPromoStatus: function(promoStatus) { switch (promoStatus) { case K.CF.PromoStatus.NOCODE: return '⚪'; case K.CF.PromoStatus.PENDING: return '⏳'; case K.CF.PromoStatus.ACCEPTED: return '✔️'; case K.CF.PromoStatus.USEDBEFORE: return '🕙'; case K.CF.PromoStatus.INVALID: return '❌'; case K.CF.PromoStatus.EXPIRED: return '📅'; case K.CF.PromoStatus.UNKNOWNERROR: return '❗'; } }, getHost: function(url, withHttps = false) { if (url.includes('//')) { url = url.split('//')[1]; } url = url.split('/')[0]; return withHttps ? ('https://' + url) : url; }, cf: { getUrlType: function(url) { if (url.endsWith('/free-rolls')) { return K.CF.UrlType.FREEROLLS; } if (url.split('?')[0].endsWith('/free')) { return K.CF.UrlType.FREE; } if (url.includes('/promotion/')) { return K.CF.UrlType.PROMOTION; } if (url.endsWith('/contact-twitter')) { return K.CF.UrlType.CONTACTTWITTER; } if (url.endsWith('/settings')) { return K.CF.UrlType.SETTINGS; } if (url.endsWith('/stats')) { return K.CF.UrlType.STATS; } if (url.endsWith('/games')) { return K.CF.UrlType.GAMES; } if (url.endsWith('/')) { url = url.slice(0, -1); if (url == helpers.getHost(url, true)) { return K.CF.UrlType.HOME; } } if (url.endsWith('/login')) { return K.CF.UrlType.LOGIN; } return K.CF.UrlType.IGNORE; } }, triggerMouseEvent: function (elm, eventType) { let clickEvent = document.createEvent('MouseEvents'); clickEvent.initEvent (eventType, true, true); elm.dispatchEvent (clickEvent); }, alternativeClick: function (elm) { helpers.triggerMouseEvent (elm, "mouseover"); helpers.triggerMouseEvent (elm, "mousedown"); helpers.triggerMouseEvent (elm, "mouseup"); helpers.triggerMouseEvent (elm, "click"); }, textQuerySelector: function (selector, text) { let all = [...document.querySelectorAll(selector)].filter(x => x.innerText.toLowerCase() == text.toLowerCase()) if (all.length == 1) { return all[0]; } return undefined; } } class Persistence { constructor(prefix = 'autoWeb_') { this.prefix = prefix; } save(key, value, parseIt = false) { GM_setValue(this.prefix + key, parseIt ? JSON.stringify(value) : value); } load(key, parseIt = false) { let value = GM_getValue(this.prefix + key); if(value && parseIt) { value = JSON.parse(value); } return value; } } let objectGenerator = { createShared: function() { let config = {}; function initializeConfig() { config = { 'devlog.enabled': false, 'devlog.maxLines': 200, 'defaults.extraInterval': true, 'defaults.timeout': 4, 'defaults.postponeMinutes': 65, 'defaults.postponeMinutes.min': 65, 'defaults.postponeMinutes.max': 65, 'defaults.workInBackground': true, 'defaults.nextRun.useCountdown': true, 'defaults.nextRun': 60, 'defaults.nextRun.min': 60, 'defaults.nextRun.max': 60, 'defaults.sleepMode': false, 'defaults.sleepMode.min': "00:00", 'defaults.sleepMode.max': "01:00", 'cf.tryGetCodes': false, 'cf.usePromoCodes': true, 'cf.rollOnce': false, 'cf.autologin': false, 'cf.credentials.mode': 1, 'cf.credentials.email': 'YOUR@EMAIL.com', 'cf.credentials.password': 'YOURPASSWORD', 'cf.sleepHoursIfIpBan': 8, 'fp.maxTimeInMinutes': 15, 'fp.randomPtcOrder': true, 'dutchy.useBoosted': false, 'bk.withdrawMode': "0", 'bk.hoursBetweenWithdraws': 4, 'bk.sleepMinutesIfIpBan': 75, 'bestchange.address': '101', 'ui.runtime': 0, 'bigbtc.postponeMinutes': '0', 'jtfey.credentials.mode': 2, 'jtfey.credentials.username': 'YOUR_USERNAME', 'jtfey.credentials.password': 'YOURPASSWORD', 'ycoin.credentials.mode': 2, 'ycoin.credentials.username': 'YOUR_ACCOUNT_NUMBER', 'ycoin.credentials.password': 'YOURPASSWORD', 'bkclass.coin': 'LTC', 'bkclass.bcoin': 'LTC', 'migrations': [ {version: '00200799', applied: false} // migration to change pcodes status from error to usable due to ui changes ] }; let storedData = persistence.load('config', true); if(storedData) { for (const prop in config) { if(storedData.hasOwnProperty(prop)) { config[prop] = storedData[prop]; } } } config.version = GM_info.script.version; }; function getConfig() { return config; }; function updateConfig(items) { items.forEach( function (item) { config[item.prop] = item.value; }); persistence.save('config', config, true); }; function migrationApplied(migrationVersion) { try { let mig = config.migrations.find(x => x.version == migrationVersion); mig.applied = true; persistence.save('config', config, true); } catch (err) { console.warn('Error saving migration as applied'); console.error(err); } }; function devlog(msg, elapsed = false, reset = false) { if(!config['devlog.enabled']) { return; } let log; if(reset) { log = [`${helpers.getPrintableTime()}|Log cleared`]; } else { log = persistence.load('devlog', true); log = log ?? []; } if(msg) { msg = scheduleUuid ? `[${scheduleUuid}] ${msg}` : msg; let previous; try { previous = log[log.length - 1].split('|')[1]; } catch {} if(elapsed && (previous == msg)) { log[log.length - 1] = `${helpers.getPrintableTime()}|${msg}|[Elapsed time: ${elapsed} seconds]`; } else { log.push(`${helpers.getPrintableTime()}|${msg}`); } } if(log.length > 200) { log.splice(0, log.length - 200); } persistence.save('devlog', log, true); }; function getDevLog() { let log; log = persistence.load('devlog', true); if(log) { return log; } }; function getRunningSites() { let ret = []; loadFlowControl(); if(!runningSites || runningSites == {}) { return ret; } for (const sch in runningSites) { if (runningSites[sch].host) { ret.push(runningSites[sch].host); } } return ret; } let runningSites = {} let scheduleUuid = null; function isOpenedByManager() { loadFlowControl(); if(!runningSites || runningSites == {}) { return false; } let uuid = null; for (const sch in runningSites) { if ( (runningSites[sch].host && runningSites[sch].host == window.location.host) || (runningSites[sch].params && runningSites[sch].params.trackUrl && window.location.href.includes(runningSites[sch].params.trackUrl)) ) { uuid = sch; break; } } if (!uuid) { return false; } if (runningSites[uuid].runStatus == 'COMPLETED') { return false; } else { scheduleUuid = uuid; return true; } }; function loadFlowControl() { runningSites = persistence.load('runningSites', true) || {}; }; function setFlowControl(schedule, id, url, webType, params = null) { runningSites[schedule] = { id: id, changedAt: Date.now(), url: url, host: url.host, type: webType, opened: false, error: false, result: {} }; if(params) { runningSites[schedule].params = params; } else { runningSites[schedule].params = {}; } saveFlowControl(schedule); }; function isCompleted(expectedId) { loadFlowControl(); for(const sch in runningSites) { if (runningSites[sch].id == expectedId) { if (runningSites[sch].runStatus == 'COMPLETED') { return true; } else { return false; } } } return false; }; function isIncompleted(expectedId) { loadFlowControl(); for(const sch in runningSites) { if (runningSites[sch].id == expectedId) { if (runningSites[sch].runStatus == 'WORKING') { return true; } else { return false; } } } return false; }; function hasErrors(expectedId) { for(const sch in runningSites) { if (runningSites[sch].id == expectedId && runningSites[sch].error) { return true; } } return false; }; function getResult(schedule) { if (schedule) { return runningSites.hasOwnProperty(schedule) ? runningSites[schedule].result : {}; } return runningSites.hasOwnProperty(scheduleUuid) ? runningSites[scheduleUuid].result : {}; }; function getCurrent(schedule) { if (schedule) { return runningSites.hasOwnProperty(schedule) ? runningSites[schedule] : {}; } return runningSites.hasOwnProperty(scheduleUuid) ? runningSites[scheduleUuid] : {}; }; function saveAndclose(runDetails, delay = 0) { markAsVisited(runDetails); if(delay) { setTimeout(window.close, delay); } else { setTimeout(window.close, 1000); } }; function purgeFlowControlSchedules(validSchedules) { loadFlowControl(); let deletables = []; for (var sch in runningSites) { if (!validSchedules.includes(sch)) { deletables.push(sch); } } deletables.forEach(x => { delete runningSites[sch]; }); persistence.save('runningSites', runningSites, true); }; function saveFlowControl(schedule) { schedule = schedule ? schedule : scheduleUuid; if (!schedule) { persistence.save('runningSites', runningSites, true); return; } let tempFlow = persistence.load('runningSites', true); tempFlow[schedule] = runningSites[schedule]; persistence.save('runningSites', tempFlow, true); }; function markAsVisited(runDetails, runStatus = 'COMPLETED') { if (!scheduleUuid) { return; } runningSites[scheduleUuid].opened = true; runningSites[scheduleUuid].runStatus = runStatus; runningSites[scheduleUuid].result = runDetails ? runDetails : runningSites[scheduleUuid].result; saveFlowControl(scheduleUuid); }; function addError(errorType, errorMessage, schedule) { if (schedule) { runningSites[schedule].error = true; runningSites[schedule].result.errorType = errorType; runningSites[schedule].result.errorMessage = errorMessage; } else { runningSites[scheduleUuid].error = true; runningSites[scheduleUuid].result.errorType = errorType; runningSites[scheduleUuid].result.errorMessage = errorMessage; } saveFlowControl(schedule ? schedule : scheduleUuid); }; function closeWithError(errorType, errorMessage) { addError(errorType, errorMessage); window.close(); setInterval(() => { window.close(); }, 15000); }; function clearFlowControl(schedule) { if (schedule && schedule != 'all') { runningSites[schedule] = {}; saveFlowControl(schedule); } else if (schedule == 'all') { runningSites = {}; persistence.save('runningSites', {}, true); } }; function clearRetries() { loadFlowControl(); runningSites[scheduleUuid].retrying = false; saveFlowControl(scheduleUuid); return false; }; function isRetrying() { if(runningSites[scheduleUuid].retrying) { return true; } runningSites[scheduleUuid].retrying = true; saveFlowControl(scheduleUuid); return false; }; function setProp(key, val) { runningSites[scheduleUuid][key] = val; saveFlowControl(scheduleUuid); }; function getProp(key) { return runningSites[scheduleUuid][key]; }; function getParam(key) { try { } catch {} return runningSites[scheduleUuid].params[key]; }; initializeConfig(); return { devlog: devlog, getDevLog: getDevLog, setFlowControl: setFlowControl, isCompleted: isCompleted, isIncompleted: isIncompleted, isOpenedByManager: isOpenedByManager, saveFlowControl: saveFlowControl, getCurrent: getCurrent, getResult: getResult, addError: addError, closeWindow: saveAndclose, closeWithError: closeWithError, updateWithoutClosing: markAsVisited, hasErrors: hasErrors, clearFlowControl: clearFlowControl, getConfig: getConfig, updateConfig: updateConfig, clearRetries: clearRetries, isRetrying: isRetrying, setProp: setProp, getProp: getProp, getParam: getParam, migrationApplied: migrationApplied, purgeFlowControlSchedules: purgeFlowControlSchedules, getRunningSites: getRunningSites }; }, createCFPromotions: function() { let codes = []; function PromotionCode(id, code, repeatDaily = false, expiration = null, isRemoved = false) { this.id = id; this.code = code; this.added = new Date(); this.statusPerFaucet = []; this.repeatDaily = repeatDaily; this.lastExecTimeStamp = null; this['expiration' + 'Date'] = expiration; this.isRemoved = isRemoved; }; function getFaucetStatusInPromo(promo, faucetId) { let faucet = promo.statusPerFaucet.find(x => x.id == faucetId); if (faucet.status && promo.repeatDaily) { if((faucet.status == K.CF.PromoStatus.ACCEPTED && (Date.now() - faucet.execTimeStamp.getTime()) > K.Integers.HS_26_IN_MILLISECONDS) || (faucet.status == K.CF.PromoStatus.USEDBEFORE && (Date.now() - faucet.execTimeStamp.getTime()) > K.Integers.HS_2_IN_MILLISECONDS)) { faucet.status = K.CF.PromoStatus.PENDING; } } return faucet.status ?? K.CF.PromoStatus.NOCODE; }; function addNew(code, repeatDaily = false, expiration = null) { let found = codes.find(x => x.code == code); if (found) { found.repeatDaily = repeatDaily; found['expiration' + 'Date'] = expiration; found.isRemoved = false; } else { found = new PromotionCode(codes.length, code, repeatDaily, expiration); codes.push(found); } found.statusPerFaucet = manager.getFaucetsForPromotion().map(x => { return { id: x.id, };}); found.statusPerFaucet.forEach(function (element, idx, arr) { arr[idx].status = K.CF.PromoStatus.PENDING; arr[idx].execTimeStamp = null; }); save(); }; function includeNewCodes(newCodes) { for(let i=0; i x.code.toLowerCase() == item.code.toLowerCase()); if (!exists) { addNew(item.code, !item.oneTimeOnly, item['expiration' + 'Date']); } else { } } }; function getAll() { return codes.filter(x => !x.isRemoved); }; function updateFaucetForCode(code, faucetId, newStatus) { let promo = codes.find(x => x.code == code); let faucet = promo.statusPerFaucet.find(x => x.id == faucetId); if(faucet) { faucet.status = newStatus; faucet.execTimeStamp = new Date(); promo.lastExecTimeStamp = faucet.execTimeStamp; } save(); }; function hasPromoAvailable(faucetId) { let resp = []; codes.forEach(function (promotion, idx, arr) { let status = getFaucetStatusInPromo(promotion, faucetId); if (status == K.CF.PromoStatus.PENDING && !promotion.isRemoved) { resp.push(promotion.code); } }); if (resp.length > 0) { return resp; } else { return false; } }; function save() { persistence.save('CFPromotions', codes, true); }; function load(data) { codes = data; save(); }; function removeAll() { codes.forEach(x => x.isRemoved = true); codes = codes.filter(x => x['expiration' + 'Date'] && Date.parse(x['expiration' + 'Date']) > Date.now()); save(); }; function remove(id, code) { let idx = codes.findIndex(x => x.id == id && x.code == code); if(idx != -1) { codes[idx].isRemoved = true; save(); } return idx; }; return { addNew: addNew, removeAll: removeAll, remove: remove, getAll: getAll, load: load, updateFaucetForCode: updateFaucetForCode, hasPromoAvailable: hasPromoAvailable, includeNewCodes: includeNewCodes } }, createInteractions: function(){ let randomInteractionLevel = K.RandomInteractionLevel.MEDIUM; let maxActions = 0; let performedActions = -1; let selectableElements; let actions = { available: [ function() { let element = interactions.selectableElements[helpers.randomInt(0, interactions.selectableElements.length - 1)]; try { if (document.body.createTextRange) { const range = document.body.createTextRange(); range.moveToElementText(element); range.select(); } else if (window.getSelection) { const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(element); selection.removeAllRanges(); selection.addRange(range); } } catch (err) { } interactions.addPerformed(); } ] }; function start(selectableElements) { performedActions = 0; switch(randomInteractionLevel) { case K.RandomInteractionLevel.NONE: maxActions = 0; break; case K.RandomInteractionLevel.LOW: maxActions = helpers.randomInt(2, 4); break; case K.RandomInteractionLevel.MEDIUM: maxActions = helpers.randomInt(5, 8); break; case K.RandomInteractionLevel.HIGH: maxActions = helpers.randomInt(12, 16); break; } interactions.selectableElements = selectableElements; performActions(); } function performActions() { if(performedActions >= maxActions) { return; } let delay = 0; for(let i = 0; i < maxActions; i++) { delay += helpers.randomMs(350, 1500); setTimeout(actions.available[helpers.randomInt(0, actions.available.length - 1)], delay); } } function addPerformed() { performedActions++; } function completed() { return (performedActions >= maxActions); } return { start: start, completed: completed, addPerformed: addPerformed, selectableElements: selectableElements }; }, createCFProcessor: function() { const NavigationProcess = { ROLLING: 1, PROCESSING_PROMOTION: 2, LOGIN: 3 }; let navigationProcess; let countdown; let rollButton; let promotionTag; let timeWaiting= 0; let loopingForErrors = false; let tempRollNumber = null; let firstRollCompleted = false; function init() { let urlType = helpers.cf.getUrlType(window.location.href); console.log('URL TYPE:', urlType) switch(urlType) { case K.CF.UrlType.FREE: if(localeConfig.setToEnglish) { document.querySelector('.locale-changer .p-dropdown-trigger')?.click(); setTimeout(() => { document.querySelector("#pv_id_3_3")?.click(); }, 1000); } addJS_Node (null, null, overrideSelectNativeJS_Functions); interactions = objectGenerator.createInteractions(); run(); break; case K.CF.UrlType.PROMOTION: interactions = objectGenerator.createInteractions(); runPromotion(); break; case K.CF.UrlType.GAMES: location.replace('/free'); break; case K.CF.UrlType.HOME: case K.CF.UrlType.LOGIN: if (shared.getConfig()['cf.autologin']) { addJS_Node (null, null, overrideSelectNativeJS_Functions); doLogin(); } else { shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, ''); } break; case K.CF.UrlType.CONTACTTWITTER: shared.closeWithError(K.ErrorType.IP_BAN, ''); break; default: break; } return; } function run() { navigationProcess = NavigationProcess.ROLLING; setInterval(tryClosePopup, helpers.randomMs(3000, 6000)); setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000)); }; function doLogin() { navigationProcess = NavigationProcess.LOGIN; setTimeout(findLoginForm, helpers.randomMs(2000, 5000)); }; function isFullyLoaded() { //Waits 55 seconds max if(document.readyState == 'complete' || timeWaiting == -1) { timeWaiting = 0; if (firstRollCompleted) { roll(); } else { interact(); } } else { timeWaiting = -1; setTimeout(isFullyLoaded, helpers.randomMs(15000, 25000)); } }; function runPromotion() { navigationProcess = NavigationProcess.PROCESSING_PROMOTION setTimeout(findPromotionTag, helpers.randomMs(1000, 3000)); }; function tryClosePopup() { let popupBtn = document.querySelector('.p-dialog .p-dialog-header-close'); if (popupBtn && popupBtn.isVisible()) { popupBtn.click(); } }; function isRollResultVisible() { let rollDiv = document.querySelector('.result'); if (rollDiv && rollDiv.isVisible() && rollDiv.innerText != '') { } }; let waitRollNumberCount = 0; function closeToast() { document.querySelector('.p-toast-icon-close')?.click(); } async function waitForRollNumber() { let newNumber = -1; try { // intento leer el rolled number newNumber = [...document.querySelectorAll('.lucky-number-wrapper img')].map(x => x.src.split('/').slice(-1)[0].split('.').slice(-3)[0]).join(''); newNumber = parseInt(newNumber) } catch(err) { newNumber = null; } if (newNumber === null) { // si no logro leerlo, bajo 1 en tempRollNumber if (tempRollNumber < 0) { tempRollNumber -= 1; } else { tempRollNumber = -1; } if (tempRollNumber < -5) { processRunDetails(); return; } else { await wait(3000); return waitForRollNumber(); } } if (newNumber == tempRollNumber) { timeWaiting = 0; if (shared.getConfig()['cf.rollOnce']) { processRunDetails(); return; } else { firstRollCompleted = true; closeToast(); setTimeout(findCountdownOrRollButton, helpers.randomMs(1000, 2000)); return; } } else { waitRollNumberCount++; if (waitRollNumberCount > 15) { setTimeout(() => { location.reload(); }, 5000); return; } tempRollNumber = newNumber; await wait(3000); return waitForRollNumber(); } }; function isLoggedIn() { return !!document.querySelector('[data-icon="user"]'); } function findCountdownOrRollButton() { if (!isLoggedIn()) { location.reload(); } if( isCountdownVisible() && !isRollButtonVisible() ) { timeWaiting = 0; processRunDetails(); } else if ( !isCountdownVisible() && isRollButtonVisible() ) { timeWaiting = 0; setTimeout(isFullyLoaded, helpers.randomMs(1000, 5000)); } else if ( isCountdownVisible() && isRollButtonVisible() ) { try { let minLeft = document.querySelector('.minutes .digits').innerText; if (minLeft < 1) { timeWaiting = 0; setTimeout(isFullyLoaded, helpers.randomMs(1000, 5000)); } } catch (err) { console.log(`Error on alt logic of CF roll: ${err}`); } } else { if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) { shared.closeWithError(K.ErrorType.TIMEOUT, ''); return; } timeWaiting += 3000; setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000)); } }; function addUrlChangeListener() { if (window.onurlchange === null) { window.addEventListener('urlchange', (data) => { if (navigationProcess == NavigationProcess.LOGIN && !window.location.href.includes('/login')) { loopingForErrors = false; init(); } }); } }; function findLoginForm() { if ( document.querySelector('#email')?.isVisible() && document.querySelector('#password')?.isVisible() ) { addUrlChangeListener(); let errElement = document.querySelector('.login-wrapper .error'); if( errElement && errElement.innerHTML != '') { let errorMessage = errElement.innerText; shared.closeWithError(K.ErrorType.LOGIN_ERROR, errorMessage); return; } if(!loopingForErrors) { if(shared.getConfig()['cf.credentials.mode'] == 1) { timeWaiting = 0; helpers.typer(document.querySelector('.login-wrapper input[name="email"],#email'), shared.getConfig()['cf.credentials.email']); helpers.typer(document.querySelector('.login-wrapper input[name="password"],#password'), shared.getConfig()['cf.credentials.password']); document.querySelector('#password')?.closest('div')?.querySelector('button')?.click(); loopingForErrors = true; } else { if(document.querySelector('.login-wrapper input[name="email"],#email').value != '' && document.querySelector('.login-wrapper input[name="password"],#password').value != '') { document.querySelector('#password')?.closest('div')?.querySelector('button')?.click(); loopingForErrors = true; } else { if (timeWaiting/1000 > (shared.getConfig()['defaults.timeout'] / 1.5) * 60) { shared.closeWithError(K.ErrorType.LOGIN_ERROR, 'No credentials were provided'); return; } } } } } if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) { shared.closeWithError(K.ErrorType.TIMEOUT, ''); return; } timeWaiting += 3000; setTimeout(findLoginForm, helpers.randomMs(2000, 5000)); }; function interact() { let selectables = [].concat([...document.querySelectorAll('td')], [...document.querySelectorAll('p')], [...document.querySelectorAll('th')]); interactions.start(selectables); setTimeout(waitInteractions, helpers.randomMs(2000, 4000)); } function waitInteractions() { if(interactions.completed()) { roll(); } else { setTimeout(waitInteractions, helpers.randomMs(2000, 4000)); } } function isCountdownVisible() { countdown = document.querySelectorAll('.minutes .digits'); return (countdown.length > 0 && countdown[0].isVisible()); }; function isRollButtonVisible() { let rollButtonIcon = document.querySelector('.p-button [data-icon="gift"]'); if (!rollButtonIcon) { return false; } rollButton = rollButtonIcon.closest('button'); return rollButton && !rollButton.disabled && rollButton.isVisible(); }; function roll() { rollButton.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" }); rollButton.click(); tempRollNumber = -1; setTimeout(waitForRollNumber, helpers.randomMs(4000, 7000)); } function isPromotionTagVisible() { let pTag; try { pTag = document.querySelectorAll('.p-message-text.p-message-text')[0]; } catch(err) { return false; } if (pTag) { promotionTag = pTag; return true; } return false; }; function findPromotionTag() { if( isPromotionTagVisible() ) { processRunDetails(); } else { setTimeout(findPromotionTag, helpers.randomMs(2000, 5000)); } }; function processRunDetails() { let result = {}; if(navigationProcess == NavigationProcess.ROLLING) { result.claimed = readClaimed(); result.balance = readBalance(); if(result.claimed != 0) { result.rolledNumber = readRolledNumber(); } let minOneHour = result.rolledNumber && result.rolledNumber != 0; result.nextRoll = readCountdown(minOneHour); result.balance = readBalance(); } else if (navigationProcess == NavigationProcess.PROCESSING_PROMOTION) { result = shared.getResult() || {}; if (!result.promoCodeResults) { result.promoCodeResults = []; } let pc = { promoCode: readPromoCode(), promoStatus: readPromoStatus() }; result.promoCodeResults.push(pc); shared.updateWithoutClosing(result, 'WORKING'); setTimeout(gotoNextPromoCode, helpers.randomMs(1000, 2500)); return; } shared.closeWindow(result); }; function gotoNextPromoCode() { let codes = shared.getCurrent().params.promoCodes; if (!codes) { shared.closeWindow(); return; } let pc = readPromoCode(); let pcIdx = codes.findIndex(x => x == pc); if (pcIdx == -1 || pcIdx == codes.length - 1) { shared.closeWindow(); return; } window.location.href = '/promotion/' + codes[pcIdx + 1]; }; function readCountdown(minOneHour = false) { let minsElement = document.querySelector('.minutes .digits'); let mins = "0"; if (minsElement) { mins = minsElement.innerHTML; } if (mins) { let estimated = helpers.addMinutes(+mins + 1); let oneHour = Date.now() + (60*60*1000); if (minOneHour && (oneHour > estimated) ) { return oneHour; } return estimated; } else { return null; } }; function readClaimed() { let claimed = 0; try { claimed = document.querySelector('.p-toast-message-text .p-toast-detail').innerHTML; claimed = claimed.trim(); claimed = claimed.split(' ').slice(-2)[0] } catch(err) { } return claimed; }; function readRolledNumber() { let number = 0; try { number = [...document.querySelectorAll('.lucky-number-wrapper img')].map(x => x.src.split('/').slice(-1)[0].split('.').slice(-3)[0]).join(''); number = parseInt(number); } catch(err) { } return number; }; function readBalance() { let balance = ""; try { balance = document.querySelectorAll('header div div div > span span')[1].innerText.trim().split(' ')[0]; } catch(err) { } return balance; }; function readPromoStatus() { let promoStatus = K.CF.PromoStatus.UNKNOWNERROR; try { if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeAccepted) > 0) { return K.CF.PromoStatus.ACCEPTED; } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeUsed) > 0) { return K.CF.PromoStatus.USEDBEFORE; } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeExpired) > 0) { return K.CF.PromoStatus.EXPIRED; } else if(localeConfig.stringSearches.promoCodeInvalid.findIndex(x => promotionTag.innerHTML.indexOf(x) > -1) == -1) { return K.CF.PromoStatus.INVALID; } } catch ( err ) { } return promoStatus; }; function validatePromoString() { }; function readPromoCode() { var urlSplit = window.location.href.split('/'); return urlSplit[urlSplit.length - 1]; }; function displayStatusUi() { let wrapper = document.createElement('div'); wrapper.innerHTML = '
⚙️ Processing
'; document.querySelector( 'body' ).prepend( wrapper.firstChild ); }; return { init: init }; }, createCFHistory: function() { let rollsMeta = [ { id: 0, range: '0000-9885', count: 0 }, { id: 1, range: '9886-9985', count: 0 }, { id: 2, range: '9986-9993', count: 0 }, { id: 3, range: '9994-9997', count: 0 }, { id: 4, range: '9998-9999', count: 0 }, { id: 5, range: '10000', count: 0 } ]; function initOrLoad() { let storedData = persistence.load('CFHistory', true); if(storedData) { rollsMeta = storedData; } }; function addRoll(number) { switch(true) { case (number <= 9885): rollsMeta[0].count++; break; case (number <= 9985): rollsMeta[1].count++; break; case (number <= 9993): rollsMeta[2].count++; break; case (number <= 9997): rollsMeta[3].count++; break; case (number <= 9999): rollsMeta[4].count++; break; case (number == 10000): rollsMeta[5].count++; break; default: break; } save(); }; function getRollsMeta() { return rollsMeta.map(x => x.count); }; function save() { persistence.save('CFHistory', rollsMeta, true); }; return { initOrLoad: initOrLoad, addRoll: addRoll, getRollsMeta: getRollsMeta } }, }; function overrideSelectNativeJS_Functions () { window.alert = function alert (message) { } } function addJS_Node (text, s_URL, funcToRun) { var scriptNode= document.createElement ('script'); scriptNode.type= "text/javascript"; if (text)scriptNode.textContent= text; if (s_URL)scriptNode.src= s_URL; if (funcToRun)scriptNode.textContent = '(' + funcToRun.toString() + ')()'; var element = document.getElementsByTagName ('head')[0] || document.body || document.documentElement; element.appendChild (scriptNode); } function addHtml(data) { // data = { target: '', where: '', content: '' } document.querySelector(data.target).insertAdjacentHTML(data.where, data.content); } function addTemplateTag(data) { let templateTag = document.createElement('template'); templateTag.id = data.id; templateTag.innerHTML = data.content; let container = document.body || document.documentElement; container.appendChild(templateTag); } function useTemplate(data) { // data = { templateId: '', target: '', where: '', replacements: {} } let template = document.querySelector(`#${data.templateId}`).innerHTML; let content = template.formatUnicorn(data.replacements); addHtml({ target: data.target, where: data.where, content: content }); } function isExpectedPtc() { let runningList = shared.getRunningSites(); let ptcHosts = ['faucetpay.io']; for (let i = 0; i < ptcHosts.length; i++) { if (document.referrer.includes(`//${ptcHosts[i]}`) && runningList.includes(ptcHosts[i])) { waitForCloseSignal(ptcHosts[i]); return true; } } return false; } async function waitForCloseSignal(host) { await wait(3000); const signal = GM_getValue(`ptc-close-signal-${host}`) || null; if (signal) { window.close(); } return waitForCloseSignal(host); } function detectWeb() { if (isExpectedPtc()) { return; } if(!shared.isOpenedByManager()) { return; } instance = K.LOCATION.SITE; let typeFromManager = shared.getCurrent().type; siteTimer = new Timer({ isManager: false, delaySeconds: 20, uuid: shared.getProp('schedule'), webType: typeFromManager }); switch( typeFromManager ) { case K.WebType.STORMGAIN: SiteProcessor = createSGProcessor(); setTimeout(SiteProcessor.run, helpers.randomMs(10000, 20000)); break; case K.WebType.CRYPTOSFAUCETS: SiteProcessor = objectGenerator.createCFProcessor(); setTimeout(SiteProcessor.init, helpers.randomMs(1000, 3000)); break; case K.WebType.FREEBITCOIN: SiteProcessor = createFBProcessor(); setTimeout(SiteProcessor.run, helpers.randomMs(2000, 5000)); break; case K.WebType.FAUCETPAY: SiteProcessor = new FPPtc(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000)); break; case K.WebType.BIGBTC: SiteProcessor = createBigBtcProcessor(); setTimeout(SiteProcessor.init, helpers.randomMs(2000, 4000)); break; case K.WebType.BESTCHANGE: SiteProcessor = createBestChangeProcessor(); setTimeout(SiteProcessor.init, helpers.randomMs(4000, 6000)); break; case K.WebType.BFBOX: SiteProcessor = new BFRoll(helpers.getEnumText(K.CMC, shared.getCurrent().params.cmc).toLowerCase()); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000)); break; case K.WebType.DUTCHYROLL: SiteProcessor = new DutchyRoll(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000)); break; case K.WebType.FCRYPTO: SiteProcessor = new FCryptoRoll(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000)); break; case K.WebType.FPB: SiteProcessor = new FPB(shared.getCurrent().params.sitePrefix); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.FREEGRC: SiteProcessor = new GRCRoll(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.VIE: SiteProcessor = new VieRoll(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.O24: SiteProcessor = new O24Roll(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.YCOIN: SiteProcessor = new YCoin(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.CDIVERSITY: SiteProcessor = new CDiversity(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.CTOP: SiteProcessor = new CTop(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.AUTOCML: SiteProcessor = new AutoCMl(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; case K.WebType.CCLICKS: SiteProcessor = new CClicks(); setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000)); break; default: break; } } class UiBaseRenderer { constructor(uiRenderer) { this.uiRenderer = uiRenderer; } } class UiSitesRenderer extends UiBaseRenderer { appendEventListeners() { document.querySelector('#modal-assign-schedule').addEventListener('click', this.onClickOnModalAssignSchedule.bind(this)); eventer.on('siteChangedSchedule', (e) => { this.uiRenderer.toast(`Site moved to schedule ${e.scheduleId}`); manager.resyncAll({withUpdate: true}); // should act based on data only }); document.querySelector('#schedule-table-body').addEventListener('click', this.onClickOnSitesTableBody.bind(this)); document.querySelector('.action-edit-all-sites').addEventListener('click', this.onClickOnEditAllSites.bind(this)); document.querySelector('.action-edit-all-sites-cancel').addEventListener('click', this.onClickOnCancelEditAllSites.bind(this)); document.querySelector('.action-edit-all-sites-save').addEventListener('click', this.onClickOnSaveEditAllSites.bind(this)); document.querySelector('.action-add-external-site').addEventListener('click', this.onClickOnAddSiteButton.bind(this)); document.querySelector('#modal-add-site').addEventListener('click', this.onClickOnModalAddSite.bind(this)); eventer.on('siteAdded', (e) => { this.uiRenderer.toast(`Site ${e.siteName} added`); manager.resyncAll({withUpdate: true}); // should act based on data only }); eventer.on('siteRemoved', (e) => { this.uiRenderer.toast(`Site ${e.siteName} removed`); manager.resyncAll({withUpdate: true}); // should act based on data only }); } _legacyAddBadges(stats) { let consecutiveTimeout = stats.countTimeouts; let otherErrors = stats.errors; let html = ' '; if (consecutiveTimeout) { html += `${consecutiveTimeout}`; } if (otherErrors) { html += `${helpers.getEnumText(K.ErrorType, otherErrors.errorType)}`; } return html; } removeDeletedSitesRows(validSiteIds) { let removableRows = [...document.querySelectorAll('#schedule-table-body tr')].filter(r => !validSiteIds.includes(r.dataset.id)); removableRows.forEach(r => { r.remove(); }); } renderSiteRow(site) { let row = [...document.querySelectorAll('#schedule-table-body tr')] .filter(r => r.dataset.id == site.id); if (row.length == 0) { row = document.createElement('tr'); document.querySelector('#schedule-table-body').appendChild(row); row.setAttribute('aria-expanded', false); row.classList.add('align-middle'); row.dataset.id = site.id; row.dataset.cmc = site.cmc; } else { row = row[0]; } row.dataset.json = `${JSON.stringify(site)}`; row.dataset.schedule = site.schedule; row.dataset.nextRollTimestamp = site.nextRoll ? site.nextRoll.getTime() : 'null'; row.dataset.enabled = site.enabled ? '1' : '0'; if (site.balance) { if (typeof site.balance == 'string') { row.dataset.balance = site.balance.split(' ')[0]; } else { row.dataset.balance = site.balance.toFixed(8); } } else { row.dataset.balance = ''; } let tds = ''; tds += ''; tds += '' + helpers.getTdPrintableTime(site.nextRoll) + ''; if (site.isExternal && site.clId == -1) { tds += ''; } else { tds += ''; } tds += ''; if (site.cmc) { tds +='
'; tds += '
'; if (site.cmc > 0) { let cmcLower = helpers.getEnumText(K.CMC, site.cmc).toLowerCase(); tds += '' + cmcLower + ''; } else { tds += ''; } tds += '
'; } tds += ' ' + site.name + '
'; tds +='' + site.lastClaim.toFixed(Number.isInteger(site.lastClaim) ? 0 : 8) + ''; tds +='' + site.aggregate.toFixed(Number.isInteger(site.aggregate) ? 0 : 8) + ''; tds += '' + (+row.dataset.balance > 100 ? (+row.dataset.balance).toFixed(2) : row.dataset.balance) + ''; tds +=''; tds +='' + this._legacyAddBadges(site.stats) + ''; tds +=''; tds += `
`; tds +=''; row.innerHTML = tds; } legacyRenderSiteData(site, config) { document.querySelector('#faucet-name').innerHTML = site.name; document.querySelector('#faucet-name').dataset.id = site.id; let data = site.params || {}; for (const prop in config) { let overrideElement = document.querySelector('[data-site-prop="' + prop + '.override"]'); if (overrideElement) { overrideElement.dataset.original = (data[prop + '.override'] ? "1" : "0"); overrideElement.checked = data[prop + '.override']; } let element = document.querySelector('[data-site-prop="' + prop + '"]'); if(element) { if(element.type == 'select-one' || element.type == 'text' || element.type == 'password' || element.type == 'number' || element.type == 'time') { element.dataset.original = data[prop] ?? config[prop]; element.value = data[prop] ?? config[prop]; } else if (element.type == 'checkbox') { element.dataset.original = ((data[prop] ?? config[prop]) ? "1" : "0"); element.checked = data[prop] ?? config[prop]; } element.disabled = true; } } let elWorkInBackgroundOverride = document.querySelector('[data-site-prop="defaults.workInBackground.override"]'); let elWorkInBackground = document.querySelector('[data-site-prop="defaults.workInBackground"]'); elWorkInBackground.disabled = !elWorkInBackgroundOverride.checked; elWorkInBackgroundOverride.onchange = function (e) { document.querySelector('[data-site-prop="defaults.workInBackground"]').disabled = !e.target.checked; } let elTimeoutOverride = document.querySelector('[data-site-prop="defaults.timeout.override"]'); let elTimeout = document.querySelector('[data-site-prop="defaults.timeout"]'); elTimeout.disabled = !elTimeoutOverride.checked; elTimeoutOverride.onchange = function (e) { document.querySelector('[data-site-prop="defaults.timeout"]').disabled = !e.target.checked; } let elPostponeOverride = document.querySelector('[data-site-prop="defaults.postponeMinutes.override"]'); let elPostpone = document.querySelector('[data-site-prop="defaults.postponeMinutes"]'); let elPostponeMin = document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]'); let elPostponeMax = document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]'); elPostpone.disabled = !elPostponeOverride.checked; elPostponeMin.disabled = !elPostponeOverride.checked || (elPostpone.value > "0"); elPostponeMax.disabled = !elPostponeOverride.checked || (elPostpone.value > "0"); elPostponeOverride.onchange = function (e) { let mode = document.querySelector('[data-site-prop="defaults.postponeMinutes"]'); mode.disabled = !e.target.checked; document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]').disabled = !e.target.checked || mode.value > 0; document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]').disabled = !e.target.checked || mode.value > 0; } elPostpone.onchange = function (e) { document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]').disabled = e.target.value > 0; document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]').disabled = e.target.value > 0; if (e.target.value > 0) { document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]').value = e.target.value; document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]').value = e.target.value; } } let elNextRunOverride = document.querySelector('[data-site-prop="defaults.nextRun.override"]'); let elNextRun = document.querySelector('[data-site-prop="defaults.nextRun"]'); let elNextRunMin = document.querySelector('[data-site-prop="defaults.nextRun.min"]'); let elNextRunMax = document.querySelector('[data-site-prop="defaults.nextRun.max"]'); let elNextRunUseCountdown = document.querySelector('[data-site-prop="defaults.nextRun.useCountdown"]'); elNextRun.disabled = !elNextRunOverride.checked; elNextRunMin.disabled = !elNextRunOverride.checked || (elNextRun.value > "0"); elNextRunMax.disabled = !elNextRunOverride.checked || (elNextRun.value > "0"); elNextRunUseCountdown.disabled = !elNextRunOverride.checked; elNextRunOverride.onchange = function (e) { let mode = document.querySelector('[data-site-prop="defaults.nextRun"]'); mode.disabled = !e.target.checked; document.querySelector('[data-site-prop="defaults.nextRun.min"]').disabled = !e.target.checked || mode.value > 0; document.querySelector('[data-site-prop="defaults.nextRun.max"]').disabled = !e.target.checked || mode.value > 0; document.querySelector('[data-site-prop="defaults.nextRun.useCountdown"]').disabled = !e.target.checked; } elNextRun.onchange = function (e) { document.querySelector('[data-site-prop="defaults.nextRun.min"]').disabled = e.target.value > 0; document.querySelector('[data-site-prop="defaults.nextRun.max"]').disabled = e.target.value > 0; if (e.target.value > 0) { document.querySelector('[data-site-prop="defaults.nextRun.min"]').value = e.target.value; document.querySelector('[data-site-prop="defaults.nextRun.max"]').value = e.target.value; } } let elSleepOverride = document.querySelector('[data-site-prop="defaults.sleepMode.override"]'); let elSleep = document.querySelector('[data-site-prop="defaults.sleepMode"]'); let elSleepMin = document.querySelector('[data-site-prop="defaults.sleepMode.min"]'); let elSleepMax = document.querySelector('[data-site-prop="defaults.sleepMode.max"]'); elSleep.disabled = !elSleepOverride.checked; elSleepMin.disabled = !elSleepOverride.checked || !elSleep.checked; elSleepMax.disabled = !elSleepOverride.checked || !elSleep.checked; elSleepOverride.onchange = function (e) { let mode = document.querySelector('[data-site-prop="defaults.sleepMode"]'); mode.disabled = !e.target.checked; document.querySelector('[data-site-prop="defaults.sleepMode.min"]').disabled = !e.target.checked || !mode.checked; document.querySelector('[data-site-prop="defaults.sleepMode.max"]').disabled = !e.target.checked || !mode.checked; } elSleep.onchange = function (e) { document.querySelector('[data-site-prop="defaults.sleepMode.min"]').disabled = !e.target.checked; document.querySelector('[data-site-prop="defaults.sleepMode.max"]').disabled = !e.target.checked; } return; } sortSitesTable() { const tbody = document.querySelector('#schedule-table-body'); let rows, switching, i, shouldSwitch; switching = true; while (switching) { switching = false; rows = tbody.rows; for (i = 0; i < (rows.length - 1); i++) { shouldSwitch = false; let aNextRoll, bNextRoll, aHasLoginError, bHasLoginError, aName, bName; aNextRoll = rows[i].dataset.nextRollTimestamp; bNextRoll = rows[i + 1].dataset.nextRollTimestamp; if (aNextRoll == 'null' && bNextRoll == 'null') { aName = rows[i].querySelector('.site-name-container').innerText; bName = rows[i + 1].querySelector('.site-name-container').innerText; if (aName.toLowerCase() > bName.toLowerCase()) { shouldSwitch = true; break; } } else if (aNextRoll == 'null' || (aNextRoll > bNextRoll)) { shouldSwitch = true; break; } } if (shouldSwitch) { rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); switching = true; } } } onClickOnSitesTableBody(e) { let actionElement = e.target; if (actionElement.tagName === 'I') { actionElement = actionElement.parentElement; } const row = actionElement.closest('tr'); if (actionElement.classList.contains('action-edit-site')) { e.stopPropagation(); this.uiRenderer.openModal('modal-site', row.dataset.id); } else if (actionElement.classList.contains('action-run-asap')) { e.stopPropagation(); Site.setAsRunAsap(row.dataset.id); } else if (actionElement.classList.contains('action-site-assign-schedule')) { this.uiRenderer.openModal('modal-assign-schedule', { site_id: row.dataset.id, schedule_id: row.dataset.schedule }); } else if (actionElement.classList.contains('action-site-edit-parameters')) { this.uiRenderer.openModal('modal-site-parameters', { site_id: row.dataset.id }); } else if (actionElement.classList.contains('action-site-remove-external')) { Site.remove(row.dataset.id); console.info('TODO: remove site and all the related configuration', row.dataset.id); } } onClickOnModalAssignSchedule(e) { const modalAssignScheduleToSite = document.querySelector('#modal-assign-schedule'); let actionElement = e.target.tagName === 'I' ? e.target.parentElement : e.target; if (actionElement.classList.contains('modal-save')) { let data = this.uiRenderer.parseContainer(modalAssignScheduleToSite.querySelector('.form-container')); if (data.original_schedule_id == data.schedule) { } else { Site.getById(data.site_id).changeSchedule(data.schedule); } } } onClickOnModalAddSite(e) { const modal = document.querySelector('#modal-add-site'); let actionElement = e.target.tagName === 'I' ? e.target.parentElement : e.target; if (actionElement.classList.contains('modal-save')) { let formData = this.uiRenderer.parseContainer(modal.querySelector('.form-container')); let data = {}; data.name = formData.site_name; data.url = new URL(formData.site_url); data.schedule = formData.schedule; data.clId = -1; data.id = 'ext_rnd_id_' + helpers.randomString(8); data.type = K.WebType.UNDEFINED; data.cmc = -1; data.rf = ''; data.isExternal = true; console.warn('Savable new site'); Site.add(data); return; if (data.original_schedule_id == data.schedule) { } else { Site.getById(data.site_id).changeSchedule(data.schedule); } } } onClickOnEditAllSites(e) { document.querySelectorAll("#schedule-table-body td.em-input .site-name-container").forEach(function (x) { let val = x.innerHTML; x.innerHTML = ""; }); document.querySelectorAll("#schedule-table-body td.edit-status").forEach(function (x) { x.classList.remove("d-none"); }); document.querySelectorAll(".em-only").forEach(x => x.classList.remove("d-none")); document.querySelectorAll(".em-hide").forEach(x => x.classList.add("d-none")); } onClickOnCancelEditAllSites(e) { document.querySelectorAll("#schedule-table-body td.em-input .site-name-container input").forEach(function(x) { x.parentNode.innerHTML = x.dataset.original; }); document.querySelectorAll(".em-only").forEach(x => x.classList.add("d-none")); document.querySelectorAll(".em-hide").forEach(x => x.classList.remove("d-none")); } onClickOnSaveEditAllSites(e) { let updateObject; var updateData = document.getElementById("update-data"); if (updateData.innerHTML != "") { updateObject = JSON.parse(updateData.innerHTML); } else { updateObject = { runAsap: { ids: [], changed: false }, editSingle: { changed: false, items: [] }, wallet: { changed: false, items: [] }, config: { changed: false, items: [] }, site: { changed: false, list: [] } }; } document.querySelectorAll("#schedule-table-body tr").forEach(function (row) { let textInputCell = row.querySelector(".em-input .site-name-container"); let textInput = textInputCell.querySelector("input"); let activeSwitch = row.querySelector("td.edit-status input"); let single = { id: row.dataset.id, displayName: textInput.dataset.original, enabled: activeSwitch.dataset.original }; textInputCell.innerHTML = textInput.value; if(textInput.dataset.original != textInput.value) { single.displayName = textInput.value; } if(activeSwitch.dataset.original != Boolean(activeSwitch.checked)) { single.enabled = Boolean(activeSwitch.checked); } if(textInput.dataset.original != textInput.value || activeSwitch.dataset.original != Boolean(activeSwitch.checked)) { updateObject.editSingle.items.push(single); updateObject.editSingle.changed = true; } }); if(updateObject.editSingle.changed) { document.getElementById("update-data").innerHTML = JSON.stringify(updateObject); this.uiRenderer.toast("Data will be updated as soon as possible"); } document.querySelectorAll(".em-only").forEach(x => x.classList.add("d-none")); document.querySelectorAll(".em-hide").forEach(x => x.classList.remove("d-none")); } onClickOnAddSiteButton(e) { e.stopPropagation(); this.uiRenderer.openModal('modal-add-site'); } renderAddExternalSite() { const modalAssignSchedule = document.getElementById('modal-add-site'); let selectElm = modalAssignSchedule.querySelector('select'); let options = []; let firstSchedule = ''; Schedule.getAllForCrud().forEach(sch => { if (firstSchedule == '') { firstSchedule = sch.uuid; } options.push(``) }); selectElm.innerHTML = options.join(''); selectElm.value = firstSchedule; return; } renderAssignScheduleToSite(values) { const modalAssignSchedule = document.getElementById('modal-assign-schedule'); modalAssignSchedule.querySelector('input[name="site_id"]').value = values.site_id; modalAssignSchedule.querySelector('input[name="original_schedule_id"]').value = values.schedule_id; let selectElm = modalAssignSchedule.querySelector('select'); let options = []; Schedule.getAllForCrud().forEach(sch => { options.push(``) }); selectElm.innerHTML = options.join(''); selectElm.value = values.schedule_id || ""; return; } } class UiPromosRenderer extends UiBaseRenderer { appendEventListeners() { document.querySelector('#promo-button').addEventListener('click', this.onClickSavePromoCode.bind(this)); document.querySelector('#button-try-get-codes').addEventListener('click', this.onClickTryGetCodes.bind(this)); document.querySelector('#promo-table-body').addEventListener('click', this.onClickOnPromoTableBody.bind(this)); } onClickSavePromoCode(e) { var promoText = document.getElementById("promo-text-input"); var promoCode = document.getElementById("promo-code-new"); var promoDaily = document.getElementById("promo-daily"); var promoObject = { action: "ADD", code: promoText.value.trim(), repeatDaily: promoDaily.checked }; promoCode.innerHTML =JSON.stringify(promoObject); this.uiRenderer.toast("Adding promo code: " + promoObject.code + "..."); promoText.value = ''; } onClickTryGetCodes(e) { var promoCode = document.getElementById("promo-code-new"); var promoObject = { action: "TRYGETCODES" }; promoCode.innerHTML =JSON.stringify(promoObject); this.uiRenderer.toast("Fetching codes..."); } _legacyRemoveUsedDailyCodes(codes) { if(codes && codes.length) { codes.forEach(code => { if(!code.repeatDaily) { let counter = 0; for(let i = 0; i < code.statusPerFaucet.length; i++) { if(code.statusPerFaucet[i].execTimeStamp) { counter++; } } if(counter == code.statusPerFaucet.length) { setTimeout(() => removePromoCode(code.id, code.code), 20000); } } }); } } legacyRenderPromotionTable(codes) { let tableBody = ''; this._legacyRemoveUsedDailyCodes(codes); for(let c=0; c < codes.length; c++) { let data = codes[c]; tableBody += ''; tableBody += ''; tableBody += ``; tableBody += '' + data.code + ''; tableBody +='' + helpers.getPrintableDateTime(data.added) + ''; for(let i=0, all = data.statusPerFaucet.length; i < all; i++) { tableBody +='' + helpers.getEmojiForPromoStatus(data.statusPerFaucet[i].status ?? 0) + ''; } tableBody +=''; } document.getElementById('promo-table-body').innerHTML = tableBody; } onClickOnPromoTableBody(e) { let actionElement = e.target; if (actionElement.tagName === 'I') { actionElement = actionElement.parentElement; } const row = actionElement.closest('tr'); if (actionElement.classList.contains('action-remove-promo-code')) { e.stopPropagation(); var promoCode = document.getElementById("promo-code-new"); var promoObject = { action: "REMOVE", id: row.dataset.promotionId, code: row.dataset.promotionCode }; promoCode.innerHTML =JSON.stringify(promoObject); } } } class UiConfigRenderer extends UiBaseRenderer { legacyRenderConfigData(data) { for (const prop in data) { let element = document.querySelector('[data-prop="' + prop + '"]'); if(element) { if(element.type == 'select-one' || element.type == 'text' || element.type == 'password' || element.type == 'number' || element.type == 'time') { element.dataset.original = data[prop]; element.value = data[prop]; } else if (element.type == 'checkbox') { element.dataset.original = (data[prop] ? "1" : "0"); element.checked = data[prop]; } } } let elCfTryGetCodes = document.querySelector('[data-prop="cf.tryGetCodes"]') let elCredentialsAutologin = document.querySelector('[data-prop="cf.autologin"]'); let elCredentialsMode = document.querySelector('[data-prop="cf.credentials.mode"]'); let elCredentialsEmail = document.querySelector('[data-prop="cf.credentials.email"]'); let elCredentialsPassword = document.querySelector('[data-prop="cf.credentials.password"]'); let elDevlogEnabled = document.querySelector('[data-prop="devlog.enabled"]'); let elDevlogMaxLines = document.querySelector('[data-prop="devlog.maxLines"]'); let elJtfeyCredentialsMode = document.querySelector('[data-prop="jtfey.credentials.mode"]'); let elJtfeyCredentialsUsername = document.querySelector('[data-prop="jtfey.credentials.username"]'); let elJtfeyCredentialsPassword = document.querySelector('[data-prop="jtfey.credentials.password"]'); let elYCoinCredentialsMode = document.querySelector('[data-prop="ycoin.credentials.mode"]'); let elYCoinCredentialsUsername = document.querySelector('[data-prop="ycoin.credentials.username"]'); let elYCoinCredentialsPassword = document.querySelector('[data-prop="ycoin.credentials.password"]'); let elPostpone = document.querySelector('[data-prop="defaults.postponeMinutes"]'); let elPostponeMin = document.querySelector('[data-prop="defaults.postponeMinutes.min"]'); let elPostponeMax = document.querySelector('[data-prop="defaults.postponeMinutes.max"]'); elPostponeMin.disabled = (elPostpone.value > "0"); elPostponeMax.disabled = (elPostpone.value > "0"); if (elPostponeMin.disabled && elPostponeMax.disabled) { elPostponeMin.value = elPostpone.value; elPostponeMax.value = elPostpone.value; } elPostpone.onchange = function (e) { document.querySelector('[data-prop="defaults.postponeMinutes.min"]').disabled = e.target.value > 0; document.querySelector('[data-prop="defaults.postponeMinutes.max"]').disabled = e.target.value > 0; if (e.target.value > 0) { document.querySelector('[data-prop="defaults.postponeMinutes.min"]').value = e.target.value; document.querySelector('[data-prop="defaults.postponeMinutes.max"]').value = e.target.value; } } let elNextRun = document.querySelector('[data-prop="defaults.nextRun"]'); let elNextRunMin = document.querySelector('[data-prop="defaults.nextRun.min"]'); let elNextRunMax = document.querySelector('[data-prop="defaults.nextRun.max"]'); let elNextRunUseCountdown = document.querySelector('[data-prop="defaults.nextRun.useCountdown"]'); elNextRunMin.disabled = (elNextRun.value > "0"); elNextRunMax.disabled = (elNextRun.value > "0"); if (elNextRunMin.disabled && elNextRunMax.disabled) { elNextRunMin.value = elNextRun.value; elNextRunMax.value = elNextRun.value; } elNextRun.onchange = function (e) { document.querySelector('[data-prop="defaults.nextRun.min"]').disabled = e.target.value > 0; document.querySelector('[data-prop="defaults.nextRun.max"]').disabled = e.target.value > 0; if (e.target.value > 0) { document.querySelector('[data-prop="defaults.nextRun.min"]').value = e.target.value; document.querySelector('[data-prop="defaults.nextRun.max"]').value = e.target.value; } } let elSleepMode = document.querySelector('[data-prop="defaults.sleepMode"]'); let elSleepModeMin = document.querySelector('[data-prop="defaults.sleepMode.min"]'); let elSleepModeMax = document.querySelector('[data-prop="defaults.sleepMode.max"]'); elSleepModeMin.disabled = !elSleepMode.checked; elSleepModeMax.disabled = !elSleepMode.checked; elSleepMode.onchange = function (e) { document.querySelector('[data-prop="defaults.sleepMode.min"]').disabled = !e.target.checked; document.querySelector('[data-prop="defaults.sleepMode.max"]').disabled = !e.target.checked; } elCredentialsMode.disabled = !elCredentialsAutologin.checked; elCredentialsEmail.disabled = ( (!elCredentialsAutologin.checked || elCredentialsMode.value == "2") ? true : false); elCredentialsPassword.disabled = ( (!elCredentialsAutologin.checked || elCredentialsMode.value == "2") ? true : false); elCredentialsAutologin.onchange = function (e) { document.querySelector('[data-prop="cf.credentials.mode"]').disabled = !e.target.checked; if (elCredentialsMode.value == "2") { document.querySelector('[data-prop="cf.credentials.email"]').disabled = true; document.querySelector('[data-prop="cf.credentials.password"]').disabled = true; } else { document.querySelector('[data-prop="cf.credentials.email"]').disabled = false; document.querySelector('[data-prop="cf.credentials.password"]').disabled = false; } } elCredentialsMode.onchange = function (e) { if (e.target.value == "2") { document.querySelector('[data-prop="cf.credentials.email"]').disabled = true; document.querySelector('[data-prop="cf.credentials.password"]').disabled = true; } else { document.querySelector('[data-prop="cf.credentials.email"]').disabled = false; document.querySelector('[data-prop="cf.credentials.password"]').disabled = false; } } elYCoinCredentialsUsername.disabled = ( (elYCoinCredentialsMode.value == "2") ? true : false); elYCoinCredentialsPassword.disabled = ( (elYCoinCredentialsMode.value == "2") ? true : false); elYCoinCredentialsMode.onchange = function (e) { if (e.target.value == "2") { document.querySelector('[data-prop="ycoin.credentials.username"]').disabled = true; document.querySelector('[data-prop="ycoin.credentials.password"]').disabled = true; } else { document.querySelector('[data-prop="ycoin.credentials.username"]').disabled = false; document.querySelector('[data-prop="ycoin.credentials.password"]').disabled = false; } } elJtfeyCredentialsUsername.disabled = ( (elJtfeyCredentialsMode.value == "2") ? true : false); elJtfeyCredentialsPassword.disabled = ( (elJtfeyCredentialsMode.value == "2") ? true : false); elJtfeyCredentialsMode.onchange = function (e) { if (e.target.value == "2") { document.querySelector('[data-prop="jtfey.credentials.username"]').disabled = true; document.querySelector('[data-prop="jtfey.credentials.password"]').disabled = true; } else { document.querySelector('[data-prop="jtfey.credentials.username"]').disabled = false; document.querySelector('[data-prop="jtfey.credentials.password"]').disabled = false; } } elDevlogMaxLines.disabled = !elDevlogEnabled.checked; elDevlogEnabled.onchange = function (e) { document.querySelector('[data-prop="devlog.maxLines"]').disabled = !e.target.checked; } } } class UiWalletRenderer extends UiBaseRenderer { legacyRenderWalletTable(data) { let tableBody = ''; for(let i=0, all = data.length; i < all; i++) { tableBody += ''; tableBody += '' + data[i].name + ''; tableBody += ''; tableBody += ''; } document.getElementById('wallet-table-body').innerHTML = tableBody; } } class UiSchedulesRenderer extends UiBaseRenderer { appendEventListeners() { document.querySelector('#schedules-toggler').addEventListener('change', this.onScheduleToggled.bind(this)); } onScheduleToggled(e) { e.stopPropagation(); let actionElement = e.target.tagName !== 'LABEL' ? e.target.closest('label') : e.target; let otherActiveLabels = [...actionElement.parentElement.querySelectorAll('label.active')].filter(l => l.dataset.schedule != actionElement.dataset.schedule); if (otherActiveLabels.length > 0) { otherActiveLabels.forEach(l => l.classList.remove('active')); } this.toggleSchedule(actionElement.dataset.schedule); } toggleSchedule(uuid) { if (uuid) { this.selectedSchedule = uuid; } else { if (!this.selectedSchedule) { this.selectedSchedule = 'all'; } } [...document.querySelectorAll('#schedule-table-body tr')].forEach((row) => { if (this.selectedSchedule == 'all') { row.classList.remove('d-none'); } else if (row.getAttribute('data-schedule') == this.selectedSchedule) { row.classList.remove('d-none'); } else { row.classList.add('d-none'); } }); if (this.selectedSchedule == 'all') { [...document.querySelectorAll('#console-log tr')].forEach(x => { x.classList.remove('d-none'); }) } else { [...document.querySelectorAll('#console-log tr')].forEach(x => { if (x.getAttribute('data-schedule') == 'false' || x.getAttribute('data-schedule') == this.selectedSchedule) { x.classList.remove('d-none'); } else { x.classList.add('d-none'); } }) } }; renderTBody() { let rows = []; Schedule.getAllForCrud().forEach(sch => { rows.push(this.renderRow(sch)); }); return rows.join(''); } renderRow(sch) { let row = `
`; return row; } } class UiSiteParameterRenderer extends UiBaseRenderer { static handlers = new Map(); static registerHandler(name, handler) { UiSiteParameterRenderer.handlers.set(name, handler); } static getHandler(name) { const handlerClass = UiSiteParameterRenderer.handlers.get(name); return handlerClass || false; } appendEventListeners() { document.querySelector('#modal-site-parameters').addEventListener('click', this.onClickOnModalSiteParameter.bind(this)); } onClickOnModalSiteParameter(e) { const modal = document.querySelector('#modal-site-parameters'); let actionElement = e.target.tagName === 'I' ? e.target.parentElement : e.target; if (actionElement.classList.contains('modal-save')) { e.preventDefault(); let form = modal.querySelector('.form-container form'); if (!form.checkValidity()) { form.reportValidity(); return; } let data = this.uiRenderer.parseContainer(form); $(modal).modal('hide'); } } renderFields(values) { let fieldsHtml = ''; values.forEach( field => { field.text = field.text || field.name.charAt(0).toUpperCase() + field.name.slice(1).toLowerCase().replaceAll('_', ' '); switch (field.type) { case 'credentials_or_autofilled': // TODO: will need to condition username/email/password! break; case 'email': fieldsHtml += uiRenderer.addInputEmailHtml(field); break; case 'password': fieldsHtml += uiRenderer.addInputPasswordHtml(field); break; case 'checkbox': field.value = (field.value === true || field.value === 'true' || field.value === 1 || field.value === "1") ? true : false; fieldsHtml += uiRenderer.addSliderHtml(field); break; case 'numberInput': fieldsHtml += uiRenderer.addInputNumberHtml(field); break; case 'textInput': case 'username': field.required = 'true'; default: fieldsHtml += uiRenderer.addInputTextHtml(field); break; } }); const modalSiteParameters = document.getElementById('modal-site-parameters'); modalSiteParameters.querySelector('.form-container form').innerHTML = fieldsHtml; } renderEditSiteParameters(args) { // { site_id: 'x' } const site = Site.getById(args.site_id); const siteParameters = site.getSiteParameters(); // async? for external site parameters that need to be loaded from other stg... if (!siteParameters) { console.warn(`Site ${site.id} ${site.name} does not require parameters setup.`); return; } if (!siteParameters.handler) { console.warn(`Handler name is missing`); return; } const handlerClass = UiSiteParameterRenderer.getHandler(siteParameters.handler); if (!handlerClass) { console.warn(`Invalid handler class name: ${siteParameters.handler}`); return; } const handler = new handlerClass(siteParameters.values); handler.preRender(); let fields = [ { name: 'AUTO_UPDATE_PROMO_CODES', type: 'checkbox', value: 'false' }, { name: 'MAX_ROLLS_PER_VISIT', type: 'numberInput', value: 1, min: 0 }, { name: 'AUTO_LOGIN', type: 'checkbox', value: 'true' }, { name: 'EMAIL', type: 'email', value: '' }, { name: 'PASSWORD', type: 'password', value: '' } ]; fields.forEach( (f, idx) => { if (f.order == null || f.order == undefined) { f.order = idx; } }); let values = persistence.load(`site_parameters_${args.site_id}`, true) || []; for(const field of fields) { let vIdx = values.findIndex(v => v.name == field.name); if (vIdx > -1) { field.value = values[vIdx].value; } } values = fields; this.renderFields(values); handler.postRender(); return; } } class UiRenderer { constructor () { this.sites = new UiSitesRenderer(this); this.siteParameters = new UiSiteParameterRenderer(this); this.promos = new UiPromosRenderer(this); this.config = new UiConfigRenderer(this); this.wallet = new UiWalletRenderer(this); this.schedules = new UiSchedulesRenderer(this); this.selectedSchedule = null; } initialize() { this.appendCSS(); } toast(msg, msgType = "info") { toastr[msgType](msg); } openModal(id, values = null) { const dlg = document.querySelector('#modal-dlg'); dlg.querySelectorAll(".modal-content").forEach(x => x.classList.add('d-none')); switch (id) { case 'modal-backup': console.info('TODO: GM_listValues => loop keys => save json as blob'); break; case 'modal-ereport': case 'modal-config': case 'modal-site': document.getElementById("target-spinner").innerHTML = JSON.stringify({id: id, siteId: values}); document.getElementById("modal-spinner").classList.remove("d-none"); dlg.querySelector('div').classList.add('modal-lg'); break; case 'modal-add-site': this.sites.renderAddExternalSite(); document.getElementById(id).classList.remove("d-none"); dlg.querySelector('div').classList.remove('modal-lg'); break; case 'modal-slAlert': shortlinkAlert.load(id); dlg.querySelector('div').classList.add('modal-lg'); break; case 'modal-schedules': document.getElementById(id).querySelector('table tbody').innerHTML = this.schedules.renderTBody(); this.appendColorPickers('.color-picker'); dlg.querySelector('div').classList.remove('modal-lg'); document.getElementById(id).classList.remove("d-none"); break; case 'modal-assign-schedule': this.sites.renderAssignScheduleToSite(values); document.getElementById(id).classList.remove("d-none"); dlg.querySelector('div').classList.remove('modal-lg'); break; case 'modal-site-parameters': this.siteParameters.renderEditSiteParameters(values); document.getElementById(id).classList.remove("d-none"); dlg.querySelector('div').classList.remove('modal-lg'); break; default: dlg.querySelector('div').classList.add('modal-lg'); document.getElementById(id).classList.remove("d-none"); break; } $(dlg).modal('show'); } appendEventListeners() { for (const renderer in this) { if (this[renderer] && typeof this[renderer].appendEventListeners === 'function') { this[renderer].appendEventListeners(); } } $('[data-toggle="tooltip"]').tooltip({ trigger: 'hover' }); } appendCSS() { let css = document.createElement('style'); css.innerHTML = ` td.em-input { padding-top: 0; padding-bottom: 0; } pre { height: 145px; width:100%; white-space: pre-wrap; padding-left: 1em; } pre span { display: block; } .row-schedule-handle { } .grabbable:not(.d-none):not(.in-use) { cursor: move; cursor: grab; cursor: -moz-grab; cursor: -webkit-grab; } .grabbable:not(.d-none):not(.in-use):active { cursor: grabbing; cursor: -moz-grabbing; cursor: -webkit-grabbing; } .row-handle { cursor: grab; } .dropdown-item { cursor: pointer; } #schedule-table th,td { vertical-align: middle; padding-top: .25rem!important; padding-bottom: .25rem!important; } #schedule-table-body td.em-input input[readonly] { background-color:transparent; border: 0; font-size: 1em; } td[data-field="displayName"] .input-group-prepend .input-group-text { background-color: transparent; border-color: transparent; font-size: 1em; } .custom-switch input,label { cursor: pointer; } `; document.head.appendChild(css); } addLegacySliderHtml(propName, propValue, text) { return ` ${text}`; } addSliderHtml(field) { const rndStr = helpers.randomString(8); return `
`; } addInputEmailHtml(field) { const rndStr = helpers.randomString(8); const pattern = "[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"; return `
`; } addInputPasswordHtml(field) { const rndStr = helpers.randomString(8); return `
`; } addInputTextHtml(field) { const rndStr = helpers.randomString(8); return `
`; } addInputNumberHtml(field) { const rndStr = helpers.randomString(8); return `
`; } parseContainer(container) { let obj = {}; Object.assign(obj, container.dataset); let inputs = container.querySelectorAll('input, select'); inputs.forEach(function (input) { if (input.type == 'checkbox') { obj[input.name] = input.checked ? 'true' : 'false'; } else if (input.type == 'number') { obj[input.name] = +input.value; } else { obj[input.name] = input.value; } }); for (const p in obj) { // type converter. TODO: add int, float, etc. if (obj[p] === 'true') { obj[p] = true } if (obj[p] === 'false') { obj[p] = false } if (p == 'uuid') { obj[p] = obj[p].toLowerCase().replace('#', ''); } if (p == 'originals') { try { obj[p] = JSON.parse(obj[p]); } catch (err) { delete obj[p]; } } } return obj; } parseTable(table) { let rows = table.querySelectorAll('tbody tr'); let data = []; rows.forEach( (r, idx) => { let obj = this.parseContainer(r); obj.order = '' + idx; // fix order if (!(obj.added && obj.removed)) { // skip if it was just added and removed data.push(obj); } }); return data; } appendColorPickers(selector) { $(selector).each(function () { $(this).colorpicker(); $(this).on('colorpickerChange', function(event) { $(event.target.querySelector('.fa-square')).css('color', event.color.toString()); }); }); } } class EventEmitter { constructor() { this.events = {}; } on(eventName, callback) { if (!this.events[eventName]) { this.events[eventName] = []; } this.events[eventName].push(callback); } emit(eventName, data) { const eventCallbacks = this.events[eventName]; if (eventCallbacks) { eventCallbacks.forEach(callback => { callback(data); }); } } } class Timeout { constructor() { this.startedAt; this.interval; this.cb = (() => { shared.closeWithError(K.ErrorType.TIMEOUT, '') }); let paramTimeout = shared.getParam('timeout'); if (paramTimeout) { this.wait = paramTimeout * 60; } else { this.wait = shared.getConfig()['defaults.timeout'] * 60 } this.wait += 30; // add a threshold this.restart(); } get elapsed() { return Date.now() - this.startedAt; } restart(addSeconds = false) { if(this.interval) { clearTimeout(this.interval); } this.startedAt = Date.now(); if(addSeconds) { this.wait = this.wait + addSeconds; } this.interval = setTimeout( () => { this.cb() }, this.wait * 1000); } } class Timer { constructor(params) { Object.assign(this, params); if(!useTimer || (this.webType && !Timer.webTypes().includes(this.webType))) { return; } this.delay = this.delaySeconds * 1000; } static webTypes() { return [K.WebType.FREELITECOIN, K.WebType.FREEETHEREUMIO, K.WebType.BIGBTC, K.WebType.FCRYPTO, K.WebType.FPB] // , K.WebType.BSCADS] }; startCheck(webType) { this.webType = webType; if(!useTimer || (helpers.hasValue(webType) && !Timer.webTypes().includes(webType))) { return; } persistence.save(this.uuid + '_lastAccess', Date.now()); this.interval = setInterval(() => { this.isAlive(); }, this.delay); } stopCheck() { if(!useTimer) { return; } clearInterval(this.interval); } tick() { if(!useTimer) { return; } persistence.save(this.uuid + '_lastAccess', Date.now()); } isAlive() { return; } } const wait = ms => new Promise(resolve => setTimeout(resolve, ms || 3000)); class CrawlerWidget { constructor(params) { if (!params || (!params.selector && !params.fnSelector)) { throw new Error('CrawlerWidget requires a selector or a function selector parameter'); } this.context = this.context || document; Object.assign(this, params); } get isUserFriendly() { if (this.selector) { this.element = this.context.isUserFriendly(this.selector); return this.element; } else { this.element = this.fnSelector(); return this.element; } } } class ReadableWidget extends CrawlerWidget { constructor(params) { if (params && !params.parser) { params.parser = Parsers.innerText; //default parser } super(params); } get value() { if (this.isUserFriendly) { return this.parser(this.element, this.options); } else { return ''; } } } class TextboxWidget extends CrawlerWidget { get value() { if (!this.isUserFriendly) { return ''; } return this.element.value; } set value(newValue) { if (!this.isUserFriendly) { return ''; } this.element.value = newValue; return ''; } } class ButtonWidget extends CrawlerWidget { click() { if (this.isUserFriendly) { this.element.click(); return Promise.resolve(true); } else { } } } class SubmitWidget extends CrawlerWidget { click() { if (this.isUserFriendly) { let frm = this.element; while(frm.nodeName != 'FORM' && frm.nodeName != null) { frm = frm.parentElement; } if (frm.nodeName == 'FORM') { frm.submit(); } else { return; } return Promise.resolve(true); } else { } } } class CountdownWidget extends CrawlerWidget { constructor(params) { if (params && !params.parser) { params.parser = Parsers.innerText; //default parser } super(params); } get timeLeft() { if (this.isUserFriendly) { return this.parser(this.element, this.options); } else { throw new Error(`CountdownWidget (selector: '${this.selector}') cannot be read`); } } } class Parsers { static innerText(elm) { // '0.12341234' => '0.12341234' try { return elm.innerText; } catch (err) { } } static trimNaNs(elm) { // 'You won 0.12341234 TRX' => '0.12341234' try { return elm.innerText.replace(/[^\d.-]/g, ''); } catch (err) { } } static splitAndIdxTrimNaNs(elm, options) { // '17.96 Coins (17.50 + 0.46)' => 17.96 try { return elm.innerText.split(options.splitter)[options.idx].replace(/[^\d.-]/g, ''); } catch (err) { } } static innerTextIntToFloat(elm) { // 'You won 1234 satoshis' => 0.00001234 try { let sats = elm.innerText.replace(/\D/g, ''); return sats / 100000000; } catch (err) { } } static innerTextJoinedToInt(elm) { // '7|2|9|6' => 7296 try { return parseInt([... elm].map( x => x.innerText).join('')); } catch (err) { } } static stormGainCountdown(elm) { // '3:01:01' => 120000 try { let timeLeft = elm.innerText.split(':'); if (timeLeft[0] == 'Synchronizing') { } if(timeLeft.length === 3) { return parseInt(timeLeft[0]) * 60 + parseInt(timeLeft[1]); } } catch (err) { return null; } } static kingBizCountdown(elm) { // '4|2' => 42 try { let itms = elm.querySelectorAll('.flip-clock-active .up'); if (itms.length > 1 && itms[0].isVisible() && itms[1].isVisible()) { return parseInt([itms[0].innerText, itms[1].innerText].join('')); } } catch (err) { return null; } } static freeGrcCountdown(elm) { // 'Wait for 53:31 before next roll' => 53 try { let val = elm.innerText.split(':')[0]; val = val.replace(/[^\d.-]/g, ''); return parseInt(val); } catch (err) { return null; } } static bestChangeCountdown(elm) { // '00:58:35' => 58 try { if (elm.value) { let timeLeft = elm.value.split(':'); if (timeLeft.length > 1) { return parseInt(timeLeft[1]); } } } catch (err) { return null; } } static freeEthereumIoClaimed(elm) { // 'You won 0.12341234 TRX and rolled number 7623' => 0.12341234 try { let line = elm.innerHTML; let idx = line.search(/0\./); return parseFloat(line.slice(idx, idx + 10)); } catch (err) { } } static bfBoxClaimed(elm) { try { let currency = elm.querySelector('.free-box__withdraw-currency').innerText; let val = elm.querySelector('.free-box__need-sum').innerText.replace(/ /g,'').split('/')[1]; if (currency == 'Satoshi') { val = val/100000000; } return val; } catch (err) { return null; } } static g8ClaimsLeft(elm) { try { if (elm.innerText.includes('\nYou have ')) { // 'Claim 183848 satoshi (0.00012 USD) every 20 Seconds\nYou have 70 claims left today.' let val = elm.innerText.split('\nYou have ')[1].split(' ')[0]; return val; } else { return null; } } catch (err) { return null; } } static cbgClaimed(elm) { try { if (elm.innerText.includes('was sent to')) { //?? was sent to you on... let val = elm.innerText.trim().split(' ')[0]; if (elm.innerText.includes('oshi') || elm.innerText.includes('gwei')) { val = val/100000000; } return val; } else { return null; } } catch (err) { return null; } } static dutchysClaimed(elm) { // 'You Won :101 DUTCHY + 20 XP' => 101 try { let splitted = elm.innerText.split('DUTCHY'); return splitted[0].replace(/[^\d.-]/g, ''); } catch (err) { shared.devlog(`@Parsers.dutchysClaimed, with element [${elm}] Error: ${err}`); } } static dutchysClaimedToFloat(elm) { // 'You Won :22437 ADA + 100 XP' => 0.00022437 try { let sats = elm.innerText.split('+'); sats = sats[0].replace(/\D/g, ''); return sats / 100000000; } catch (err) { shared.devlog(`@Parsers.dutchysClaimedToFloat, with element [${elm}] Error: ${err}`); } } static splitAndIdxToInt(elm, options) { // options: { splitter: ':', idx: 1} // '26 Minutes 23' w/spliiter='Minutes' => 26 try { return parseInt(elm.innerText.split(options.splitter)[options.idx].trim()); } catch (err) { shared.devlog(`Error @Parsers.splitAndIdxToInt: ${err}`); } } static fromTextTimer(elm) { // '0 hours 11 minutes 1 seconds' => 12 minutes try { let hours, minutes; hours = +elm.innerText.split(' hours')[0].trim(); minutes = +elm.innerText.split('hours ')[1].split('minutes')[0].trim(); return hours * 60 + minutes + 1; } catch (err) { shared.devlog(`Error @Parsers.splitAndIdxToInt: ${err}`); } } } class ImageProcessor { constructor(img) { this._img = img; } isImageComplete() { return this._img && this._img.complete; } createDrawer(width, height) { let canvas = document.createElement('canvas'); canvas.setAttribute('width', width); canvas.setAttribute('height', height); let ctx = canvas.getContext('2d'); return { canvas: canvas, ctx: ctx }; } getDrawer() { return this._drawer; } toCanvas() { this._drawer = this.createDrawer(this._img.width, this._img.height); this._drawer.ctx.drawImage(this._img, 0, 0); } foreach(filter) { let imgData = this._drawer.ctx.getImageData(0, 0, this._drawer.canvas.width, this._drawer.canvas.height); for (var x = 0; x < imgData.width; x++) { for (var y = 0; y < imgData.height; y++) { var i = x * 4 + y * 4 * imgData.width; var pixel = { r: imgData.data[i + 0], g: imgData.data[i + 1], b: imgData.data[i + 2] }; pixel = filter(pixel); imgData.data[i + 0] = pixel.r; imgData.data[i + 1] = pixel.g; imgData.data[i + 2] = pixel.b; imgData.data[i + 3] = 255; } } this._drawer.ctx.putImageData(imgData, 0, 0); } binarize (threshold) { var image = this._drawer.canvas.getContext('2d').getImageData(0, 0, this._drawer.canvas.width, this._drawer.canvas.height); for (var x = 0; x < image.width; x++) { for (var y = 0; y < image.height; y++) { var i = x * 4 + y * 4 * image.width; var brightness = 0.34 * image.data[i] + 0.5 * image.data[i + 1] + 0.16 * image.data[i + 2]; image.data[i] = brightness >= threshold ? 255 : 0; image.data[i + 1] = brightness >= threshold ? 255 : 0; image.data[i + 2] = brightness >= threshold ? 255 : 0; image.data[i + 3] = 255; } } this._drawer.canvas.getContext('2d').putImageData(image, 0, 0); } invert(filter) { this.foreach(function (p) { p.r = 255 - p.r; p.g = 255 - p.g; p.b = 255 - p.b; return p; }); } imgDataToBool(imgData) { let character = []; const data = imgData.data; for (let i = 0; i < imgData.data.length; i += 4) { let val = data[i] + data[i+1] + data[i+2]; character.push(val == 0 ? true : false); } return character; } } class CaptchaWidget extends CrawlerWidget { constructor(params) { super(params); } solve() { return true; } async isSolved() { return false; } } class RecaptchaWidget extends CaptchaWidget { constructor(params) { let defaultParams = { selector: function() { return grecaptcha }, waitMs: [1000, 5000], timeoutMs: 4 * 60 * 1000 }; for (let p in params) { defaultParams[p] = params[p]; } super(defaultParams); } get isUserFriendly() { this.element = grecaptcha; return this.element; } async isSolved() { return wait().then( () => { try { if (this.isUserFriendly && this.element.hasOwnProperty('getPageId') && this.element.getPageId() && this.element.hasOwnProperty('getResponse') && (typeof(this.element.getResponse) == 'function') && this.element.getResponse().length > 0) { return Promise.resolve(true); } } catch (err) {} return this.isSolved(); }); } } class HCaptchaWidget extends CaptchaWidget { constructor(params) { let defaultParams = { selector: '.h-captcha > iframe', waitMs: [1000, 5000], timeoutMs: 4 * 60 * 1000 }; for (let p in params) { defaultParams[p] = params[p]; } super(defaultParams); } async isSolved() { return wait().then( () => { if (this.isUserFriendly && this.element.hasAttribute('data-hcaptcha-response') && this.element.getAttribute('data-hcaptcha-response').length > 0) { return Promise.resolve(true); } return this.isSolved(); }); } } class BKCaptchaWidget extends CaptchaWidget { constructor() { let defaultParams = { selector: 'img[src="antibot.php"]', waitMs: [1000, 5000], timeoutMs: 4 * 60 * 1000 }; super(defaultParams); this._imgProcessor; this._characters = []; } charList() { return [{"answer":"g","width":8,"height":9,"bools":[false,true,true,true,true,true,false,true,true,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]}, {"answer":"5","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]}, {"answer":"W","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true]}, {"answer":"O","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]}, {"answer":"N","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,true,false,false,false,true,true,true,true,true,true,false,false,true,true,true,true,true,true,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,true,true,true,true,true,true,false,false,false,true,true,true,true,true,false,false,false,true,true,true,true,true,false,false,false,false,true,true]}, {"answer":"T","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]}, {"answer":"q","width":8,"height":9,"bools":[false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true]}, {"answer":"l","width":4,"height":10,"bools":[true,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,true,true,true,true]}, {"answer":"B","width":8,"height":10,"bools":[true,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,false]}, {"answer":"3","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false,false]}, {"answer":"s","width":8,"height":7,"bools":[false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]}, {"answer":"p","width":8,"height":9,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]}, {"answer":"L","width":7,"height":10,"bools":[true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]}, {"answer":"Z","width":7,"height":10,"bools":[false,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]}, {"answer":"F","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]}, {"answer":"p","width":8,"height":9,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]}, {"answer":"T","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]}, {"answer":"8","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]}, {"answer":"P","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]}, {"answer":"J","width":6,"height":10,"bools":[false,false,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,true,false,false,false,true,true,true,true,false,true,true,false,false,true,true,true,false,false]}, {"answer":"y","width":8,"height":9,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,true,false,false,false,false,false,true,true,false,true,true,true,true,true,true,false]}, {"answer":"r","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"R","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,false,true,true,true,true,true,false,false,false,true,true,false,false,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"M","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"d","width":8,"height":10,"bools":[false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true]}, {"answer":"E","width":7,"height":10,"bools":[true,true,true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]}, {"answer":"7","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]}, {"answer":"Z","width":7,"height":10,"bools":[true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]}, {"answer":"l","width":4,"height":10,"bools":[true,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,true,true,true,true]}, {"answer":"K","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,false,false,true,true,false,false,true,true,false,true,true,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true]}, {"answer":"6","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,false,false]}, {"answer":"H","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"5","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]}, {"answer":"Y","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]}, {"answer":"d","width":8,"height":10,"bools":[false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true]}, {"answer":"p","width":8,"height":9,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]}, {"answer":"z","width":6,"height":7,"bools":[true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,true,true,false,false,false,true,true,false,false,false,true,true,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true]}, {"answer":"n","width":8,"height":7,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"a","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,true,false,true,true,true,true,false,true,true]}, {"answer":"8","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]}, {"answer":"t","width":8,"height":9,"bools":[false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false]}, {"answer":"q","width":8,"height":9,"bools":[false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true]}, {"answer":"a","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,true,false,true,true,true,true,false,true,true]}, {"answer":"Z","width":7,"height":10,"bools":[true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,true,true]}, {"answer":"1","width":6,"height":10,"bools":[false,false,true,true,false,false,false,true,true,true,false,false,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,true,true,true,true,true,true]}, {"answer":"m","width":8,"height":7,"bools":[true,false,true,true,false,true,true,false,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true]}, {"answer":"l","width":4,"height":10,"bools":[true,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,true,true,true,true]}, {"answer":"q","width":8,"height":9,"bools":[false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true]}, {"answer":"C","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"a","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,true,false,true,true,true,true,false,true,true]}, {"answer":"2","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true,true]}, {"answer":"h","width":8,"height":10,"bools":[true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"F","width":7,"height":10,"bools":[true,true,true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false]}, {"answer":"c","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"P","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false]}, {"answer":"r","width":8,"height":7,"bools":[true,true,false,true,true,true,false,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false]}, {"answer":"Y","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]}, {"answer":"S","width":8,"height":10,"bools":[false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]}, {"answer":"u","width":8,"height":7,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true]}, {"answer":"M","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"S","width":8,"height":10,"bools":[false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]}, {"answer":"g","width":8,"height":9,"bools":[false,true,true,true,true,true,false,true,true,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]}, {"answer":"U","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]}, {"answer":"k","width":7,"height":10,"bools":[true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,true,true,false,true,true,false,true,true,false,false,true,true,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,false,false,true,true,false,false,true,true,false,true,true,false,false,false,true,true]}, {"answer":"4","width":8,"height":10,"bools":[false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,false,false,true,true,false,false,true,true,false,true,true,false,false,false,true,true,false,true,true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false]}, {"answer":"A","width":8,"height":10,"bools":[false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"b","width":8,"height":10,"bools":[true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false]}, {"answer":"I","width":6,"height":10,"bools":[true,true,true,true,true,true,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,true,true,true,true,true,true]}, {"answer":"o","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]}, {"answer":"i","width":6,"height":10,"bools":[false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,true,true,true,true,true,true]}, {"answer":"C","width":8,"height":10,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"e","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"w","width":8,"height":7,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,true,true,true,true,true,true,false,true,true,false,false,true,true,false]}, {"answer":"f","width":8,"height":10,"bools":[false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false]}, {"answer":"j","width":7,"height":12,"bools":[false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,false]}, {"answer":"F","width":6,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false]}, {"answer":"x","width":8,"height":7,"bools":[true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true]}, {"answer":"e","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"G","width":8,"height":10,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"0","width":8,"height":10,"bools":[false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false]}, {"answer":"0","width":8,"height":10,"bools":[false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false]}, {"answer":"D","width":8,"height":10,"bools":[true,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,false]}, {"answer":"e","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]}, {"answer":"X","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]}, {"answer":"Q","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,true,true,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,true]}]; } async isReady() { return wait().then( () => { let img = document.querySelector(this.selector); if(img && img.complete) { this._imgProcessor = new ImageProcessor(img); return Promise.resolve(true); } return this.isReady(); }); } async isSolved() { return this.isReady() .then( () => this.solve()) .then( (solution) => { document.querySelector('input[name="kodecaptcha"]').value = solution; return Promise.resolve(true); }) .catch(err => { return Promise.reject(`Error ${err}`); }); } preProcessImage() { this._imgProcessor.toCanvas(); this._imgProcessor.binarize(200); this._imgProcessor.invert(); } cropCharacter(startFrom = 0) { let imgData = this._imgProcessor.getDrawer().ctx.getImageData(startFrom, 0, this._imgProcessor.getDrawer().canvas.width - startFrom, this._imgProcessor.getDrawer().canvas.height); let newBounds = { left: null, right:null, top: null, bottom: null }; let readingCharacter = false; let endOfCharacter = null; for (var x = 0; x < imgData.width; x++) { if (endOfCharacter) { newBounds.right = endOfCharacter; break; } let isColumnEmpty = true; for (var y = 0; y < imgData.height; y++) { var i = x * 4 + y * 4 * imgData.width; var pixel = { r: imgData.data[i + 0], g: imgData.data[i + 1], b: imgData.data[i + 2] }; if (pixel.r + pixel.g + pixel.b == 0) { if (newBounds.left == null || newBounds.left > x) { newBounds.left = x; } if (newBounds.right == null || newBounds.right < x) { newBounds.right = x; } if (newBounds.top == null || newBounds.top > y) { newBounds.top = y; } if (newBounds.bottom == null || newBounds.bottom < y) { newBounds.bottom = y; } readingCharacter = true; isColumnEmpty = false; } } if (isColumnEmpty && readingCharacter) { endOfCharacter = x - 1; break; } } return { x: startFrom + newBounds.left, y: newBounds.top, width: newBounds.right - newBounds.left + 1, height: newBounds.bottom - newBounds.top + 1, nextBegins: startFrom + newBounds.right + 1 }; } splitInCharacters() { let chars = []; let i =0; do { chars.push(this.cropCharacter( i== 0 ? 0 : chars[i-1].nextBegins ) ); let copy = document.createElement('canvas').getContext('2d'); copy.canvas.width = chars[i].width; copy.canvas.height = chars[i].height; let trimmedData = this._imgProcessor.getDrawer().ctx.getImageData(chars[i].x, chars[i].y, chars[i].width, chars[i].height); copy.putImageData(trimmedData, 0, 0); chars[i].bools = this._imgProcessor.imgDataToBool(trimmedData); chars[i].dataUrl = copy.canvas.toDataURL("image/png"); i++; } while(i < 5); this._characters = chars; } guess(charElm) { let bestGuess = { answer: '', blacksMatched: 0, blacksMissed: 0, percentageBlacks: 0, exactMatch: false }; let totalPixels = charElm.width * charElm.height; let totalBlacks = charElm.bools.filter(x => x === true).length; this.charList().filter(x => x.answer != '').forEach( function (elm) { if (bestGuess.exactMatch) { return; } if (charElm.width == elm.width && charElm.height == elm.height) { if (charElm.bools.join(',') == elm.bools.join(',')) { bestGuess = { answer: elm.answer, percentageBlacks: 100, exactMatch: true }; return; } let blacksMatched = 0; let blacksMissed = 0; let percentageBlacks = 0; for (let p = 0; p < totalPixels; p++) { if (charElm.bools[p] === true || elm.bools[p] === true) { if (elm.bools[p] == charElm.bools[p]) { blacksMatched++; } else { blacksMissed++; } } } if (blacksMatched != 0 || blacksMissed != 0) { percentageBlacks = blacksMatched/(blacksMatched + blacksMissed); } if (percentageBlacks > bestGuess.percentageBlacks) { bestGuess = { answer: elm.answer, blacksMatched: blacksMatched, blacksMissed: blacksMissed, percentageBlacks: percentageBlacks }; } } }); return bestGuess; } async solve() { let solution = ''; if(this._imgProcessor.isImageComplete()) { this.preProcessImage(); this.splitInCharacters(); this._characters.forEach( ch => { let bestGuess = this.guess(ch); solution += bestGuess.answer; }); } return Promise.resolve(solution); } } class NoCaptchaWidget extends CaptchaWidget { constructor(params) { let defaultParams = { selector: 'svg.feather-check-circle', waitMs: 10000 }; for (let p in params) { defaultParams[p] = params[p]; } super(defaultParams); } async isSolved() { return wait().then( () => { if (this.isUserFriendly) { return Promise.resolve(true); } return this.isSolved(); }); } } class GeeTestCaptchaWidget extends CaptchaWidget { constructor(params) { let defaultParams = { selector: '.geetest_captcha.geetest_lock_success,.geetest_ghost_success.geetest_success_animate', waitMs: 2000 }; for (let p in params) { defaultParams[p] = params[p]; } super(defaultParams); } async isSolved() { return wait().then( () => { if (this.isUserFriendly) { return Promise.resolve(true); } return this.isSolved(); }); } } class CBL01CaptchaWidget extends CaptchaWidget { constructor(params) { let defaultParams = { selector: '', waitMs: 2000 }; for (let p in params) { defaultParams[p] = params[p]; } super(defaultParams); } async isReady() { return wait(1).then( () => { if(this.isUserFriendly) { return Promise.resolve(true); } return wait().then( () => { this.isReady(); }); }); } async solve() { let answer = document.getElementById('captchainput').value; if (answer != '') { if (answer.startsWith('JJJ')) { answer = answer.slice(3); document.getElementById('captchainput').value = answer; } if (answer.length != 6) { document.getElementById('captchainput').value =''; window.location.reload(); return wait(10000).then( () => { this.solve(); }); } else { return wait().then( () => { return true; } ); } } else { return wait().then( () => { this.solve(); }); } } async isSolved() { return this.isReady() .then( () => this.solve()) .then( (solution) => { return Promise.resolve(true); }) .catch(err => { shared.devlog(err); }) } } class D1CaptchaWidget extends CaptchaWidget { constructor() { let defaultParams = { selector: '#submit_captcha span', waitMs: [1000, 5000], timeoutMs: 4 * 60 * 1000 }; super(defaultParams); this.selectors = { submitButton: '#submit', answerSpan: '#submit_captcha span' } this._elements = { submitButton: new ButtonWidget({selector: '#submit'}), answerSpan: new ReadableWidget({selector: '#submit_captcha span'}) }; } async isReady() { return wait().then( () => { if(this._elements.submitButton.isUserFriendly) { return Promise.resolve(true); } return this.isReady(); }); } async solve() { if (this._elements.answerSpan.isUserFriendly) { let answer = this._elements.answerSpan.value; answer = answer ? answer.trim() : answer; let input = document.querySelector(`input[value="${answer}"`); if (input) { helpers.alternativeClick(input.parentElement.querySelector('i')); return wait().then( () => { return true; } ); } else { return Promise.reject(`@D1Captcha input NOT FOUND for answer: ${answer}`); } } else { return Promise.reject('Answer span not found!!!'); } } async isSolved() { return this.isReady() .then( () => this.solve()) .then( (solution) => { return Promise.resolve(true); }) .catch(err => { shared.devlog(err); }) } } class Faucet { constructor(elements, actions = {}) { this._url = window.location.href; this._timeout = new Timeout(); // this.maxSeconds); this._elements = elements; this._actions = { preRun: false, preRoll: false, altValidation: false, readClaimed: true, readBalance: true, readTimeLeft: true, readRolledNumber: false, isMultiClaim: false, checkIfOutOfFunds: false, preSaveResult: false } this._actions = { ...this._actions, ...actions }; this._params = shared.getCurrent().params || {}; this._result = this._actions.isMultiClaim ? (shared.getProp('tempResults') || {}) : (shared.getResult() || {}); } hasCloudflare() { let h2 = document.querySelector('h2#challenge-running'); let stage = document.querySelector('#challenge-stage'); if (h2 || stage) { return true; } return false; } useUrlListener() { if (window.onurlchange === null) { window.addEventListener('urlchange', (data) => { if (this._url != window.location.href) { this._url = window.location.href; this.resetRun(); } }); } } resetRun() { wait().then( () => { this.init(); }); } init() { throw new Error('Init not implemented!'); } login() { throw new Error('Login not implemented!'); //return NEED_TO_LOGIN } async run(action = false) { if (this._actions.checkIfOutOfFunds) { this.checkIfOutOfFunds(); } if (this._actions.preRun) { await wait().then( () => { this.preRun() } );; } if (!action) { this.detectAction().then( (resolve) => { this.perform(resolve.action); }); } else { this.perform(action); } } perform(action) { switch(action) { case 'doRoll': if(this._actions.preRoll) { this.preRoll(); } this._elements.captcha.isSolved().then(() => { this.clickRoll() }); break; case 'needToWait': this.updateResult(); break; default: break; } } async detectAction() { return wait().then( () => { if ( this.isCountdownVisible() ) { return Promise.resolve({action: 'needToWait'}); } else if ( this.isRollButtonVisible() ) { return Promise.resolve({action: 'doRoll'}); } else { return this.detectAction(); } }); } preRoll() { throw new Error('PreRoll not implemented!'); } preRun() { throw new Error('PreRun not implemented!'); } altValidation() { throw new Error('AltValidation not implemented!'); } isCountdownVisible() { return this._elements.countdownMinutes && this._elements.countdownMinutes.isUserFriendly; } isRollButtonVisible() { return this._elements.rollButton && this._elements.rollButton.isUserFriendly; } clickRoll() { try { this._elements.rollButton.element.scrollIntoView(false); this._elements.rollButton.click(); this.validateRun(); } catch (err) { shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err); } } failureValidation() { throw new Error('FailureValidation not implemented!'); } async validateRun() { return wait(this._actions.useFailureValidation ? 6000 : null).then( () => { if (this._actions.useFailureValidation) { if (this.failureValidation()) { return; } } if (this._elements.success?.isUserFriendly) { return this.updateResult(); } else if(this._actions.altValidation) { if(this.altValidation()) { return this.updateResult(); } } return wait(2000).then( () => { this.validateRun() }); }); } async updateResult() { if(this._actions.readClaimed) { this._result.claimed = this.readClaimed(); } if(this._actions.readBalance) { this._result.balance = this.readBalance(); } if(this._actions.readTimeLeft) { this._result.nextRoll = this.readNextRoll(); } if(this._actions.readRolledNumber) { this._result.rolledNumber = this.readRolledNumber(); } if (this._actions.isMultiClaim) { shared.setProp('tempResults', this._result); return this._actions.postRun ? this.postRun() : true; } if (this._actions.preSaveResult) { this.preSaveResult(); } if (this._actions.updateWithoutClosing) { shared.updateWithoutClosing(this._result); return this._actions.postRun ? this.postRun() : true; } else { shared.closeWindow(this._result); } } readNextRoll() { try { if (this._elements.countdownMinutes && this._elements.countdownMinutes.isUserFriendly) { return helpers.addMinutes(this._elements.countdownMinutes.timeLeft); } } catch (err) { shared.devlog(`@readNextRoll: ${err}`); } return null; } readRolledNumber() { let rolled = 0; try { if(this._elements.rolledNumber.isUserFriendly) { rolled = this._elements.rolledNumber.value; } } catch (err) { shared.devlog(`@readRolledNumber: ${err}`); } return rolled; } readBalance() { let balance = 0; try { if(this._elements.balance.isUserFriendly) { balance = this._elements.balance.value; } } catch (err) { shared.devlog(`@readBalance: ${err}`); } return balance; } readClaimed() { //TODO: review if previous claimed should be received as arg let claimed = this._result.claimed ?? 0; if (this._actions.isMultiClaim) { this._oldClaimed = claimed; } else { } try { if(this._elements.claimed.isUserFriendly) { claimed = +claimed + +this._elements.claimed.value; } else { } } catch (err) { shared.devlog(`@readClaimed: ${err}`); } return claimed; } checkIfOutOfFunds() { let divAlerts = [...document.querySelectorAll(this._elements.outOfFundsDivSelector)]; divAlerts.forEach( function (d) { if (d.innerText.toLowerCase().includes('not have sufficient funds')) { shared.closeWithError(K.ErrorType.FAUCET_EMPTY, d.innerText); return; } }); } setCurrentCaptcha() { if ([...document.querySelectorAll('iframe')].map(x => x.src || '').filter(x => x.includes('hcaptcha.com')).length > 0) { return; } this._elements.captcha = new RecaptchaWidget(); } } class BFRoll extends Faucet { constructor(coinPrefix, trySpin = false) { let elements = { preRunButton: new ButtonWidget({selector: '.free-box.free-box__' + coinPrefix + ' button'}), //'#' + coinPrefix + '_free_box_withdraw_page'}), captcha: new NoCaptchaWidget({ selector: '.free-box-withdraw__footer button' }), // .button_red.button_center.button_fullwidth' }), rollButton: new ButtonWidget({selector: '.free-box-withdraw__footer button' }), // .button_red.button_center.button_fullwidth'}), success: new ReadableWidget({selector: '.modal:not(.free-box-withdraw,fury-wheel-modal), .vue-notification-template.my-notify.success'}), claimed: new ReadableWidget({selector: '.free-box.free-box__' + coinPrefix, parser: Parsers.bfBoxClaimed}), progressBar: new ReadableWidget({selector: '.free-box.free-box__' + coinPrefix + ' .free-box__progress-bar progress'}), }; let actions = { preRun: true, readClaimed: true, readBalance: false, readRolledNumber: false }; super(elements, actions); this.coinPrefix = coinPrefix; this.trySpin = trySpin; } init() { if (this._url.includes('https://betfury.io/boxes/all')) { this.run(); return; } else { return; } } async spin() { let clickables = document.querySelectorAll('.fury-wheel__wheel-btn, .fury-wheel__btn-wrap, .fury-wheel__btn-content, .fury-wheel__btn-img'); if (clickables.length > 0) { clickables[Math.floor(Math.random()*clickables.length)].click(); wait(15000).then ( () => { shared.closeWindow(this._result); } ); } return; } async preRun() { return wait().then( () => { try { let popup = document.querySelector('.modal-wrapper .modal:not(.free-box-withdraw,fury-wheel-modal) .modal__btn-close'); if (popup) { popup.click(); popup.click(); // twice } } catch (err) {} if (this.trySpin) { let spinUnavailable = document.querySelector('.bonus.bonus_furywheel.wait'); if (spinUnavailable) { } else { let spinBtn = document.querySelector('.wheel-amin'); //bonus bonus_furywheel wait if (spinBtn) { spinBtn.click(); wait(10000).then ( () => { this.spin() } ); return wait(60000).then ( () => { this.preRun(); } ); } } } if (!this._elements.progressBar || !this._elements.progressBar.isUserFriendly) { return this.preRun(); } if (this._elements.preRunButton.isUserFriendly) { if (!this._elements.preRunButton.isUserFriendly.disabled) { return this._elements.preRunButton.click(); } else { this._timeout.restart(); shared.closeWindow(this._result); return; } } else if (document.querySelectorAll('.free-box').length > 1) { shared.closeWithError(K.ErrorType.ERROR, 'Box might not exist for your account.'); return; } return this.preRun(); }); } async validateRun() { return wait(7000).then( () => { let gtHook = document.querySelector('div.geetest_slice_bg'); if (gtHook) { if (gtHook.isUserFriendly()) { return this.validateRun(); } } let popup = document.querySelector('.modal-wrapper .modal:not(.free-box-withdraw,fury-wheel-modal) .modal__btn-close'); if (!popup) { if (this._elements.preRunButton.isUserFriendly && !this._elements.preRunButton.isUserFriendly.disabled) { this._elements.preRunButton.click(); return this.validateRun(); } } else { try { if (popup) { popup.click(); popup.click(); } } catch (err) {} } if (this._elements.success.isUserFriendly) { return this.updateResult(); } else if(this._actions.altValidation) { if(this.altValidation()) { return this.updateResult(); } } return this.validateRun(); }); } } class DutchyRoll extends Faucet { constructor() { let elements = { countdownMinutes: new CountdownWidget({selector: '#timer', parser: Parsers.splitAndIdxToInt, options: { splitter: 'Minutes', idx: 0} }), // "26 Minutes 23" captcha: new HCaptchaWidget(), rollButton: new ButtonWidget({selector: '#claim'}), //w/booster video: '#unlockbutton' & then #claim_boosted success: new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse'}), claimed: new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.freeEthereumIoClaimed}) //"You Won 0.00409070 TRX + 20 XP" }; let actions = { preRun: true, readClaimed: true, readBalance: false, readRolledNumber: false }; super(elements, actions); } init() { switch(window.location.host) { case 'autofaucet.dutchycorp.space': if (this._url.includes('/roll.php')) { this._elements.claimed = new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.dutchysClaimed}) } else if (this._url.includes('/login.php')) { shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, ''); return; } break; case 'express.dutchycorp.space': if (this._url.includes('/roll.php')) { this._elements.claimed = new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.dutchysClaimed}) } else if (this._url.includes('/coin_roll.php')) { this._elements.claimed = new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.dutchysClaimedToFloat}) } else if (this._url.includes('/index.php')) { shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, 'You need to login using ExpressCrypto (EC-UserId-XXXXXX).'); return; } break; } this.run(); return; } async preRun() { if (this._elements.captcha.isUserFriendly) { if (shared.getConfig()['dutchy.useBoosted']) { this._elements.rollButton = new ButtonWidget({selector: '#unlockbutton'}); this._elements.confirmBoost = new ButtonWidget({selector: '#claim_boosted'}); setInterval(() => { try { if (this._elements.confirmBoost.isUserFriendly) { this._elements.confirmBoost.click(); } } catch (err) {} }, 8000); } return true; } else { this.setCurrentCaptcha(); await wait(); return this.preRun(); } } } class YCoin extends Faucet { constructor() { let elements = { rollButton: new ButtonWidget({selector: 'input[type="submit"][value="Get Free Crypto!"]'}), claimed: new ReadableWidget({selector: 'div.alert.alert-info', parser: Parsers.freeEthereumIoClaimed}), captcha: new HCaptchaWidget(), balance: new ReadableWidget({selector: 'a.wha[href="/account?page=history"]', parser: Parsers.trimNaNs}), success: new ReadableWidget({selector: 'div.alert.alert-info'}), login: { inputUser: new TextboxWidget({ selector: 'input[name="number"]' }), inputPass: new TextboxWidget({ selector: 'input[name="pass"]' }), inputSubmit: new SubmitWidget({ selector: 'input[type="submit"][value="Login!"]' }), setCredentials: false }, }; if(shared.getConfig()['ycoin.credentials.mode'] == 1) { elements.login.setCredentials = { username: shared.getConfig()['ycoin.credentials.username'], password: shared.getConfig()['ycoin.credentials.password'] }; } let actions = { preRun: true, readClaimed: true, readBalance: true, readRolledNumber: false, checkIfOutOfFunds: false }; super(elements, actions); } async preRun() { let msgDiv; msgDiv = document.querySelector('p.info.success'); if (msgDiv && msgDiv.innerText.includes('has been transferred')) { let result = {}; if (msgDiv.innerText.includes('0 claims')) { result.nextRoll = helpers.addMinutes(60 * 24 + helpers.randomInt(10, 50)); } else { result.nextRoll = helpers.addMinutes('60'); } result.claimed = +msgDiv.innerText.split(' ')[0]; result.balance = this.readBalance(); shared.closeWindow(result); return; } msgDiv = document.querySelector('p.info.warn'); if (msgDiv) { if (msgDiv.innerText.includes('can claim only')) { let result = {}; result.nextRoll = helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); shared.closeWindow(result); return; } else if (msgDiv.innerText.includes('Please wait')) { let result = {}; try { let unit = msgDiv.innerText.includes(' seconds') ? ' seconds' : ' minutes'; let val = msgDiv.innerText.split('Please wait ')[1].replace(/\D/g, ''); if (unit == ' seconds') { result.nextRoll = helpers.addSeconds(val); } else { result.nextRoll = helpers.addMinutes(val); } } catch { result.nextRoll = helpers.addMinutes(60); } shared.closeWindow(result); return; } } msgDiv = document.querySelector('p.info.fail'); if (msgDiv) { if (msgDiv.innerText.toLowerCase().includes('run out of bitcoin')) { shared.closeWithError(K.ErrorType.FAUCET_EMPTY, 'Out of Funds'); return; } } if (this._elements.captcha.isUserFriendly) { } else { if (this._elements.rollButton) { this._elements.rollButton.click(); return; } } } async init() { if (this._url.includes('/faucet')) { let needToLoginButton = document.querySelector('input[type="submit"][value="Login / Signup"]'); if (needToLoginButton) { needToLoginButton.click(); return; } this.run(); this.solveColorCaptcha(); return; } else if (this._url.includes('/account')) { this.doLogin(); return; } } async doLogin() { return wait().then( () => { let container = document.querySelector('#cc'); if (container.innerText.includes('You are now logged in as account')) { let toFaucetButton = document.querySelector('#mmenu a[href="/faucet"]'); if (toFaucetButton) { toFaucetButton.click(); return; } return this.doLogin(); } if (!this._elements.login.inputUser.isUserFriendly || !this._elements.login.inputPass.isUserFriendly || !this._elements.login.inputSubmit.isUserFriendly) { return this.doLogin(); } let loginErrorDiv = document.querySelector('#cc .info.fail'); if (loginErrorDiv && loginErrorDiv.innerText.includes('Invalid')) { shared.closeWithError(K.ErrorType.LOGIN_ERROR, loginErrorDiv.innerText); return; } if (this._elements.login.setCredentials != false) { this._elements.login.inputUser.value = this._elements.login.setCredentials.username; this._elements.login.inputPass.value = this._elements.login.setCredentials.password; } try { this._elements.login.rememberMe.isUserFriendly.checked = true; } catch (err) {} if (this._elements.login.inputUser.value != '' && this._elements.login.inputPass.value != '' ) { this._elements.login.inputSubmit.click(); } else { shared.closeWithError(K.ErrorType.LOGIN_ERROR, 'No credentials were provided'); return; } }); } async solveColorCaptcha() { await wait(2000); let optionInputs = [...document.querySelectorAll('#newch input[type="submit"]')]; let options = optionInputs.map(x => x.style.background); let wantedColor = document.querySelector('#newch p b'); if (options.length > 0 && wantedColor) { try { let knownColors = Object.keys(nearestColor.STANDARD_COLORS); let toColorName = nearestColor.from(nearestColor.STANDARD_COLORS); options = options.map(x => toColorName(x).name); wantedColor = wantedColor.innerText.toLowerCase(); if (wantedColor == 'grey') { wantedColor = 'gray'; } let solutionIdx = options.findIndex(x => x.includes(wantedColor)); if (solutionIdx > -1) { optionInputs[solutionIdx].click(); return; } if (wantedColor == 'green') { wantedColor = 'lime'; solutionIdx = options.findIndex(x => x.includes(wantedColor)); if (solutionIdx > -1) { optionInputs[solutionIdx].click(); return; } } await wait(5000); location.reload(); } catch (err) { await wait(15000); location.reload(); } } else { return this.solveColorCaptcha(); } } } class CDiversity extends Faucet { constructor() { let elements = { claimed: new ReadableWidget({selector: 'p.success', parser: Parsers.trimNaNs}), captcha: new HCaptchaWidget(), rollButton: new ButtonWidget({selector: 'input[type="submit"][value="Get Free Crypto!"]'}), }; let actions = { readTimeLeft: true, readRolledNumber: false, readBalance: false }; super(elements, actions); } init() { if(this.hasErrorMessage()) { shared.closeWithError(K.ErrorType.ERROR, 'Suspicious Activity Message Displayed'); return; } let claimed = this.readClaimed(); if (claimed != 0) { let result = { claimed: claimed, nextRoll: this.readNextRoll() }; shared.closeWindow(result); return; } let nextRoll = this.readNextRoll(); if(nextRoll) { let result = { nextRoll: nextRoll }; shared.closeWindow(result); return; } this.solve(); } hasErrorMessage() { return document.body.innerText.toLowerCase().includes('suspicious activity'); } isFirstStep() { return document.querySelector('form select[name="coin"]') ? true : false; } async doFirstStep() { let form = document.querySelector('form'); if (!form) { this.updateResult(); return; } let coinSelect = form.querySelector('select[name="coin"]'); if (!coinSelect) { this.updateResult(); return; } let userInput = form.querySelector('input[name="ado"]'); if (!userInput) { this.updateResult(); return; } let submitButton = form.querySelector('input[type="submit"]'); if (!submitButton) { this.updateResult(); return; } coinSelect.value = this.getCoin(); userInput.value = this._params.address; submitButton.parentElement.submit(); return; } getCoin() { try { let tds = document.querySelectorAll('table tr td:nth-child(2)'); return tds[helpers.randomInt(0, 5)].innerText.split(' ')[1] } catch (err) { return 'BTC'; } } isSecondStep() { let ps = [...document.querySelectorAll('p')]; return ps.findIndex(x => x.innerText.toLowerCase().includes('one more step...')) >= 0; } async solve() { if (this.isSecondStep()) { return this.run(); } if (this.isFirstStep()) { return this.doFirstStep(); } } isCountdownVisible() { let successDiv = document.querySelector('p.success'); if (!successDiv) { return false; } if (successDiv.innerText.includes('0 claims')) { return true; } return false; } readClaimed() { let successDiv = document.querySelector('p.success'); if (successDiv) { return successDiv.innerText.split(' ')[0]; } else { return 0; } } readNextRoll() { try { let successDiv = document.querySelector('p.success'); if (successDiv && successDiv.innerText.includes('You have')) { let claimsLeft; try { claimsLeft = successDiv.innerText.split(' claims')[0].split('have ')[1]; } catch (err) {} if (claimsLeft) { return helpers.addMinutes(helpers.randomInt(6, 22)); } else if (claimsLeft === '0') { return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } } } catch (err) { } try { let warnDiv = document.querySelector('p.warn'); if (warnDiv) { if (warnDiv.innerText.includes('You can claim only')) { return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } if (warnDiv.innerText.includes('Please wait ')) { try { let unit = warnDiv.innerText.includes(' seconds') ? ' seconds' : ' minutes'; let val = warnDiv.innerText.split('Please wait ')[1].split(unit)[0].replace(/\D/g, ''); if (unit == ' seconds') { return helpers.addSeconds(val); } else { return helpers.addMinutes(val); } } catch { } let claimsLeft; try { claimsLeft = warnDiv.innerText.split(' seconds')[0].split('wait ')[1]; } catch (err) {} if (claimsLeft) { return helpers.addMinutes(helpers.randomInt(6, 22)); } } } } catch (err) { } return null; } } class CTop extends Faucet { constructor() { let elements = { claimed: new ReadableWidget({selector: 'p.success', parser: Parsers.trimNaNs}), captcha: new HCaptchaWidget(), rollButton: new ButtonWidget({selector: 'input[type="submit"]'}), addressInput: new TextboxWidget({ selector: 'form input[name="adr"], form input[name="a"]'}) }; let actions = { readTimeLeft: true, readRolledNumber: false, readBalance: false }; super(elements, actions); } init() { if(this.hasErrorMessage('suspicious activity')) { shared.closeWithError(K.ErrorType.ERROR, 'Suspicious Activity Message Displayed'); return; } if(this.hasErrorMessage('no funds left')) { shared.closeWithError(K.ErrorType.FAUCET_EMPTY, 'Out of Funds'); return; } if(this.hasErrorMessage('faucet is currently disabled')) { shared.closeWithError(K.ErrorType.FAUCET_EMPTY, 'Faucet is disabled'); return; } let claimed = this.readClaimed(); if (claimed != 0) { let result = { claimed: claimed, nextRoll: this.readNextRoll() }; shared.closeWindow(result); return; } let nextRoll = this.readNextRoll(); if(nextRoll) { let result = { nextRoll: nextRoll }; shared.closeWindow(result); return; } this.solve(); } hasErrorMessage(searchTerm) { return document.body.innerText.toLowerCase().includes(searchTerm); } isFirstStep() { return this._elements.addressInput.isUserFriendly; } async doFirstStep() { let form = document.querySelector('form'); if (!form) { this.updateResult(); return; } if (!this._elements.addressInput.isUserFriendly) { this.updateResult(); return; } let submitButton = form.querySelector('input[type="submit"]'); if (!submitButton) { this.updateResult(); return; } this._elements.addressInput.value = this._params.address; submitButton.closest('form').submit(); return; } isSecondStep() { let ps = [...document.querySelectorAll('p')]; return ps.findIndex(x => x.innerText.toLowerCase().includes('one more step...')) >= 0; } async solve() { if (this.isSecondStep()) { return this.run(); } if (this.isFirstStep()) { return this.doFirstStep(); } } isCountdownVisible() { let successDiv = document.querySelector('p.success'); if (!successDiv) { return false; } if (successDiv.innerText.includes('0 claims')) { return true; } return false; } readClaimed() { let successDiv = document.querySelector('p.success'); if (successDiv) { return successDiv.innerText.split(' ')[0]; } else { return 0; } } readNextRoll() { try { let successDiv = document.querySelector('p.success'); if (successDiv && successDiv.innerText.includes('You have')) { let claimsLeft; try { claimsLeft = successDiv.innerText.split(' claims')[0].split('have ')[1]; } catch (err) {} if (claimsLeft) { return helpers.addMinutes(helpers.randomInt(12, 22)); } else if (claimsLeft === '0') { return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } } } catch (err) { } try { let warnDiv = document.querySelector('p.warn'); if (warnDiv) { if (warnDiv.innerText.includes('You can claim only')) { return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } if (warnDiv.innerText.includes('Please wait ')) { try { let unit = warnDiv.innerText.includes(' seconds') ? ' seconds ' : ' minutes '; let val = warnDiv.innerText.split('Please wait ')[1].split(unit)[0].replace(/\D/g, ''); if (unit == ' seconds ') { return helpers.addSeconds(val + helpers.randomInt(90, 180)); } else { return helpers.addMinutes(val + helpers.randomInt(1, 5)); } } catch { } let claimsLeft; try { claimsLeft = warnDiv.innerText.split(' seconds')[0].split('wait ')[1]; } catch (err) {} if (claimsLeft) { return helpers.addMinutes(helpers.randomInt(12, 22)); } } } } catch (err) { } return null; } } class FPB extends Faucet { constructor(sitePrefix = null) { let elements = { rollButton: new ButtonWidget({selector: 'input[type="submit"][value="Claim From Faucet"],input[type="submit"][name="claim"]'}), claimed: new ReadableWidget({selector: 'div.alert.alert-info', parser: Parsers.freeEthereumIoClaimed}), captcha: new HCaptchaWidget(), success: new ReadableWidget({selector: 'div.alert.alert-info'}), login: { inputUser: new TextboxWidget({ selector: 'input[name="user_name"]' }), inputPass: new TextboxWidget({ selector: 'input[name="password"]' }), rememberMe: new TextboxWidget({ selector: 'input[name="remember_me"]' }), inputSubmit: new ButtonWidget({ selector: 'input[type="submit"][name="login"]' }), setCredentials: false }, outOfFundsDivSelector: '.alert.alert-info' }; if(shared.getConfig()[sitePrefix + '.credentials.mode'] == 1) { elements.login.setCredentials = { username: shared.getConfig()[sitePrefix + '.credentials.username'], password: shared.getConfig()[sitePrefix + '.credentials.password'] }; } let actions = { readClaimed: true, readBalance: false, readRolledNumber: false, checkIfOutOfFunds: true }; super(elements, actions); } init() { if (this._url.includes('/dashboard')) { this.run(); return; } else if (this._url.includes('/login')) { this.doLogin(); return; } } async doLogin() { return wait().then( () => { if (!this._elements.login.inputUser.isUserFriendly || !this._elements.login.inputPass.isUserFriendly || !this._elements.login.inputSubmit.isUserFriendly) { return this.doLogin(); } let loginErrorDiv = document.querySelector('div.alert.alert-info'); if (loginErrorDiv && loginErrorDiv.innerText.includes('not valid')) { shared.closeWithError(K.ErrorType.LOGIN_ERROR, loginErrorDiv.innerText); return; } if (this._elements.login.setCredentials != false) { this._elements.login.inputUser.value = this._elements.login.setCredentials.username; this._elements.login.inputPass.value = this._elements.login.setCredentials.password; } try { this._elements.login.rememberMe.isUserFriendly.checked = true; } catch (err) {} if (this._elements.login.inputUser.value != '' && this._elements.login.inputPass.value != '' ) { this._elements.captcha.isSolved().then(() => { this._elements.login.inputSubmit.click(); return; }); } else { shared.closeWithError(K.ErrorType.LOGIN_ERROR, 'No credentials were provided'); return; } }); } async detectAction() { return wait().then( () => { if ( this.isCountdownVisible() ) { return Promise.resolve({action: 'needToWait'}); } else if ( this._elements.success.isUserFriendly ) { return this.updateResult(); } else if ( this.isRollButtonVisible() ) { return Promise.resolve({action: 'doRoll'}); } else { return this.detectAction(); } }); } clickRoll() { try { try { window.scrollTo(0, document.body.scrollHeight); } catch (err) { } this._elements.rollButton.click(); setTimeout( () => { this._elements.rollButton.click(); }, 5000); } catch (err) { shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err); } } } class VieRoll extends Faucet { constructor() { let elements = { rollButton: new SubmitWidget({selector: '.main-content button[type="submit"]'}), claimed: new ReadableWidget({selector: '.swal2-html-container', parser: Parsers.trimNaNs}), captcha: new HCaptchaWidget(), success: new ReadableWidget({selector: '.swal2-success-ring'}), login: { inputUser: new TextboxWidget({ selector: '#email' }), inputPass: new TextboxWidget({ selector: '#password' }), inputSubmit: new SubmitWidget({ selector: 'button[type="submit"]' }) } }; let actions = { readClaimed: true, readBalance: false, readTimeLeft: false, readRolledNumber: false, preSaveResult: false, preRun: true }; super(elements, actions); } getClaimsQty() { let statWidgets = document.querySelectorAll('.card.mini-stats-wid'); if (statWidgets.length < 4) return false; let claimCounts = statWidgets[3].querySelector('p'); if (!claimCounts) return false; claimCounts = claimCounts.innerText.split('/'); if (claimCounts.length != 2) return false; return claimCounts[0]; } async evalClaimsQty() { let current = this.getClaimsQty(); if (current) { current = +current; } else { return; } let previous = await shared.getProp('tempClaimsQty') || 0; if (!isNaN(previous)) previous = +previous; if (current == previous) { return; } else if (current < previous) { return this.updateResult(); } else { await shared.setProp('tempClaimsQty', current); } } readClaimed() { let claimed = 0.12; try { claimed = +document.querySelectorAll('.card.mini-stats-wid')[2].querySelector('p').innerText.split(' ')[0]; } catch (err) { } return claimed; } async init() { await this.evalClaimsQty(); if (window.location.pathname.includes('/faucet')) { this.run(); return; } else if (window.location.pathname.includes('/firewall')) { this.solveFirewall(); return; } else if (window.location.pathname.includes('/dashboard')) { window.location.href = (new URL('faucet', window.location)).href; return; } else if (window.location.pathname == '/') { let loginBtn = document.querySelector('.btn.btn-success'); if (loginBtn) { loginBtn.click(); return; } else { window.location.href = (new URL('login', window.location)).href; } return; } else if (this._url.includes('/login')) { let credentialsMode = this._params.credentials.mode; switch(credentialsMode) { case -1: shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, 'Manual login required.'); break; case 0: shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, 'Login required and autologin is not configured.'); break; default: this.doLogin(); break; } return; } } async preRun() { return; } async solveFirewall() { this.closeSwal(); this._elements.captcha.isSolved().then(() => { let btn = new SubmitWidget({selector: 'form:not(.p-3) button[type="submit"]'}); btn.click(); }); } async doLogin() { return wait().then( () => { if (!this._elements.login.inputUser.isUserFriendly || !this._elements.login.inputPass.isUserFriendly || !this._elements.login.inputSubmit.isUserFriendly) { return this.doLogin(); } let loginErrorDiv = document.querySelector('div.alert.alert-danger'); if (loginErrorDiv) { shared.closeWithError(K.ErrorType.LOGIN_ERROR, loginErrorDiv.innerText); return; } if (this._params.credentials.mode == 1) { this._elements.login.inputUser.value = this._params.credentials.username; this._elements.login.inputPass.value = this._params.credentials.password; } if (this._elements.login.inputUser.value != '' && this._elements.login.inputPass.value != '' ) { this._elements.captcha.isSolved().then(() => { this._elements.login.inputSubmit.click(); return; }); } else { shared.closeWithError(K.ErrorType.LOGIN_ERROR, 'No credentials were provided'); return; } }); } preSaveResult() { this.closeSwal(); } closeSwal() { let okButton = document.querySelector('button.swal2-confirm'); if (okButton) { okButton.click(); } } } class GRCRoll extends Faucet { constructor() { let elements = { countdownMinutes: new CountdownWidget({selector: '#roll_wait_text', parser: Parsers.freeGrcCountdown}), rollButton: new ButtonWidget({selector: 'input[id="roll_button"]'}), balance: new ReadableWidget({selector: '#balance', parser: Parsers.trimNaNs}), claimed: new ReadableWidget({selector: '#roll_comment .won', parser: Parsers.trimNaNs}), rolledNumber: new ReadableWidget({selector: '#roll_result', parser: Parsers.trimNaNs}), captcha: new NoCaptchaWidget({selector: '#roll_button'}), success: new ReadableWidget({selector: '#roll_result'}) }; let actions = { readTimeLeft: true, readRolledNumber: true }; super(elements, actions); } init() { if (this._url.includes('#free_roll')) { if (document.querySelectorAll('a[href="#login"]').length > 0) { shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, ''); return; } else { this.run(); return; } } else { return; } } isCountdownVisible() { return this._elements.countdownMinutes && this._elements.countdownMinutes.isUserFriendly && this._elements.countdownMinutes.isUserFriendly.innerText != ''; } } class O24Roll extends Faucet { constructor() { let elements = { claimed: new ReadableWidget({selector: '#roll_comment .won', parser: Parsers.trimNaNs}) }; let actions = { readTimeLeft: true, readRolledNumber: false, readBalance: false }; super(elements, actions); this._isFMonster = location.host === 'faucet.monster'; } init() { if(this.hasErrorMessage('no funds left')) { shared.closeWithError(K.ErrorType.FAUCET_EMPTY, 'Out of Funds'); return; } if (this.isCountdownVisible() || this.readClaimed() != 0) { this.updateResult(); return; } this.solve(); } hasErrorMessage(searchTerm) { return document.body.innerText.toLowerCase().includes(searchTerm); } getSpotsAvailable() { try { let soldSpots = document.querySelectorAll('.pos:not(.pfree)').length; let available = 1024-soldSpots; return { sold: '' + soldSpots, available: '' + available } } catch (err) { } } isPrime(num) { for(var i = 2; i < num; i++){ if(num % i === 0){ return false; } } return num > 1; } async solve() { let spots; spots = this.getSpotsAvailable(); if(!this._isFMonster && !spots) { this.updateResult(); return; } const findNotPrime = document.querySelector('select[name="pr"]').parentElement.innerText.includes('not a prime') let numbers = [...document.querySelectorAll('select[name="pr"] option[value]')].map(x => x.innerText) let prime = null; if (findNotPrime) { prime = numbers.find(x => { return !this.isPrime(x) }); } else { prime = numbers.find(x => { return this.isPrime(x) }); } if(!prime) { this.updateResult(); return; } let addrInput = document.querySelector('label input[name="a"]'); if (addrInput) { addrInput.value = this._params.address; } else { this.updateResult(); return; } await wait(helpers.randomInt(1500, 3000)); if (this._isFMonster) { let usdtQuestion = document.querySelector('form p:nth-child(2)'); if (!usdtQuestion || !usdtQuestion.innerText.toLowerCase().includes('faucet monitor lists tether faucets')) { this.updateResult(); return; } let usdtAnswersList = [...document.querySelectorAll('select[name="fm"] option')]; if (usdtAnswersList.length == 0) { this.updateResult(); return; } usdtAnswersList = usdtAnswersList.map(x => x.value); let idxCorrect = usdtAnswersList.findIndex(x => x.toLowerCase() == 'yes' || x.toLowerCase() == 'y'); if (idxCorrect === -1) { this.updateResult(); return; } document.querySelector('select[name="fm"]').value = usdtAnswersList[idxCorrect]; } else { let answersList = [...document.querySelectorAll('select[name="tt"] option')].map(x => x.value); if (answersList.includes(spots.sold)) { document.querySelector('select[name="tt"]').value=spots.sold; } else if (answersList.includes(spots.available)) { document.querySelector('select[name="tt"]').value=spots.available; } else { this.updateResult(); return; } } await wait(helpers.randomInt(400, 5000)); let primeSelect = document.querySelector('select[name="pr"]'); helpers.triggerMouseEvent (primeSelect, "mouseenter"); await wait(helpers.randomInt(5600, 29000)); helpers.triggerMouseEvent (primeSelect, "mouseout"); primeSelect.value=prime.toString() await wait(helpers.randomInt(1500, 5000)); let claimForm = document.querySelector('form'); if(claimForm) { claimForm.submit(); } } isCountdownVisible() { let pars = [...document.querySelectorAll('p')]; if (pars.find(x => x.innerText.includes('wait until next day'))) { return true; } if (pars.find(x => x.innerText.includes('PROBLEM'))) { return true; } return false; } readClaimed() { let pars = [...document.querySelectorAll('p')]; let claimedElm = pars.find(x => x.innerText.includes('been transferred to your account')); if (claimedElm) { return claimedElm.innerText.split(' ')[0]; } else { return 0; } } readNextRoll() { try { let pars = [...document.querySelectorAll('p')]; if (pars.find(x => x.innerText.includes('until next day') || x.innerText.includes('ALL DAILY CLAIMS') || x.innerText.includes('You have 0 claims left'))) { return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } if (pars.find(x => x.innerText.includes('PROBLEM'))) { return helpers.addMinutes(helpers.randomInt(6, 22)); } if (pars.find(x => x.innerText.includes('You have'))) { return helpers.addMinutes(helpers.randomInt(6, 22)); } } catch (err) { shared.devlog(`@readNextRoll: ${err}`); } return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } } class FCryptoRoll extends Faucet { constructor() { let elements = { countdownMinutes: new CountdownWidget({selector: '.sidebar-links .cursor-not-allowed span.notranslate', parser: Parsers.splitAndIdxToInt, options: { splitter: ':', idx: 1} }), // '00:21:28' rollButton: new ButtonWidget({selector: '.flex.justify-center button.inline-flex.items-center:not(.hidden)'}), balance: new ReadableWidget({selector: 'div.flex.badge.text-bg-yellow', parser: Parsers.trimNaNs}), // '405.81 Coins' claimed: new ReadableWidget({selector: 'div.ml-3.w-0 p span.text-yellow-500.font-medium', parser: Parsers.splitAndIdxTrimNaNs, options: { splitter: '(', idx: 0} }), // '25.05 Coins (12 + 13.05)' captcha: new HCaptchaWidget({selector: '#hcap-script > iframe'}), success: new ReadableWidget({selector: 'div.ml-3.w-0 p span.text-yellow-500.font-medium'}) }; let actions = { isMultiClaim: true, preRoll: true, postRun: true, readRolledNumber: false, }; super(elements, actions); this._paths = { faucet: '/task/faucet-claim', dashboard: '/dashboard' }; this._linkSelectors = { Faucet: 'a[href="https://faucetcrypto.com/task/faucet-claim"]' } this.useUrlListener(); } init() { this._elements.captcha = new HCaptchaWidget({selector: '#hcap-script > iframe'}); this._elements.rollButton = new ButtonWidget({selector: '.flex.justify-center button.inline-flex.items-center:not(.hidden)'}); if (this._url.endsWith(this._paths.dashboard)) { return this.runDashboard(); } else if (this._url.includes(this._paths.faucet)) { return wait().then( () => { this.run(); }); } return; } readSections() { let sections = {}; try { for (var l in this._linkSelectors) { sections[l] = {}; sections[l].elm = document.querySelector(this._linkSelectors[l]); if (sections[l].elm) { let qty = sections[l].elm.querySelector('span.ml-auto'); sections[l].qty = (qty && !isNaN(qty.innerText)) ? qty.innerText : 0; } } } catch {} this.sections = sections; } runDashboard() { this.readSections(); if (this.sections['Faucet'].elm) { this.sections['Faucet'].elm.click(); return; } else { return wait().then( () => { this.run(); }); } } scrollTo() { let mainContainer = document.querySelector('main'); if (mainContainer) { mainContainer.scrollTo(0, mainContainer.scrollHeight - mainContainer.offsetHeight); } } preRoll() { // search for 'You don't need to solve any captcha! The system is telling me that you are a good person :)' this.scrollTo(); let checkCircleSpan = document.querySelector('p.font-medium.flex.justify-center.leading-0 span.text-green-500.mr-3 svg'); if(checkCircleSpan) { if (checkCircleSpan.parentElement.parentElement.innerText.toLowerCase().includes('the system is telling me that you are a good person')) { this._elements.captcha = new NoCaptchaWidget({selector: '.flex.justify-center button.inline-flex.items-center:not(.hidden)'}); return; } } } postRun() { if (this._url.endsWith(this._paths.dashboard) || this._oldClaimed != this._result.claimed) { try { this._elements.claimed.isUserFriendly.parentElement.parentElement.parentElement.querySelector('button'); } catch (err) { } this._oldClaimed = null; this.readSections(); if (this.sections != {}) { if (this.sections['Faucet'].elm) { this.sections['Faucet'].elm.click(); return; } else { } } else { } } else { } this._result = shared.getProp('tempResults'); shared.closeWindow(this._result); return; } async runPtcList() { let listItems = [...document.querySelectorAll('.grid.grid-responsive-3 .feather.feather-eye')].map(x => x.parentElement.parentElement).filter(x => x.isUserFriendly()); if (listItems.length > 0) { listItems[0].click(); return; } else { return wait().then( () => { this.runPtcList() } ); } } runPtcSingleStart() { return this.run('doRoll'); } runPtcSingleWait() { this._elements.captcha = new NoCaptchaWidget({selector: 'a.notranslate:not(.cursor-not-allowed)' }); this._elements.rollButton = new ButtonWidget({selector: 'a.notranslate:not(.cursor-not-allowed)' }); return this.run('doRoll'); } } class FPPtc extends Faucet { constructor() { let elements = { claimButton: new ButtonWidget({selector: '#pop-up button.purpleButton:not([disabled])'}), claimButtonDisabled: new ButtonWidget({selector: '#pop-up button.purpleButton'}), openPtcButton: new ButtonWidget({fnSelector: function() { let blacklistTitles = ['JOIN US ON WINTOMATO.COM']; let btn = [...document.querySelectorAll('button')].filter(x => x.innerText.toLowerCase().includes('view')); try { btn = btn.filter(x => !blacklistTitles.includes(x.parentElement.parentElement.querySelector('h2').innerText.toUpperCase())); } catch (err) {} return (btn.length > 0) ? btn[0] : null; }}), claimed: new ReadableWidget({fnSelector: function() { let divSpanSuccessClaim = [...document.querySelectorAll('div span')].filter(x => x.innerText.toLowerCase().includes('successfully credited with')); return (divSpanSuccessClaim.length > 0) ? divSpanSuccessClaim[0] : null; }, parser: Parsers.trimNaNs}), captcha: new GeeTestCaptchaWidget(), success: new ReadableWidget({selector: 'div.ml-3.w-0 p span.text-yellow-500.font-medium'}) }; let actions = { isMultiClaim: true, preRoll: true, postRun: true, readRolledNumber: false, }; super(elements, actions); this._paths = { ptcList: '/ptc', ptcSingleView: '/ptc/view', login: '/account/login', dashboard: '/user-admin' }; this.useUrlListener(); } init() { if (this._url.includes(this._paths.ptcSingleView)) { this.doPtcList(true); return; } else if (this._url.includes(this._paths.ptcList)) { this.doPtcList(); return; } else if (this._url.includes(this._paths.login)) { this.doLogin(); return; } else if (this._url.includes(this._paths.dashboard)) { return; } return; } hasExpired() { return document.body.innerText.includes('The session has expired'); } hasError() { return document.body.innerText.includes('must finish watching') || document.title.includes('Tab Closed Error'); } getETAWaitSeconds(btn) { try { let seconds = btn.nextSibling.firstChild.innerText.split('s')[0]; return +seconds; } catch (err) { } return 15; } getPayout(btn) { this.lastClaimed = 0; try { let payout = btn.nextSibling.lastChild.innerText.split(' ')[0]; this.lastClaimed = +payout; } catch (err) { } } async validateClaim() { await wait(1000); if (this.hasExpired()) { console.info('CLAIM => expired'); await wait(2000); return false; } if (this._elements.claimed.isUserFriendly) { let claimed = this._elements.claimed.value; if (claimed) { console.info('CLAIM => Returning claimed:', claimed); await this.storeClaim(); await wait(2000); return claimed; } } console.info('@validateClaim => Still waiting...'); return this.validateClaim(); } async storeClaim() { let result = shared.getResult(); result.ptcsDone = (result.ptcsDone ?? 0) + 1; result.claimed = +(result.claimed ?? 0) + +this.lastClaimed; this.lastClaimed = 0; shared.updateWithoutClosing(result, 'WORKING'); } async confirmClaim() { GM_setValue(`ptc-close-signal-faucetpay.io`, Date.now()); await wait(5000); GM_deleteValue(`ptc-close-signal-faucetpay.io`); let captcha = new GeeTestCaptchaWidget(); await captcha.isSolved(); if (!this._elements.claimButton.isUserFriendly) { return; } this._elements.claimButton.click(); let validation = await this.validateClaim(); return this.doPtcList(); } async startPtc() { await wait(1000); let minSeconds = this.getETAWaitSeconds(this._elements.openPtcButton.isUserFriendly); this.getPayout(this._elements.openPtcButton.isUserFriendly); this._elements.openPtcButton.click(); await wait(4000); return this.waitPtcSeconds(); } async waitPtcSeconds() { if (this._elements.claimButtonDisabled.isUserFriendly) { return this.confirmClaim(); } if (!document.title.includes('PTC Ads') && document.title.includes('s |')) { await wait(5000); return this.waitPtcSeconds(); } let iframe = document.querySelector('iframe[title="ptc-view"]'); if (document.title.includes('PTC Ads') && iframe) { await wait(5000); return this.waitPtcSeconds(); } return this.confirmClaim(); } async doPtcList(isSingle = false) { if (document.title.includes('PTC Ads') || document.title.includes('Complete Visit')) { if (this._elements.claimButtonDisabled.isUserFriendly) { return this.confirmClaim(); } else { if(isSingle) { await wait(4000); return this.doPtcList(true); } if (this._elements.openPtcButton.isUserFriendly) { return this.startPtc(); } else { shared.closeWindow(); return; } } } } async doLogin() { let username = document.querySelector('input'); let password = document.querySelector('input[type="password"]'); let captcha = new GeeTestCaptchaWidget(); let btn = document.querySelector('button[type="submit"'); if (username && password && btn && username.value != '' && password.value != '') { await captcha.isSolved(); btn.click(); return; } else { shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, ''); } } } function createFBProcessor() { let countdownMinutes; let timeout = new Timeout(); // this.maxSeconds); let captcha = new HCaptchaWidget(); function run() { setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000)); }; function findCountdownOrRollButton() { if ( isCountdownVisible() ) { timeout.restart(); countdownMinutes = +document.querySelectorAll('.free_play_time_remaining.hasCountdown .countdown_amount')[0].innerHTML + 1; let result = {}; result.balance = readBalance(); result.nextRoll = helpers.addMinutes(countdownMinutes.toString()); shared.closeWindow(result); return; } if ( isRollButtonVisible() ) { try { let doBonus = false; // true; if (doBonus) { if (!document.getElementById('bonus_span_free_wof')) { RedeemRPProduct('free_wof_5'); setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000)); return; } } } catch { } /* For 'Play without captcha accounts' */ if (!captcha.isUserFriendly) { clickRoll() } else { captcha.isSolved().then(() => { clickRoll(); }); } } else { setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000)); } }; function isCountdownVisible() { return document.querySelectorAll('.free_play_time_remaining.hasCountdown .countdown_amount').length > 0; }; function isHCaptchaVisible() { let hCaptchaFrame = document.querySelector('.h-captcha > iframe'); if (hCaptchaFrame && hCaptchaFrame.isVisible()) { return true; } return false; }; function isRollButtonVisible() { return document.getElementById('free_play_form_button').isVisible(); }; function clickRoll() { try { document.getElementById('free_play_form_button').click(); setTimeout(processRunDetails, helpers.randomMs(3000, 10000)); } catch (err) { shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err); } }; function processRunDetails() { if (document.getElementById('winnings').isVisible()) { closePopup(); let result = {}; result.claimed = readClaimed(); result.balance = readBalance(); if(result.claimed != 0) { result.rolledNumber = readRolledNumber(); } shared.closeWindow(result); return; } if (document.querySelector('.free_play_result_error').isVisible()) { shared.closeWithError(K.ErrorType.ROLL_ERROR, document.querySelector('.free_play_result_error').innerHTML); return; } if(document.getElementById('free_play_error').isVisible()) { shared.closeWithError(K.ErrorType.ROLL_ERROR, document.querySelector('.free_play_error').innerHTML); return; } if (document.getElementById('same_ip_error').isVisible()) { shared.closeWithError(K.ErrorType.ROLL_ERROR, document.getElementById('same_ip_error').innerHTML); return; } setTimeout(processRunDetails, helpers.randomMs(5000, 6000)); }; function closePopup() { let closePopupBtn = document.querySelector('.reveal-modal.open .close-reveal-modal'); if (closePopupBtn) { closePopupBtn.click(); } }; function readRolledNumber() { let rolled = 0; try { rolled = parseInt([... document.querySelectorAll('#free_play_digits span')].map( x => x.innerHTML).join('')); } catch { } return rolled; }; function readBalance() { let balance = 0; try { balance = document.getElementById('balance').innerHTML; } catch { } return balance; }; function readClaimed() { let claimed = 0; try { claimed = document.getElementById('winnings').innerHTML; } catch { } return claimed; }; return { run: run }; } function createBigBtcProcessor() { let timeout = new Timeout(); // this.maxSeconds); let countdownMinutes; let captcha = new HCaptchaWidget(); let selectElement = { loadingDiv: function() { let loading = document.querySelector('#loading'); if (loading && loading.isVisible()) { return true; } else { return false; } }, addressInput: function() { return document.querySelector('#login input[name="address"]'); }, loginButton: function() { return document.querySelector('#login input[type="submit"]'); }, claimButton: function() { return document.getElementById('claimbutn'); }, countdown: function() { // "You have to wait\n60 minutes" let cd = document.getElementById('countdown'); if(cd && cd.isVisible()) { return parseInt(cd.innerText); } return null; }, claimedAmount: function() { let elm = document.querySelector('.alert.alert-success.pulse'); //"Yuppie! You won 2 satoshi!" if(elm && elm.isVisible()) { let val = parseInt(elm.innerText.replace(/\D/g, '')); if (Number.isInteger(val)) { val = val / 100000000; } return val; } else { return null; } }, balance: function() { let elm = document.querySelector('a b'); if (elm && elm.isVisible()) { let val = parseInt(elm.innerText.replace(',', '')); if (Number.isInteger(val)) { val = val / 100000000; } return val; } else { return null; } }, error: function () { return null; } }; function init() { window.scrollTo(0, document.body.scrollHeight); let m = document.getElementById('main'); if (m) { m.style.display='block'; } m = document.getElementById('block-adb-enabled'); if (m) { m.style.display='none'; } m = document.getElementById('ielement'); if (m) { m.style.display='block'; } setInterval(() => { let frames = [...document.querySelectorAll('iframe')]; frames.forEach(x => { if (!x.src.includes('hcaptcha')) { x.remove() } }); }, 5000); if (window.location.href.includes('/faucet')) { setTimeout(runFaucet, helpers.randomMs(12000, 14000)); return; } else { setTimeout(run, helpers.randomMs(3000, 5000)); return; } } function run() { try { setTimeout(waitIfLoading, helpers.randomMs(12000, 15000)); } catch (err) { shared.closeWithErrors(K.ErrorType.ERROR, err); } }; function doLogin() { let address = selectElement.addressInput(); if(address && address.value != shared.getCurrent().params.address) { address.value = shared.getCurrent().params.address; } else { selectElement.loginButton().click(); return; } setTimeout( doLogin , helpers.randomMs(1000, 2000)); }; function waitIfLoading() { if ( !selectElement.loadingDiv() ) { doLogin(); return; } else { } setTimeout(waitIfLoading, helpers.randomMs(5000, 7000)); }; function runFaucet() { let claimedAmount = selectElement.claimedAmount(); if(claimedAmount) { processRunDetails(); return; } else if (selectElement.countdown()) { let result = {}; shared.closeWindow(result); } else { captcha.isSolved().then(() => { clickClaim(); }); } } function clickClaim() { try { selectElement.claimButton().click(); return; } catch (err) { shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err); } }; function processRunDetails() { let claimedAmount = selectElement.claimedAmount(); let balance = selectElement.balance(); let countdown = selectElement.countdown(); if (claimedAmount && balance) { let result = {}; result.claimed = claimedAmount; result.balance = balance; shared.closeWindow(result); return; } setTimeout(processRunDetails, helpers.randomMs(5000, 6000)); }; return { init: init }; } function createBestChangeProcessor() { let timeout = new Timeout(); // this.maxSeconds); let countdownMinutes; let captcha = new HCaptchaWidget({selector: '.hcaptcha > iframe'}); let elements = { captcha: function() { return document.querySelector('.hcaptcha > iframe'); }, container: function() { return document.querySelector('#info_bonus'); }, containerOpener: function() { return document.querySelector('#tab_bonus a'); }, addressInput: function() { return document.querySelector('#bonus_purse'); }, claimButton: function() { return document.querySelector('#bonus_button'); }, countdown: function() { // Time left: mm:ss let elm = document.querySelector('#bonus_button'); try { if (elm.value) { let timeLeft = elm.value.split(':'); if (timeLeft.length > 1) { return parseInt(timeLeft[1]); } } } catch (err) { return null; } }, claimedAmount: function() { let elm = document.querySelector("#bonus_status b"); try { let sats = elm.innerText.replace(/\D/g, ''); return sats / 100000000; } catch (err) { return null; } }, balance: function() { let elm = document.querySelector("#faucet_unpaid_balance b"); try { let sats = elm.innerText.replace(/\D/g, ''); return sats / 100000000; } catch (err) { return null; } } }; function init() { run(); } function run() { try { if (!elements.container().isUserFriendly()) { let co = elements.containerOpener(); if(co.isUserFriendly()) { co.onclick = co.onmousedown; co.click(); } } setTimeout(findCountdownOrRoll, helpers.randomMs(4000, 5000)); } catch (err) { shared.closeWithErrors(K.ErrorType.ERROR, err); } }; function findCountdownOrRoll() { let countdown = elements.countdown(); if(countdown) { let result = { }; result.nextRoll = helpers.addMinutes(countdown.toString()); shared.closeWindow(result); return; } let ai = elements.addressInput(); if (ai.isUserFriendly()) { if (ai.value != shared.getCurrent().params.address) { ai.value = shared.getCurrent().params.address; } captcha.isSolved().then(() => { clickClaim(); }); return; } setTimeout(findCountdownOrRoll, helpers.randomMs(10000, 12000)); }; function clickClaim() { try { let btn = elements.claimButton(); if(btn.isUserFriendly()) { btn.click(); setTimeout(processRunDetails, helpers.randomMs(4000, 8000)); } else { setTimeout(clickClaim, helpers.randomMs(4000, 8000)); } return; } catch (err) { shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err); } }; function processRunDetails() { let claimedAmount = elements.claimedAmount(); let balance = elements.balance(); if (claimedAmount && balance) { let result = {}; result.claimed = claimedAmount; result.balance = balance; shared.closeWindow(result); return; } setTimeout(processRunDetails, helpers.randomMs(5000, 6000)); }; return { init: init }; } function createSGProcessor() { let timerSpans; function run() { if(isLoading()) { setTimeout(run, helpers.randomMs(5000, 10000)); return; } else if (hasPopup()) { closePopup(); setTimeout(run, helpers.randomMs(5000, 10000)); } else { if(isMinerActive()) { processRunDetails(); } else { setTimeout(run, helpers.randomMs(5000, 10000)); activateMiner(); } } }; function hasPopup() { if (document.querySelector('div.absolute.flex.top-0.right-0.cursor-pointer.p-4.text-white.md-text-gray-1')) { return true; } return false; }; function closePopup() { try { document.querySelector("div.absolute.flex.top-0.right-0.cursor-pointer.p-4.text-white.md-text-gray-1").click(); document.querySelector('svg.flex.w-8.h-8.fill-current').parentElement.click(); } catch { shared.devlog(`@SG: error closing popup`); } }; function isLoading() { return document.getElementById('loader-logo') ? true : false; }; function isMinerActive() { timerSpans = document.querySelector('.font-bold.text-center.text-accent.w-11-12.text-18 span'); if(timerSpans) { return true; } else { return false; } return (!!timerSpans); }; function activateMiner() { let activateButton = document.querySelector("#region-main button.activate.block.w-full.h-full.mx-auto.p-0.rounded-full.select-none.cursor-pointer.focus-outline-none.border-0.bg-transparent"); if (activateButton) { activateButton.click(); setTimeout(run, helpers.randomMs(10000, 20000)); } else { processRunDetails() } }; function processRunDetails() { let result = {}; result.nextRoll = helpers.addMinutes(readCountdown().toString()); result.balance = readBalance(); shared.closeWindow(result); }; function readCountdown() { let synchronizing = document.querySelector('.text-15.font-bold.text-center.text-accent'); // use let mins = 15; try { let timeLeft = timerSpans.innerText.split(':'); if (timeLeft[0] == 'Synchronizing') { } if(timeLeft.length === 3) { mins = parseInt(timeLeft[0]) * 60 + parseInt(timeLeft[1]); } } catch (err) { shared.devlog(`SG Error reading countdown: ${err}`); } return mins; }; function readBalance() { let balance = ""; try { balance = document.querySelector('span.text-accent').innerText + " BTC"; } catch (err) { } return balance; }; return { run: run, processRunDetails: processRunDetails }; } class AutoCMl extends Faucet { constructor() { let elements = { claimed: new ReadableWidget({selector: 'div.alert.alert-success', parser: Parsers.splitAndIdxTrimNaNs, options: { splitter: ' ', idx: 0} }), captcha: new HCaptchaWidget(), rollButton: new ButtonWidget({selector: 'input[type="submit"].claim-button'}), addressInput: new TextboxWidget({ selector: 'form[role="form"] input[type="text"]'}) }; let actions = { readTimeLeft: false, readRolledNumber: false, readBalance: false }; super(elements, actions); } init() { this.hideAdBlocker(); if(this.hasErrorMessage('suspicious activity')) { shared.closeWithError(K.ErrorType.ERROR, 'Suspicious Activity Message Displayed'); return; } if(this.hasErrorMessage('no funds left') || this.hasErrorMessage('not have sufficient funds')) { shared.closeWithError(K.ErrorType.FAUCET_EMPTY, 'Out of Funds'); return; } if(this.hasErrorMessage('reached the daily claim limit')) { let result = { nextRoll: this.readNextRoll() }; shared.closeWindow(result); return; } let claimed = this.readClaimed(); if (claimed != 0) { if (!location.href.includes('doge')) { claimed = claimed/100000000; } let result = { claimed: claimed, nextRoll: this.readNextRoll() }; shared.closeWindow(result); return; } let waitTime = this.hasWaitTime(); if (waitTime) { let result = { nextRoll: helpers.addMinutes(waitTime + 1) }; shared.closeWindow(result); return; } if (this.changeCaptcha()) { return; } this.setCurrentCaptcha(); if (this._elements.addressInput.isUserFriendly) { if (this._elements.addressInput.value != this._params.address) { this._elements.addressInput.value = this._params.address; } } this.run(); } hideAdBlocker() { try { document.getElementById("page-body").style.display = "block"; document.getElementById("blocker-enabled").style.display = "none"; } catch (err) {} setInterval(() => { try { document.getElementById("page-body").style.display = "block"; document.getElementById("blocker-enabled").style.display = "none"; } catch (err) {} }, 3000); } changeCaptcha() { let selections = [...document.querySelectorAll('div.text-center b')]; if (selections.length == 0) { return false; } if (selections.filter(x => x.innerText.toLowerCase().includes('hcaptcha')).length != 1) { location.href = location.href.includes('?') ? (location.href + '&cc=hCaptcha') : (location.href + '?cc=hCaptcha'); return true; } return false; } hasErrorMessage(searchTerm) { return document.body.innerText.toLowerCase().includes(searchTerm); } hasWaitTime() { try { let pInfos = [...document.querySelectorAll('p.alert.alert-info')].filter(x => x.innerText.toLowerCase().includes('you have to wait')); if (pInfos.length == 1) { let time = +pInfos[0].innerText.toLowerCase().replace('you have to wait ', '').split(' ')[0]; return time; } } catch (err) {} return false; } readNextRoll() { try { let spans = [...document.querySelectorAll('div.row div.col-md-5ths span:not(.glyphicon)')]; let idxClaimsLeft = spans.findIndex(x => x.innerText.includes('daily claims left')); if (idxClaimsLeft > -1) { if (spans[idxClaimsLeft].innerText.includes('0')) { return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } else { return helpers.addMinutes(helpers.randomInt(5, 12)); } } } catch (err) { shared.devlog(`@readNextRoll: ${err}`); } return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160)); } } class CClicks extends Faucet { constructor() { let elements = { claimed: new ReadableWidget({selector: 'div.alert.alert-success', parser: Parsers.cbgClaimed}), captcha: new HCaptchaWidget(), rollButton: new ButtonWidget({selector: '#myModal input[type="submit"].btnclaim'}), addressInput: new TextboxWidget({ selector: '#myModal input[type="text"]'}), openModalButton: new ButtonWidget({selector: 'button[data-target="#myModal"]'}) }; let actions = { readTimeLeft: false, readRolledNumber: false, readBalance: false }; super(elements, actions); } async init() { if (this.hasCloudflare()) { return; } if(this.hasErrorMessage('suspicious activity')) { shared.closeWithError(K.ErrorType.ERROR, 'Suspicious Activity Message Displayed'); return; } if(this.hasErrorMessage('no funds left') || this.hasErrorMessage('not have sufficient funds')) { shared.closeWithError(K.ErrorType.FAUCET_EMPTY, 'Out of Funds'); return; } if(this.hasErrorMessage('reached the daily claim limit') || this.hasErrorMessage('reached the daily limit')) { let result = { nextRoll: helpers.addMinutes(60 * 8 + helpers.randomInt(15, 40)) }; shared.closeWindow(result); return; } let claimed = this.readClaimed(); if (claimed != 0) { let result = { claimed: claimed, nextRoll: this.readNextRoll() }; shared.closeWindow(result); return; } if (this.changeCaptcha()) { return; } if (this._elements.openModalButton.isUserFriendly) { this._elements.openModalButton.click(); await wait(helpers.randomInt(1000, 2000)); } if (this._elements.addressInput.isUserFriendly) { if (this._elements.addressInput.value != this._params.address) { this._elements.addressInput.value = this._params.address; } } this.run(); } changeCaptcha() { let selections = [...document.querySelectorAll('div.text-center b')]; if (selections.length == 0) { return false; } if (selections.filter(x => x.innerText.toLowerCase().includes('hcaptcha')).length != 1) { location.href = location.href.includes('?') ? (location.href + '&cc=hCaptcha') : (location.href + '?cc=hCaptcha'); return true; } return false; } hasErrorMessage(searchTerm) { return document.body.innerText.toLowerCase().includes(searchTerm); } readNextRoll() { try { let p = document.querySelector('p.alert.alert-success'); if (p && p.innerText.toLowerCase().includes('daily')) { p = p.innerText.split('\n')[1]; p = +p.split(' daily')[0]; if (p > 0) { return helpers.addMinutes(helpers.randomInt(3, 9)); } else { return helpers.addMinutes(60 * 8 + helpers.randomInt(15, 40)); } } return helpers.addMinutes(helpers.randomInt(3, 9)); } catch (err) { shared.devlog(`@readNextRoll: ${err}`); } return helpers.addMinutes(60 * 8 + helpers.randomInt(15, 40)); } } let landing, instance, siteTimer; let useTimer; class Site { constructor(params) { Object.assign(this, { schedule: '4a70e0', // Owner! id: null, name: null, cmc: null, // REVIEW LOCATION coinRef: null, // REVIEW LOCATION. Only for CFs? url: null, // REVIEW FORMAT. Only one/'start' url? What about complex scripts/rotators/SLs? rf: null, // ... type: null, // REVIEW DEFAULT. It should be something like 'Crawler' or 'Handler' and the site params should depend on this value clId: null, wallet: null, // should be part of site parameters/crawler based? enabled: false, lastClaim: 0, aggregate: 0, balance: 0, stats: {}, nextRoll: null, params: {}, // should have schedule overrides and be called customExecution, scheduleParamaters or something like that firstRun: true, isExternal: false, }, params); this.setLegacyConditionalDefaults(); } setLegacyConditionalDefaults() { if (this.type == K.WebType.CRYPTOSFAUCETS) { this.schedule = '65329c'; } if (this.type == K.WebType.FREEBITCOIN) { this.params['custom.useWofRp'] = 0; this.params['custom.useFunRp'] = 0; } if (this.type == K.WebType.STORMGAIN) { this.params['defaults.nextRun.override'] = true; this.params['defaults.nextRun.useCountdown'] = true; this.params['defaults.nextRun'] = 0; this.params['defaults.nextRun.min'] = 15; this.params['defaults.nextRun.max'] = 20; } if (this.type == K.WebType.FAUCETPAY) { this.params['defaults.workInBackground.override'] = true; this.params['defaults.workInBackground'] = false; this.params['defaults.nextRun.override'] = true; this.params['defaults.nextRun.useCountdown'] = false; this.params['defaults.nextRun'] = 0; this.params['defaults.nextRun.min'] = 300; this.params['defaults.nextRun.max'] = 360; } if (this.type == K.WebType.BIGBTC) { this.params['defaults.nextRun.override'] = true; this.params['defaults.nextRun.useCountdown'] = false; this.params['defaults.nextRun'] = 0; this.params['defaults.nextRun.min'] = 15; this.params['defaults.nextRun.max'] = 40; } if (this.type == K.WebType.DUTCHYROLL) { this.params['defaults.nextRun.override'] = true; this.params['defaults.nextRun.useCountdown'] = true; this.params['defaults.nextRun'] = 0; this.params['defaults.nextRun.min'] = 30; this.params['defaults.nextRun.max'] = 35; } if (this.type == K.WebType.FCRYPTO) { this.params['defaults.workInBackground.override'] = true; this.params['defaults.workInBackground'] = false; this.params['defaults.nextRun.override'] = true; this.params['defaults.nextRun.useCountdown'] = false; this.params['defaults.nextRun'] = 0; this.params['defaults.nextRun.min'] = 26; this.params['defaults.nextRun.max'] = 35; this.params['defaults.timeout.override'] = true; this.params['defaults.timeout'] = 3; this.params['defaults.postponeMinutes.override'] = true; this.params['defaults.postponeMinutes'] = 0; this.params['defaults.postponeMinutes.min'] = 12; this.params['defaults.postponeMinutes.max'] = 18; } if (this.type == K.WebType.FPB) { this.params['defaults.nextRun.override'] = true; this.params['defaults.nextRun.useCountdown'] = false; this.params['defaults.nextRun'] = 0; this.params['defaults.nextRun.min'] = 22; this.params['defaults.nextRun.max'] = 45; } } static _sites = []; static getAll() { return Site._sites; } static getById(siteId) { return Site.getAll().find(x => x.id == siteId) || false; } static createFromDataArray(newSites) { if (!Array.isArray(newSites)) { newSites = [...newSites]; } newSites.forEach(s => Site.getAll().push(new Site(s))); } static add(data) { let newSite = new Site(data); Site.getAll().push(newSite); let schedule = Schedule.getById(newSite.schedule); if (!schedule) { try { schedule = Schedule.getAll()[0]; } catch (err) { console.warn('No schedules found! Reseting to default schedules'); let defaultSchedule = new Schedule({ uuid: '4a70e0', name: 'Default' }); let sampleSchedule = new Schedule({ uuid: '65329c', name: 'CF' }); if (Schedule.getAll().length == 0) { Schedule.add(defaultSchedule); Schedule.add(sampleSchedule); } schedule = Schedule.getAll()[0]; } } if (!schedule) { console.warn('Schedule NOT found'); console.warn(data); return; } schedule.addSite(newSite); eventer.emit('siteAdded', { siteId: newSite.id, siteName: newSite.name, scheduleId: newSite.schedule }); } static remove(siteId) { let idx = this._sites.findIndex(x => x.id === siteId); if (idx > -1 && this._sites[idx].isExternal) { let siteName = this._sites[idx].name; this._sites = Site.getAll().filter(x => x.id !== siteId); Schedule.getAll().forEach(sch => { sch.removeSite(siteId); }); eventer.emit('siteRemoved', { siteId: siteId, siteName: siteName }); } } static sortAll() { Site.getAll().sort( function(a,b) { if (a === b) { return 0; } else if (a.nextRoll === null && b.nextRoll === null) { let aHasLoginError = a.stats?.errors?.errorType == 2; let bHasLoginError = b.stats?.errors?.errorType == 2; if (aHasLoginError) { return -1; } else if (bHasLoginError) { return 1; } return a.id > b.id ? -1 : 1 } else if (a.nextRoll === null) { return 1; } else if (b.nextRoll === null) { return -1; } else { return a.nextRoll.getTime() < b.nextRoll.getTime() ? -1 : 1; } }); } static setAsRunAsap(siteId) { let site = Site.getById(siteId); if (!site) return false; try { let schedule = Schedule.getById(site.schedule); if (schedule.status == STATUS.CLAIMING) { console.warn(`Setting ASAP as 1st in schedule time + 1`); site.nextRoll = new Date(schedule.currentSite.nextRoll.getTime() + 1); } else { let now = new Date(); if (!schedule.currentSite?.nextRoll) { console.warn(`Setting ASAP as now()`); site.nextRoll = now; } else if (now < schedule.currentSite.nextRoll) { console.warn(`Setting ASAP as now()`); site.nextRoll = now; } else { console.warn(`Setting ASAP as 1st in schedule time - 1`); site.nextRoll = new Date(schedule.currentSite.nextRoll.getTime() - 1); } } site.enabled = true; console.warn(`[${site.schedule}] ${site.name} updated to run ASAP from Site`); eventer.emit('siteUpdated', site); return; } catch (err) { console.error(err); ui.log({msg: `Error setting faucet to run ASAP from Site: ${err}`}); } } changeSchedule(newScheduleId) { let oldScheduleId = null; if (this.schedule) { oldScheduleId = this.schedule; Schedule.getById(this.schedule)?.removeSite(this.id); } this.schedule = newScheduleId; let newSchedule = Schedule.getById(this.schedule); newSchedule.addSite(this); // maybe use just the ids... eventer.emit('siteChangedSchedule', { siteId: this.id, scheduleId: this.schedule, oldScheduleId: oldScheduleId }); } static saveAll() { persistence.save('webList', Site._sites.map(x => x.toStorage()), true); } toStorage() { // Single site if (!this.isExternal) { return { id: this.id, isExternal: this.isExternal || false, name: this.name, schedule:this.schedule, lastClaim: this.lastClaim, aggregate: this.aggregate, balance: this.balance, stats: this.stats, nextRoll: this.nextRoll, enabled: this.enabled, params: this.params }; } else { return { id: this.id, url: this.url.href, clId: this.clId, type: this.type, cmc: this.cmc, rf: this.rf, name: this.name, isExternal: this.isExternal || false, schedule:this.schedule, lastClaim: this.lastClaim, aggregate: this.aggregate, balance: this.balance, stats: this.stats, nextRoll: this.nextRoll, enabled: this.enabled, params: this.params }; } } update(items) { // this should be for Parameters or Execution (custom) this.params = this.params || {}; items.forEach( item => { this.params[item.prop] = item.value; }); ui.log({schedule: this.schedule, siteName: this.name, msg: `Site ${this.name} updated`}); } getSiteParameters() { if (this.type == K.WebType.CRYPTOSFAUCETS) { this.siteParameters = { handler: 'CF', fields: [ { name: 'try_get_codes', type: 'checkbox', value: 'false', text: 'Auto update promo codes' }, { name: 'max_rolls_per_visit', type: 'numberInput', value: 1, min: 0 }, { name: 'autologin', type: 'checkbox', value: 'true', text: 'Autologin when necessary' }, { name: 'credentials_mode', type: 'credentials_or_autofilled', value: '2' }, { name: 'email', type: 'email', value: '' }, { name: 'password', type: 'password', value: '' } ] }; } return this.siteParameters || false; } } class Schedule { constructor(params) { Object.assign(this, { uuid: '4a70e0', name: 'default_schedule', status: STATUS.INITIALIZING, currentSite: null, sites: [], tab: null, timer: null, // TBD timeWaiting: 0, timeUntilNext: null, worker: null }, params) this.timer = new Timer({ isManager: true, delaySeconds: 30, uuid: this.uuid, webType: null }); } static schedules = []; static getAll() { return Schedule.schedules; } static getById(scheduleId) { return Schedule.getAll().find(x => x.uuid == scheduleId) || false; } static add(newSchedule) { Schedule.getAll().push(newSchedule); } static getAllForCrud() { return Schedule.getAll().map(x => { return { uuid: x.uuid, name: x.name, hasSites: x.sites && x.sites.length > 0 }; }); } static async initialize() { Schedule.loadAll(); let defaultSchedule = new Schedule({ uuid: '4a70e0', name: 'Default' }); let sampleSchedule = new Schedule({ uuid: '65329c', name: 'CF' }); if (Schedule.getAll().length == 0) { Schedule.add(defaultSchedule); Schedule.add(sampleSchedule); return; } let idxDefault = Schedule.getAll().findIndex(x => x.uuid == '4a70e0'); if (idxDefault == -1) { Schedule.add(defaultSchedule); } }; static saveAll() { persistence.save('schedules', Schedule.schedules.map(x => { return { uuid: x.uuid, name: x.name }; }), true); } static loadAll() { Schedule.schedules = []; let schedulesJson = persistence.load('schedules', true) || []; schedulesJson.forEach(function(element) { Schedule.getAll().push(new Schedule({ uuid: element.uuid, name: element.name, })); }); } sortSites() { this.sites.sort( function(a,b) { if (a === b) { return 0; } else if (a.nextRoll === null && b.nextRoll === null) { let aHasLoginError = a.stats?.errors?.errorType == 2; let bHasLoginError = b.stats?.errors?.errorType == 2; if (aHasLoginError) { return -1; } else if (bHasLoginError) { return 1; } return a.id > b.id ? -1 : 1 } else if (a.nextRoll === null) { return 1; } else if (b.nextRoll === null) { return -1; } else { return a.nextRoll.getTime() < b.nextRoll.getTime() ? -1 : 1; } }); } static crud(data) { let isInvalid = false; try { const orphanSites = []; data.forEach(x => { if (x.added) { if (Schedule.getById(x.uuid)) { isInvalid = true; } else { let newSchedule = new Schedule({ uuid: x.uuid, name: x.name, order: x.order }) Schedule.getAll().push(newSchedule); newSchedule.start(); } } else if (x.removed) { let pos = Schedule.getAll().findIndex(s => s.uuid == x.originals.uuid); orphanSites.push(...Schedule.getAll()[pos].sites); Schedule.getAll().splice(pos, 1); } else { let sch = Schedule.getAll().find(s => s.uuid == x.originals.uuid); if (Schedule.getById(x.uuid) && (Schedule.getById(x.uuid) != sch)) { isInvalid = true; } else { sch.uuid = x.uuid; } sch.name = x.name; sch.order = x.order; } }); Schedule.getAll().sort((a, b) => a.order - b.order); if (orphanSites.length > 0) { orphanSites.forEach(x => { x.schedule = Schedule.getAll()[0].uuid; }); Schedule.getAll()[0].sites.push(...orphanSites); } Schedule.saveAll(); } catch (err) { console.error(err); return false; } if (isInvalid) { return false; } return true; } addSite(site) { this.sites.push(site) } removeSite(siteId) { if (this.sites.findIndex(x => x.id === siteId) > -1) { this.sites = this.sites.filter(x => x.id !== siteId); this.setCurrentSite(); } } setCurrentSite() { this.currentSite = this.sites[0]; } start() { this.status = STATUS.IDLE; this.worker = setTimeout(() => { this.checkNextRoll(); }, 2000); } checkNextRoll() { if (this.status != STATUS.IDLE) { return; } this.timer.stopCheck(); clearTimeout(this.worker); if(!this.currentSite || this.currentSite.nextRoll == null) { document.querySelector(`#wait-times span[data-schedule="${this.uuid}"]`).setAttribute('data-nextroll', 'UNDEFINED'); this.status = STATUS.IDLE; return; } if(this.currentSite.nextRoll.getTime() < Date.now()) { ui.log({ schedule: this.uuid, siteName: this.currentSite.name, msg: `Opening ${this.currentSite.name}`}); document.querySelector(`#wait-times span[data-schedule="${this.uuid}"]`).setAttribute('data-nextroll', 'RUNNING'); this.open(); this.timeUntilNext = null; return; } else { this.timeUntilNext = this.currentSite.nextRoll.getTime() - Date.now() + helpers.randomMs(1000, 2000); document.querySelector(`#wait-times span[data-schedule="${this.uuid}"]`).setAttribute('data-nextroll', this.currentSite.nextRoll.getTime()); this.worker = setTimeout(() => { this.checkNextRoll(); }, this.timeUntilNext); this.status = STATUS.IDLE; } } getCustomOrDefaultVal(param, useOverride = false) { let val; if (useOverride) { if (this.currentSite.params && this.currentSite.params.hasOwnProperty(param)) { val = this.currentSite.params[param]; if (val != -1) { return val; } } } return shared.getConfig()[param]; } useOverride(param) { let overrideFlag = param + '.override'; return this.currentSite.params && this.currentSite.params[overrideFlag]; } closeTab() { try { this.tab.close(); } catch (err) { console.warn('Error while trying to close tab', err); } }; reopenTab() { this.tab = GM_openInTab(this.currentSite.url, { active: !this.getCustomOrDefaultVal('defaults.workInBackground', this.useOverride('defaults.workInBackground')) }); }; open(promoCodes) { this.status = STATUS.CLAIMING; let navUrl = this.currentSite.url; try { let params = this.currentSite.params || {}; params.siteParams = this.currentSite.siteParams || { "test": "test_value" }; if(promoCodes) { navUrl = new URL('promotion/' + promoCodes[0], this.currentSite.url.origin); ui.log({ schedule: this.uuid, siteName: this.currentSite.name, msg: `Opening ${this.currentSite.name} with ${promoCodes.length} Promo Codes [${promoCodes.join(',')}]`}); params.promoCodes = promoCodes; } if (this.currentSite.firstRun) { if(Array.isArray(this.currentSite.rf) && this.currentSite.rf.length > 0) { navUrl = new URL(navUrl.href + this.currentSite.rf[helpers.randomInt(0, this.currentSite.rf.length - 1)]); } } if (this.currentSite.wallet) { try { params.address = manager.userWallet.find(x => x.type == this.currentSite.wallet)?.address; if (!params.address) { throw new Error('Address is not defined.'); } } catch { ui.log({ schedule: this.uuid, siteName: this.currentSite.name, msg: `Unable to launch ${this.currentSite.name}: Address not detected > add it to the wallet.`}); this.moveNextAfterTimeoutOrError(); return; } } if(this.currentSite.type == K.WebType.BESTCHANGE) { params.address = shared.getConfig()['bestchange.address'] == '1' ? manager.userWallet.find(x => x.type == 1).address : params.address; } params.timeout = this.getCustomOrDefaultVal('defaults.timeout', this.useOverride('defaults.timeout')); params.cmc = this.currentSite.cmc; if(this.currentSite.type == K.WebType.FPB) { switch(this.currentSite.id) { case '77': params.sitePrefix = 'fpb'; break; case '83': params.sitePrefix = 'fbch'; break; case '92': params.sitePrefix = 'shost'; break; } } if(this.currentSite.type == K.WebType.VIE) { params.credentials = { mode: shared.getConfig()['jtfey.credentials.mode'], username: shared.getConfig()['jtfey.credentials.username'], password: shared.getConfig()['jtfey.credentials.password'] }; } shared.setFlowControl(this.uuid, this.currentSite.id, navUrl, this.currentSite.type, params); setTimeout(() => { this.waitForResult(); }, 15000); if (this.tab && !this.tab.closed) { this.closeTab(); // this.tab.close(); } else { } this.timer.startCheck(this.currentSite.type); let noSignUpList = [ K.WebType.BESTCHANGE, K.WebType.CBG, K.WebType.G8, K.WebType.O24, K.WebType.CDIVERSITY, K.WebType.CTOP, K.WebType.AUTOCML, K.WebType.CCLICKS ]; let hrefOpener = navUrl.href; if (noSignUpList.includes(this.currentSite.type)) { hrefOpener = (new URL(this.currentSite.clId, 'https://criptologico.com/goto/')).href; } this.tab = GM_openInTab(hrefOpener, { active: !this.getCustomOrDefaultVal('defaults.workInBackground', this.useOverride('defaults.workInBackground')) }); } catch(err) { ui.log({ schedule: this.uuid, msg: `Error opening tab: ${err}`}); } }; waitForResult() { if(manager.isObsolete()) { return; } if(shared.isCompleted(this.currentSite.id)) { this.analyzeResult(); // rename to something else... return; } this.timeWaiting += 15; if(shared.isIncompleted(this.currentSite.id) && this.hasTimedOut()) { this.analyzeResult(); // rename to something else... return; } this.waitOrMoveNext(); // this should just be the error and timeout check return; }; analyzeResult() { let currentSchedule = shared.getCurrent(this.uuid); currentSchedule.result = currentSchedule.result || {}; currentSchedule.runStatus = currentSchedule.runStatus || false; if (currentSchedule.result) { this.updateWebListItem(currentSchedule); if (currentSchedule.result.closeParentWindow) { ui.log({ schedule: this.uuid, msg: `Closing working tab per process request` }); this.closeTab(); } if (shared.getConfig()['cf.usePromoCodes'] && this.currentSite.type == K.WebType.CRYPTOSFAUCETS) { let promoCode = CFPromotions.hasPromoAvailable(this.currentSite.id); if (promoCode) { this.timeWaiting = 0; this.currentSite.nextRoll = new Date(754000 + +this.currentSite.id); manager.update(false); this.open(promoCode); return; } } } else { ui.log({ schedule: this.uuid, siteName: this.currentSite.name, msg: `Unable to read last run result, for ID: ${this.currentSite.id} > ${this.currentSite.name}`}); } this.timeWaiting = 0; this.status = STATUS.IDLE; shared.clearFlowControl(this.uuid); manager.update(true); manager.readUpdateValues(true); return; } waitOrMoveNext() { if (this.currentSite.isExternal) { if (!this.tab || (this.tab && this.tab.closed)) { this.timeWaiting = this.getCustomOrDefaultVal('defaults.timeout', this.useOverride('defaults.timeout')) * 60 + 9999; } } if (!shared.hasErrors(this.currentSite.id) && !this.hasTimedOut()) { ui.log({ schedule: this.uuid, siteName: this.currentSite.name, elapsed: this.timeWaiting, msg: `Waiting for ${this.currentSite.name} results...`}); setTimeout(() => { this.waitForResult(); }, 15000); return; } if (shared.hasErrors(this.currentSite.id)) { this.currentSite.stats.errors = shared.getResult(this.uuid); // shared.getResult(this.uuid); ui.log({ schedule: this.uuid, siteName: this.currentSite.name, msg: `${this.currentSite.name} closed with error: ${helpers.getEnumText(K.ErrorType,this.currentSite.stats.errors.errorType)} ${this.currentSite.stats.errors.errorMessage}`}); if(this.sleepIfBan()) { return; } } if (this.hasTimedOut()) { if (this.currentSite.isExternal) { this.currentSite.stats.countTimeouts = 0; this.currentSite.stats.errors = null; ui.log({ schedule: this.uuid, siteName: this.currentSite.name, msg: `Closing ${this.currentSite.name}` }); try { this.closeTab(); } catch (err) { console.error('Unable to close working tab', err); } this.moveAfterNormalRun(); return; } else { if(this.currentSite.stats.countTimeouts) { this.currentSite.stats.countTimeouts += 1; } else { this.currentSite.stats.countTimeouts = 1; } ui.log({ schedule: this.uuid, siteName: this.currentSite.name, msg: `Waited too much time for ${this.currentSite.name} results: triggering timeout` }); } } this.moveNextAfterTimeoutOrError(); return; } hasTimedOut() { // here or on a site level??? let val = this.getCustomOrDefaultVal('defaults.timeout', this.useOverride('defaults.timeout')) * 60; return (this.timeWaiting > val); }; sleepIfBan() { // This should be a SiteType hook if( (this.currentSite.stats.errors.errorType == K.ErrorType.IP_BAN && shared.getConfig()['cf.sleepHoursIfIpBan'] > 0) || ( (this.currentSite.stats.errors.errorType == K.ErrorType.IP_RESTRICTED || this.currentSite.stats.errors.errorType == K.ErrorType.IP_BAN) && shared.getConfig()['bk.sleepMinutesIfIpBan'] > 0) ) { if(this.currentSite.type == K.WebType.CRYPTOSFAUCETS) { Site.getAll().filter(x => x.enabled && x.type == K.WebType.CRYPTOSFAUCETS) .forEach( function(el) { el.nextRoll = this.sleepCheck(helpers.addMs(helpers.getRandomMs(shared.getConfig()['cf.sleepHoursIfIpBan'] * 60, 2)).toDate()); }); } shared.clearFlowControl(this.uuid); manager.update(true); this.timeWaiting = 0; this.status = STATUS.IDLE; shared.clearFlowControl(this.uuid); manager.readUpdateValues(true); return true; } return false; } updateWebListItem(currentSchedule) { let result = currentSchedule.result; ui.log({ schedule: this.uuid, msg: `Updating data: ${JSON.stringify(result)}` }); this.currentSite.stats.countTimeouts = 0; this.currentSite.stats.errors = null; if (result.claimed) { try { result.claimed = parseFloat(result.claimed); } catch { } if(!isNaN(result.claimed)) { this.currentSite.lastClaim = result.claimed; this.currentSite.aggregate += result.claimed; } } if(result.balance) { this.currentSite.balance = result.balance; } this.currentSite.nextRoll = this.getNextRun(result.nextRoll ? result.nextRoll.toDate() : null); if(result.promoCodeResults) { // TODO: move to a processResult hook for(let i = 0; i < result.promoCodeResults.length; i++) { let item = result.promoCodeResults[i]; CFPromotions.updateFaucetForCode(item.promoCode, this.currentSite.id, item.promoStatus); } } if(result.rolledNumber) { CFHistory.addRoll(result.rolledNumber); } } getNextRun(nextRollFromCountdown) { let useCustom = this.useOverride('defaults.nextRun'); let useCountdown = this.getCustomOrDefaultVal('defaults.nextRun.useCountdown', useCustom); let nextRunMode = this.getCustomOrDefaultVal('defaults.nextRun', useCustom); let min = this.getCustomOrDefaultVal('defaults.nextRun.min', useCustom); let max = this.getCustomOrDefaultVal('defaults.nextRun.max', useCustom); let nextRun; if (useCountdown && nextRollFromCountdown) { nextRun = nextRollFromCountdown; } else { let minutes = (nextRunMode == 0) ? helpers.randomInt(min, max) : nextRunMode; let msDelay = helpers.getRandomMs(minutes, 1); nextRun = helpers.addMs(msDelay).toDate(); } nextRun = this.sleepCheck(nextRun) return nextRun; } errorTreatment() { // Move to group custom getNextRoll try { switch(this.currentSite.stats.errors.errorType) { case K.ErrorType.NEED_TO_LOGIN: this.currentSite.enabled = false; this.currentSite.nextRoll = null; return true; case K.ErrorType.FAUCET_EMPTY: // retry in 8 hours this.currentSite.enabled = true; this.currentSite.nextRoll = new Date(new Date().setHours(new Date().getHours() + 8)); return true; } } catch {} return false; } sleepCheck(nextRun) { let useCustom = this.useOverride('defaults.sleepMode'); let sleepMode = this.getCustomOrDefaultVal('defaults.sleepMode', useCustom); if (sleepMode) { let intNextRunTime = nextRun.getHours() * 100 + nextRun.getMinutes(); let min = this.getCustomOrDefaultVal('defaults.sleepMode.min', useCustom).replace(':', ''); let max = this.getCustomOrDefaultVal('defaults.sleepMode.max', useCustom).replace(':', ''); if (+min < +max) { if (+min < intNextRunTime && intNextRunTime < +max) { nextRun.setHours(max.slice(0, 2), max.slice(-2), 10, 10); ui.log({ schedule: this.uuid, msg: `Next run adjusted by Sleep Mode: ${helpers.getPrintableDateTime(nextRun)}` }); } } else if (+min > +max) { if (intNextRunTime > +min || intNextRunTime < +max) { nextRun.setHours(max.slice(0, 2), max.slice(-2), 10, 10); if (nextRun.getTime() < Date.now()) { nextRun.setDate(nextRun.getDate() + 1); } ui.log({ schedule: this.uuid, msg: `Next run adjusted by Sleep Mode: ${helpers.getPrintableDateTime(nextRun)}` }); } } } return nextRun; } moveAfterNormalRun() { this.currentSite.nextRoll = this.getNextRun(null); shared.clearFlowControl(this.uuid); manager.update(true); this.timeWaiting = 0; this.status = STATUS.IDLE; shared.clearFlowControl(this.uuid); manager.readUpdateValues(true); } moveNextAfterTimeoutOrError() { let useCustom = this.useOverride('defaults.postponeMinutes'); let mode = this.getCustomOrDefaultVal('defaults.postponeMinutes', useCustom); let min = this.getCustomOrDefaultVal('defaults.postponeMinutes.min', useCustom); let max = this.getCustomOrDefaultVal('defaults.postponeMinutes.max', useCustom); let minutes = (mode == 0) ? helpers.randomInt(min, max) : mode; let msDelay = helpers.getRandomMs(minutes, 5); this.currentSite.nextRoll = this.sleepCheck(helpers.addMs(msDelay).toDate()); if(this.errorTreatment()) { } shared.clearFlowControl(this.uuid); manager.update(true); this.timeWaiting = 0; this.status = STATUS.IDLE; shared.clearFlowControl(this.uuid); manager.readUpdateValues(true); } } function createManager() { let timestamp = null; let intervalUiUpdate; let getFeedInterval; let userWallet = []; const sites = [ { id: '1', name: 'CF ADA', cmc: '2010', coinRef: 'ADA', url: new URL('https://app.freecardano.com/free'), rf: '?ref=335463', type: K.WebType.CRYPTOSFAUCETS, clId: 45 }, { id: '2', name: 'CF BNB', cmc: '1839', coinRef: 'BNB', url: new URL('https://app.freebinancecoin.com/free'), rf: '?ref=161127', type: K.WebType.CRYPTOSFAUCETS, clId: 42 }, { id: '3', name: 'CF BTC', cmc: '1', coinRef: 'BTC', url: new URL('https://app.freebitcoin.io/free'), rf: '?ref=490252', type: K.WebType.CRYPTOSFAUCETS, clId: 40 }, { id: '4', name: 'CF DASH', cmc: '131', coinRef: 'DASH', url: new URL('https://app.freedash.io/free'), rf: '?ref=124083', type: K.WebType.CRYPTOSFAUCETS, clId: 156 }, { id: '5', name: 'CF ETH', cmc: '1027', coinRef: 'ETH', url: new URL('https://app.freeethereum.com/free'), rf: '?ref=204076', type: K.WebType.CRYPTOSFAUCETS, clId: 44 }, { id: '6', name: 'CF LINK', cmc: '1975', coinRef: 'LINK', url: new URL('https://app.freecryptom.com/free'), rf: '?ref=78652', type: K.WebType.CRYPTOSFAUCETS, clId: 157 }, { id: '7', name: 'CF LTC', cmc: '2', coinRef: 'LTC', url: new URL('https://app.free-ltc.com/free'), rf: '?ref=117042', type: K.WebType.CRYPTOSFAUCETS, clId: 47 }, { id: '8', name: 'CF NEO', cmc: '1376', coinRef: 'NEO', url: new URL('https://app.freeneo.io/free'), rf: '?ref=100529', type: K.WebType.CRYPTOSFAUCETS, clId: 158 }, { id: '9', name: 'CF STEAM', cmc: '825', coinRef: 'STEEM', url: new URL('https://app.freesteam.io/free'), rf: '?ref=117686', type: K.WebType.CRYPTOSFAUCETS, clId: 49 }, { id: '10', name: 'CF TRX', cmc: '1958', coinRef: 'TRX', url: new URL('https://app.free-tron.com/free'), rf: '?ref=145047', type: K.WebType.CRYPTOSFAUCETS, clId: 41 }, { id: '11', name: 'CF USDC', cmc: '3408', coinRef: 'USDC', url: new URL('https://app.freeusdcoin.com/free'), rf: '?ref=100434', type: K.WebType.CRYPTOSFAUCETS, clId: 51 }, { id: '12', name: 'CF USDT', cmc: '825', coinRef: 'USDT', url: new URL('https://app.freetether.com/free'), rf: '?ref=181230', type: K.WebType.CRYPTOSFAUCETS, clId: 43 }, { id: '13', name: 'CF XEM', cmc: '873', coinRef: 'XEM', url: new URL('https://app.freenem.com/free'), rf: '?ref=295274', type: K.WebType.CRYPTOSFAUCETS, clId: 46 }, { id: '14', name: 'CF XRP', cmc: '52', coinRef: 'XRP', url: new URL('https://app.coinfaucet.io/free'), rf: '?ref=808298', type: K.WebType.CRYPTOSFAUCETS, clId: 48 }, { id: '15', name: 'StormGain', cmc: '1', url: new URL('https://app.stormgain.com/crypto-miner/'), rf: 'friend/BNS27140552', type: K.WebType.STORMGAIN, clId: 35 }, { id: '16', name: 'CF DOGE', cmc: '74', coinRef: 'DOGE', url: new URL('https://app.free-doge.com/free'), rf: '?ref=97166', type: K.WebType.CRYPTOSFAUCETS, clId: 50 }, { id: '17', name: 'FreeBitco.in', cmc: '1', url: new URL('https://freebitco.in/'), rf: '?r=41092365', type: K.WebType.FREEBITCOIN, clId: 36 }, { id: '18', name: 'FaucetPay PTC', cmc: '825', url: new URL('https://faucetpay.io/ptc'), rf: '?r=41092365', type: K.WebType.FAUCETPAY, clId: 159 }, { id: '52', name: 'BigBtc', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://bigbtc.win/'), rf: '?id=39255652', type: K.WebType.BIGBTC, clId: 200 }, { id: '53', name: 'BestChange', cmc: '1', url: new URL('https://www.bestchange.com/'), rf: ['index.php?nt=bonus&p=1QCD6cWJNVH4Cdnz85SQ2qtTkAwGr9fvUk'], type: K.WebType.BESTCHANGE, clId: 163 }, { id: '58', name: 'BF BTC', cmc: '1', url: new URL('https://betfury.io/boxes/all'), rf: ['?r=608c5cfcd91e762043540fd9'], type: K.WebType.BFBOX, clId: 1 }, { id: '61', name: 'Dutchy', cmc: '-1', url: new URL('https://autofaucet.dutchycorp.space/roll.php'), rf: '?r=corecrafting', type: K.WebType.DUTCHYROLL, clId: 141 }, { id: '62', name: 'Dutchy Monthly Coin', cmc: '-1', url: new URL('https://autofaucet.dutchycorp.space/coin_roll.php'), rf: '?r=corecrafting', type: K.WebType.DUTCHYROLL, clId: 141 }, { id: '68', name: 'CF SHIBA', cmc: '5994', coinRef: 'SHIBA', url: new URL('https://app.freeshibainu.com/free'), rf: '?ref=18226', type: K.WebType.CRYPTOSFAUCETS, clId: 167 }, { id: '78', name: 'CF Cake', cmc: '7186', coinRef: 'CAKE', url: new URL('https://app.freepancake.com/free'), rf: '?ref=699', type: K.WebType.CRYPTOSFAUCETS, clId: 197 }, { id: '80', name: 'FreeGRC', cmc: '833', url: new URL('https://freegridco.in/#free_roll'), rf: '', type: K.WebType.FREEGRC, clId: 207 }, { id: '81', name: 'CF Matic', cmc: '3890', coinRef: 'MATIC', url: new URL('https://app.freematic.com/free'), rf: '?ref=6435', type: K.WebType.CRYPTOSFAUCETS, clId: 210 }, { id: '84', name: 'JTFey', cmc: '-1', url: new URL('https://james-trussy.com/faucet'), rf: ['?r=corecrafting'], type: K.WebType.VIE, clId: 213 }, { id: '85', name: 'O24', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://www.only1024.com/f'), rf: ['?r=1QCD6cWJNVH4Cdnz85SQ2qtTkAwGr9fvUk'], type: K.WebType.O24, clId: 97 }, { id: '87', name: 'CF BTT', cmc: '16086', coinRef: 'BTT', url: new URL('https://app.freebittorrent.com/free'), rf: '?ref=2050', type: K.WebType.CRYPTOSFAUCETS, clId: 218 }, { id: '89', name: 'CF BFG', cmc: '11038', coinRef: 'BFG', url: new URL('https://app.freebfg.com/free'), rf: '?ref=117', type: K.WebType.CRYPTOSFAUCETS, clId: 219 }, { id: '93', name: 'YCoin', cmc: '1', url: new URL('https://yescoiner.com/faucet'), rf: ['?ref=4729452'], type: K.WebType.YCOIN, clId: 234 }, { id: '94', name: 'CDiversity', cmc: '-1', wallet: K.WalletType.FP_MAIL, url: new URL('http://coindiversity.io/free-coins'), rf: ['?r=1J3sLBZAvY5Vk9x4RY2qSFyL7UHUszJ4DJ'], type: K.WebType.CDIVERSITY, clId: 235 }, { id: '96', name: 'Top Ltc', cmc: '2', wallet: K.WalletType.FP_LTC, url: new URL('https://ltcfaucet.top/'), rf: ['?r=MWSsGAQTYD7GH5o4oAehC8Et5PyMBfhnKK'], type: K.WebType.CTOP, clId: 239 }, { id: '97', name: 'Top Bnb', cmc: '1839', wallet: K.WalletType.FP_BNB, url: new URL('https://bnbfaucet.top/'), rf: ['?r=0x1e8CB8A79E347C54aaF21C0502892B58F97CC07A'], type: K.WebType.CTOP, clId: 240 }, { id: '98', name: 'Top Doge', cmc: '74', wallet: K.WalletType.FP_DOGE, url: new URL('https://dogecoinfaucet.top/'), rf: ['?r=D8Xgghu5gCryukwmxidFpSmw8aAKon2mEQ'], type: K.WebType.CTOP, clId: 241 }, { id: '99', name: 'Top Trx', cmc: '1958', wallet: K.WalletType.FP_TRX, url: new URL('https://tronfaucet.top/'), rf: ['?r=TK3ofbD3AyXotN2111UvnwCzr2YaW8Qmx7'], type: K.WebType.CTOP, clId: 242 }, { id: '100', name: 'Top Eth', cmc: '1027', wallet: K.WalletType.FP_ETH, url: new URL('https://ethfaucet.top/'), rf: ['?r=0xC21FD989118b8C0Db6Ac2eC944B53C09F7293CC8'], type: K.WebType.CTOP, clId: 243 }, { id: '101', name: 'Top Bch', cmc: '1831', wallet: K.WalletType.FP_BCH, url: new URL('https://freebch.club/'), rf: ['?r=qq2qlpzs4rsn30utrumezpkzezpteqj92ykdgfeq5u'], type: K.WebType.CTOP, clId: 244 }, { id: '102', name: 'Top Zec', cmc: '1437', wallet: K.WalletType.FP_ZEC, url: new URL('https://zecfaucet.net/'), rf: ['?r=t1erPs9qw3SgnX7kJPmR4uKFnLaoVww2jCy'], type: K.WebType.CTOP, clId: 245 }, { id: '103', name: 'FMonster', cmc: '825', wallet: K.WalletType.FP_USDT, url: new URL('https://faucet.monster/'), rf: '', type: K.WebType.O24, clId: 246 }, { id: '104', name: 'Auto-C BNB', cmc: '1839', wallet: K.WalletType.FP_BNB, url: new URL('https://auto-crypto.click/'), rf: ['?r=0x1e8CB8A79E347C54aaF21C0502892B58F97CC07A'], type: K.WebType.AUTOCML, clId: 247 }, { id: '105', name: 'Auto-C DOGE', cmc: '74', wallet: K.WalletType.FP_DOGE, url: new URL('https://freeshiba.cf/'), rf: ['?r=D8Xgghu5gCryukwmxidFpSmw8aAKon2mEQ'], type: K.WebType.AUTOCML, clId: 248 }, { id: '106', name: 'ClClicks DOGE', cmc: '74', wallet: K.WalletType.FP_USERNAME, url: new URL('https://claimclicks.com/doge/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 61 }, { id: '107', name: 'ClClicks LTC', cmc: '2', wallet: K.WalletType.FP_USERNAME, url: new URL('https://claimclicks.com/ltc/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 62 }, { id: '108', name: 'ClClicks TRX', cmc: '1958', wallet: K.WalletType.FP_USERNAME, url: new URL('https://claimclicks.com/trx/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 63 }, { id: '109', name: 'ClClicks BTC', cmc: '1', wallet: K.WalletType.FP_USERNAME, url: new URL('https://claimclicks.com/btc/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 252 }, { id: '110', name: 'ClClicks SOL', cmc: '5426', wallet: K.WalletType.FP_USERNAME, url: new URL('https://claimclicks.com/sol/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 253 }, { id: '111', name: 'ClClicks BNB', cmc: '1839', wallet: K.WalletType.FP_USERNAME, url: new URL('https://claimclicks.com/bnb/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 254 }, { id: '112', name: 'CrClicks DOGE', cmc: '74', wallet: K.WalletType.FP_USERNAME, url: new URL('https://cryptoclicks.net/doge/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 257 }, { id: '113', name: 'CrClicks LTC', cmc: '2', wallet: K.WalletType.FP_USERNAME, url: new URL('https://cryptoclicks.net/ltc/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 258 }, { id: '114', name: 'CrClicks TRX', cmc: '1958', wallet: K.WalletType.FP_USERNAME, url: new URL('https://cryptoclicks.net/trx/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 259 }, { id: '115', name: 'CrClicks BTC', cmc: '1', wallet: K.WalletType.FP_USERNAME, url: new URL('https://cryptoclicks.net/btc/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 256 }, { id: '116', name: 'CrClicks SOL', cmc: '5426', wallet: K.WalletType.FP_USERNAME, url: new URL('https://cryptoclicks.net/sol/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 261 }, { id: '117', name: 'CrClicks BNB', cmc: '1839', wallet: K.WalletType.FP_USERNAME, url: new URL('https://cryptoclicks.net/bnb/'), rf: ['?r=corecrafting'], type: K.WebType.CCLICKS, clId: 260 }, ]; const wallet = [ { id: '99', name: 'FaucetPay Username', type: K.WalletType.FP_USERNAME }, { id: '100', name: 'FaucetPay Email', type: K.WalletType.FP_MAIL }, { id: '101', name: 'FaucetPay BTC (Bitcoin)', type: K.WalletType.FP_BTC }, { id: '102', name: 'FaucetPay BNB (Binance Coin)', type: K.WalletType.FP_BNB }, { id: '103', name: 'FaucetPay BCH (Bitcoin Cash)', type: K.WalletType.FP_BCH }, { id: '104', name: 'FaucetPay DASH (Dash)', type: K.WalletType.FP_DASH }, { id: '105', name: 'FaucetPay DGB (DigiByte)', type: K.WalletType.FP_DGB }, { id: '106', name: 'FaucetPay DOGE (Dogecoin)', type: K.WalletType.FP_DOGE }, { id: '107', name: 'FaucetPay ETH (Ethereum)', type: K.WalletType.FP_ETH }, { id: '108', name: 'FaucetPay FEY (Feyorra)', type: K.WalletType.FP_FEY }, { id: '109', name: 'FaucetPay LTC (Litecoin)', type: K.WalletType.FP_LTC }, { id: '110', name: 'FaucetPay TRX (Tron)', type: K.WalletType.FP_TRX }, { id: '111', name: 'FaucetPay USDT (Tether TRC20)', type: K.WalletType.FP_USDT }, { id: '112', name: 'FaucetPay ZEC (Zcash)', type: K.WalletType.FP_ZEC }, { id: '113', name: 'FaucetPay SOL (Solana)', type: K.WalletType.FP_SOL }, { id: '114', name: 'FaucetPay MATIC (Polygon)', type: K.WalletType.FP_MATIC }, { id: '116', name: 'FaucetPay ADA (Cardano)', type: K.WalletType.FP_ADA }, { id: '200', name: 'ExpressCrypto (EC-UserId-XXXXXX)', type: K.WalletType.EC }, { id: '1', name: 'BTC Alternative Address', type: K.WalletType.BTC } ]; async function start() { await loader.initialize(); ui.init(getCFlist(), Schedule.getAll()); uiRenderer.appendEventListeners(); shared.purgeFlowControlSchedules(Schedule.getAll().map(x => x.uuid)); update(); uiRenderer.wallet.legacyRenderWalletTable(userWallet); intervalUiUpdate = setInterval(readUpdateValues, 10000); Schedule.getAll().forEach(x => { x.start(); }); if (document.querySelector('#console-log').innerText == 'Loading...') { document.querySelector('#console-log').innerHTML = '
Running...
'; } getFeedInterval = setInterval(getCodesFeed, 25000); }; let loader = function() { async function initialize() { setTimestamp(); await Schedule.initialize(); await initializeSites(); initializeUserWallet(); initializePromotions(); initializeHistory(); }; async function initializeSites() { Site.createFromDataArray(sites); await updateSitesWithStoredData(); await addSitesToSchedules(); }; async function updateSitesWithStoredData() { let storedData = persistence.load('webList', true); if (storedData) { storedData.forEach( function (stored) { if (stored.isExternal) { stored.url = new URL(stored.url); Site.add(stored); } let site = Site.getById(stored.id); if (!site) { return; } for (const prop in stored) { site[prop] = stored[prop]; } if (!site.enabled) { site.nextRoll = null; } else { site.nextRoll = site.nextRoll ? new Date(site.nextRoll) : new Date(); } if (site.aggregate || site.balance) { site.firstRun = false; } }) } }; async function addSitesToSchedules() { Site.getAll().forEach(site => { let scheduleOfSite = Schedule.getById(site.schedule); if (!scheduleOfSite) { console.warn(`Attention! Site ${site.name} has a reference to a schedule that does not exist: (${site.schedule})`); scheduleOfSite = Schedule.getAll()[0]; console.warn(`Assigning it to first schedule (${scheduleOfSite.uuid}) instead.`); site.schedule = scheduleOfSite.uuid; // use .changeSchedule to save the change??? } scheduleOfSite.addSite(site); }); }; function initializeUserWallet() { addWallets(); addStoredWalletData(); }; function addWallets() { wallet.forEach(x => userWallet.push(x)); userWallet.forEach(function (element, idx, arr) { arr[idx].address = ''; }); }; function addStoredWalletData() { let storedData = persistence.load('userWallet', true); if(storedData) { storedData.forEach( function (element) { let idx = userWallet.findIndex(x => x.id == element.id); if(idx != -1) { userWallet[idx].address = element.address ?? userWallet[idx].address; } }); } }; function initializePromotions() { let storedData = persistence.load('CFPromotions', true); if (storedData) { let mig00200799 = false; try { mig00200799 = shared.getConfig().migrations.find(x => x.version == '00200799' && !x.applied); } catch (err) {} let allCFs = manager.getFaucetsForPromotion().map( cf => cf.id ); storedData.forEach( function (element, idx, arr) { arr[idx].added = new Date(element.added); arr[idx].statusPerFaucet.forEach( function (el, i, a) { a[i].execTimeStamp = (el.execTimeStamp != null) ? new Date(el.execTimeStamp) : null; if (mig00200799 && el.status == 4) { a[i].status = 1; } }); allCFs.forEach( function (cf) { if (!arr[idx].statusPerFaucet.find( x => x.id == cf )) { let newCf = { id: cf, status: 1, execTimeStamp: null }; arr[idx].statusPerFaucet.push(newCf); } }); }); if (mig00200799) { shared.migrationApplied('00200799'); } CFPromotions.load(storedData); } }; function initializeHistory() { CFHistory.initOrLoad(); }; function setTimestamp() { timestamp = Date.now(); persistence.save('timestamp', timestamp); }; return { initialize: initialize }; }(); function getCodesFeed(force = false) { clearInterval(getFeedInterval); if (!force) { let tryGet = shared.getConfig()['cf.tryGetCodes'] || false; if (!tryGet) { return; } } let nextFeed = helpers.randomMs(2 * 60 * 60 * 1000, 4 * 60 * 60 * 1000); getFeedInterval = setInterval(getCodesFeed, nextFeed) GM_xmlhttpRequest({ method: "GET", url: "https://criptologico.com/api/?key=XI2HV-1P9PQ-W637F-68B9B-A248&requests[cf_codes]", timeout: 10000, onload: function(response) { try { let txt = response.responseText; let parsed = JSON.parse(txt); if (parsed.success) { let newCodes = []; for(let i = 0; i < parsed.cf_codes.length; i++) { let item = parsed.cf_codes[i]; let newCode = {}; newCode.code = item.code; newCode.oneTimeOnly = item.is_one_time == '1'; newCode['expiration' + 'Date'] = item.expiration_date.replace(' ', 'T') + 'Z'; newCode['expiration' + 'Date'] = new Date(newCode['expiration' + 'Date']); newCodes.push(newCode); } CFPromotions.includeNewCodes(newCodes); uiRenderer.promos.legacyRenderPromotionTable(CFPromotions.getAll()); } } catch(err) { console.error('unexpected error parsing codes list'); console.error(err); } }, onerror: function(e) { console.error('error getting codes'); console.error(e); }, ontimeout: function() { console.error('timeout getting codes'); }, }); } function readUpdateValues(forceCheck = false) { readPromoCodeValues(); readModalData(); if(true) { let updateDataElement = document.getElementById('update-data'); let updateValues = updateDataElement.innerText.clean(); if (updateValues != '') { updateDataElement.innerText = ''; let updateObj = JSON.parse(updateValues); if(updateObj.editSingle.changed) { updateObj.editSingle.items.forEach(function (element, idx, arr) { try { let site = Site.getById(element.id); site.name = element.displayName; if (site.enabled != element.enabled) { site.enabled = element.enabled; if(site.enabled) { site.nextRoll = new Date(idx); } else { site.nextRoll = null; } } ui.log({ schedule: site.schedule, msg: `Faucet updated. New name: ${element.displayName}. Active: ${element.enabled}` }); } catch (err) { ui.log({ schedule: this.uuid, msg: `Error updating faucet data: ${err}` }); } }); } if(updateObj.wallet.changed) { updateObj.wallet.items.forEach(function (element) { try { let itemIndex = userWallet.findIndex(x => x.id == element.id); userWallet[itemIndex].address = element.address; ui.log({ msg: `Wallet Address updated [${userWallet[itemIndex].name}]: ${userWallet[itemIndex].address}` }); } catch (err) { ui.log({ msg: `Error updating wallet/address: ${err}` }); } }); uiRenderer.wallet.legacyRenderWalletTable(userWallet); saveUserWallet(); } if(updateObj.config.changed) { try { shared.updateConfig(updateObj.config.items); ui.log({ msg: `Config updated. Reloading in a few seconds...` }); window.location.reload(); return; } catch (err) { ui.log({ msg: `Error updating config: ${err}` }); } } if(updateObj.site.changed) { updateObj.site.list.forEach( (x) => { try { updateSite(x.id, x.items); } catch (err) { ui.log({ msg: `Error updating site: ${err}` }); } }); } if(updateObj.runAsap.changed || updateObj.editSingle.changed || updateObj.site.changed) { resyncAll({ withUpdate: true }); return; } } } if(forceCheck) { resyncAll({ withUpdate: false }); } }; function resyncAll(options = { withUpdate: false} ) { if (options.withUpdate) { update(true); } Schedule.getAll().forEach(x => { x.checkNextRoll(); }); } function updateSite(id, items) { let site = Site.getById(id); if (site) { site.params = site.params || {}; items.forEach( (item) => { site.params[item.prop] = item.value; }); ui.log({ schedule: site.schedule, siteName: site.name, msg: `Site ${site.name} updated` }); } } function readModalData() { // This should be migrated and dissapear! if(document.getElementById('modal-spinner').isVisible()) { let targetObject = JSON.parse(document.getElementById('target-spinner').innerHTML); let target = targetObject.id; if (target == 'modal-ereport') { let temp = shared.getDevLog(); document.getElementById('log-textarea').value = temp.join('\n'); } else if (target == 'modal-config') { uiRenderer.config.legacyRenderConfigData(shared.getConfig()); } else if (target == 'modal-site') { let site = Site.getById(targetObject.siteId); uiRenderer.sites.legacyRenderSiteData(site, shared.getConfig()); } document.getElementById('modal-spinner').classList.toggle('d-none'); document.getElementById(target).classList.toggle('d-none'); document.getElementById('target-spinner').innerHTML = ''; } } function sortSites () { // Temporary, just to decouple it... Site.sortAll(); Schedule.getAll().forEach( schedule => schedule.sortSites() ); }; function update(sortIt = true) { if(sortIt) { sortSites(); Schedule.getAll().forEach( schedule => schedule.setCurrentSite() ); } Site.saveAll(); Site.getAll().forEach(site => { uiRenderer.sites.renderSiteRow(site); }); uiRenderer.sites.removeDeletedSitesRows(Site.getAll().map(x => x.id)); convertToFiat(); uiRenderer.sites.sortSitesTable(); // y reordenar uiRenderer.promos.legacyRenderPromotionTable(CFPromotions.getAll()); updateRollStatsSpan(); }; function saveUserWallet() { const data = userWallet.map(x => { return { id: x.id, address: x.address };}); persistence.save('userWallet', data, true); } function isObsolete() { let savedTimestamp = persistence.load('timestamp'); if (savedTimestamp && savedTimestamp > timestamp) { ui.log({ msg: 'STOPING EXECUTION! A new Manager UI window was opened. Process should continue there' }); clearInterval(intervalUiUpdate); return true; } return false; }; function readPromoCodeValues() { let promoCodeElement = document.getElementById('promo-code-new'); let promoDataStr = promoCodeElement.innerText.clean(); if (promoDataStr == '') { return; } let promoData = JSON.parse(promoDataStr); if(promoData.action) { switch (promoData.action) { case 'FORCESTOPFAUCET': Schedule.getAll().forEach(s => { if (s.status != STATUS.IDLE) { s.currentSite.enabled = false; s.closeTab(); } }); update(true); shared.clearFlowControl('all'); setTimeout(() => { window.location.reload(); }, 3000); promoCodeElement.innerText = ''; break; case 'ADD': CFPromotions.addNew(promoData.code, promoData.repeatDaily); promoCodeElement.innerText = ''; document.getElementById('promo-text-input').value = ''; uiRenderer.toast("Code " + promoData.code + " added!"); ui.log({ msg: `Promo code ${promoData.code} added` }); uiRenderer.promos.legacyRenderPromotionTable(CFPromotions.getAll()); break; case 'REMOVEALLPROMOS': CFPromotions.removeAll(); promoCodeElement.innerText = ''; uiRenderer.toast("Promo codes removed!"); ui.log({ msg: `Promo codes removed` }); uiRenderer.promos.legacyRenderPromotionTable(CFPromotions.getAll()); break; case 'REMOVE': if(CFPromotions.remove(promoData.id, promoData.code) != -1) { ui.log({ msg: `Promo code ${promoData.code} removed` }); } else { ui.log({ msg: `Unable to remove code ${promoData.code}` }); } promoCodeElement.innerText = ''; uiRenderer.promos.legacyRenderPromotionTable(CFPromotions.getAll()); break; case 'TRYGETCODES': getCodesFeed(true); promoCodeElement.innerText = ''; uiRenderer.toast("Looking for new codes!"); break; } } }; function updateRollStatsSpan() { let rollsSpanElement = document.getElementById('rolls-span'); rollsSpanElement.innerText = CFHistory.getRollsMeta().join(','); }; function getCFlist() { let items; items = Site.getAll().filter(f => f.type === K.WebType.CRYPTOSFAUCETS); items = items.map(x => { return { id: x.id, name: x.coinRef };}); items.sort((a, b) => (a.name > b.name) ? 1 : -1); return items; }; function closeWorkingTab(schedule) { let sc = Schedule.getAll().find(x => x.uuid == schedule); if (sc) sc.closeTab() }; function reloadWorkingTab(schedule) { let sc = Schedule.getAll().find(x => x.uuid == schedule); if (sc) { sc.closeTab(); sc.reopenTab(); } }; function getAllSites() { return Site.getAll(); } return{ start: start, getFaucetsForPromotion: getCFlist, closeWorkingTab: closeWorkingTab, reloadWorkingTab: reloadWorkingTab, getAllSites: getAllSites, resyncAll: resyncAll, isObsolete: isObsolete, update: update, userWallet: userWallet, readUpdateValues: readUpdateValues }; } function createUi() { let injectables = { managerJs: function () { window.myBarChart = null; window.landing = window.location.host; window.sendErrorReport = function sendErrorReport() { try { let header = new Headers(); header.append("Content-Type", "application/json"); let description = document.getElementById("log-message").value; let log = document.getElementById("log-textarea").value.split('\n'); let content = {"description":description, "log":log}; let opt = { method: "POST", header, mode: "cors", body: JSON.stringify(content) }; fetch("https://1d0103ec5a621b87ea27ffed3c072796.m.pipedream.net", opt).then(response => { }).catch(err => { console.error("[error] " + err.message); }); } catch { } }; window.getUpdateObject = function getUpdateObject() { let updateObject; var updateData = document.getElementById("update-data"); if (updateData.innerHTML != "") { updateObject = JSON.parse(updateData.innerHTML); } else { updateObject = { runAsap: { ids: [], changed: false}, editSingle: { changed: false, items: [] }, wallet: { changed: false, items: []}, config: { changed: false, items: []}, site: { changed: false, list: []} }; } return updateObject; }; window.removePromoCode = function removePromoCode(id, code) { var promoCode = document.getElementById("promo-code-new"); var promoObject = { action: "REMOVE", id: id, code: code }; promoCode.innerHTML =JSON.stringify(promoObject); }; window.editWallet = { save: function() { let updateObject = getUpdateObject(); document.querySelectorAll("#wallet-table-body tr").forEach( function(row) { let textInput = row.querySelector(".em-input input"); if(textInput.dataset.original != textInput.value) { let single = { id: row.dataset.id, address: textInput.value.trim() }; updateObject.wallet.items.push(single); updateObject.wallet.changed = true; } }); if(updateObject.wallet.changed) { document.getElementById("update-data").innerHTML = JSON.stringify(updateObject); toastr["info"]("Wallet will be updated as soon as possible"); } }, toggleJson: function(val) { if (document.querySelector('#wallet-json').isVisible()) { if(val != 'cancel') { editWallet.fromJson(); } } else { editWallet.toJson(); } document.querySelector('.footer-json').classList.toggle('d-none'); document.querySelector('.footer-table').classList.toggle('d-none'); document.querySelector('#wallet-table').classList.toggle('d-none'); document.querySelector('#wallet-json').classList.toggle('d-none'); }, toJson: function() { let j = []; document.querySelectorAll('#wallet-table-body tr').forEach(function (row) { j.push({ id: row.dataset.id, address: row.querySelector('.em-input input').value }); }); document.querySelector('#wallet-json').value = JSON.stringify(j); }, fromJson: function() { let j = JSON.parse(document.querySelector('#wallet-json').value); document.querySelectorAll('#wallet-table-body tr').forEach(function (row) { let element = j.find(x => x.id == row.dataset.id); if (element) { row.querySelector('.em-input input').value = element.address; } }); }, cancel: function() { document.querySelectorAll("#wallet-table-body .em-input input").forEach( function(x) { x.value = x.dataset.original; }); } }; window.editConfig = { save: function() { let updateObject = getUpdateObject(); document.querySelectorAll("#modal-config [data-original][data-prop]").forEach(function(elm) { let single = { prop: elm.dataset.prop, value: elm.dataset.value }; if(elm.dataset.original != elm.value && (elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") ) { single.value = elm.value; updateObject.config.items.push(single); updateObject.config.changed = true; } else if (elm.type == "checkbox" && ((elm.dataset.original == "0" && elm.checked) || (elm.dataset.original == "1" && !elm.checked)) ) { single.value = elm.checked; updateObject.config.items.push(single); updateObject.config.changed = true; } }); if(updateObject.config.changed) { document.getElementById("update-data").innerHTML = JSON.stringify(updateObject); toastr["info"]("Config will be updated as soon as possible"); } }, cancel: function() { document.querySelectorAll("#modal-config [data-original][data-prop]").forEach(function(elm) { if(elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") { elm.value = elm.dataset.original; } else if (elm.type == "checkbox") { elm.checked = (elm.dataset.original == "1" ? true : false) } }); } }; window.editSite = { save: function() { let updateObject = getUpdateObject(); let faucet = { id: document.querySelector("#faucet-name").dataset.id, items: [] }; document.querySelectorAll("#modal-site [data-original][data-site-prop]").forEach(function(elm) { let single = { prop: elm.dataset.siteProp, value: elm.dataset.original }; if(elm.dataset.original != elm.value && (elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") ) { single.value = elm.value; faucet.items.push(single); updateObject.site.changed = true; } else if (elm.type == "checkbox" && ((elm.dataset.original == "0" && elm.checked) || (elm.dataset.original == "1" && !elm.checked)) ) { single.value = elm.checked; faucet.items.push(single); updateObject.site.changed = true; } }); if(updateObject.site.changed) { updateObject.site.list.push(faucet); document.getElementById("update-data").innerHTML = JSON.stringify(updateObject); toastr["info"]("Site will be updated as soon as possible"); } }, cancel: function() { document.querySelectorAll("#modal-site [data-original][data-site-prop]").forEach(function(elm) { if(elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") { elm.value = elm.dataset.original; } else if (elm.type == "checkbox") { elm.checked = (elm.dataset.original == "1" ? true : false) } }); } }; window.editEreport = { save: function() { sendErrorReport(); }, cancel: function() { } }; window.modalSave = function modalSave(content) { switch(content) { case "wallet": editWallet.save(); break; case "ereport": editEreport.save(); break; case "config": editConfig.save(); break; case "site": editSite.save(); break; case "slAlert": shortlinkAlert.save(); break; } }; window.modalCancel = function modalCancel(content) { if(content == "wallet") { editWallet.cancel(); } else if ("ereport") { editEreport.cancel(); } document.querySelectorAll("modal-content").forEach(x => x.classList.add("d-none")); }; window.updateValues = function updateValues(type, values) { let updateObject = getUpdateObject(); if (type == "runAsap") { updateObject.runAsap.ids.push(values.id); updateObject.runAsap.changed = true; document.getElementById("update-data").innerHTML = JSON.stringify(updateObject); uiRenderer.toast("Faucet will be updated to run as soon as possible"); } }; window.schedulesInterval = null; window.startSchedulesInterval = function startSchedulesInterval(uuids) { if (window.schedulesInterval) { clearInterval(window.schedulesInterval); } let innerWaitTimes = ''; uuids.forEach(x => { innerWaitTimes += ``; }); let container = document.querySelector('#wait-times'); container.innerHTML = innerWaitTimes; window.schedulesInterval = setInterval(() => { [...document.querySelectorAll('#wait-times > span')].forEach(sp => { let nroll = sp.getAttribute('data-nextroll'); let spanScheduleId = sp.getAttribute('data-schedule'); if (nroll == 'UNDEFINED') { sp.querySelector('span').innerText = '-'; } else if (nroll == 'RUNNING') { sp.querySelector('span').innerText = 'Running'; let inUseElm = document.querySelector(`#schedule-table tr[data-schedule="${spanScheduleId}"]`); if (inUseElm) { inUseElm.classList.add('in-use'); } } else { let timeVal = +nroll - Date.now(); sp.querySelector('span').innerText = timeVal.msToCountdown(); if (timeVal < -60000) { console.info(`Resync required: ${timeVal}`); } } }) }, 1000); } window.confirmable = { open: function (req, details = null, params = null) { let btn = document.getElementById("confirm-req-btn"); btn.setAttribute('data-request', req); btn.setAttribute('data-params', params ? JSON.stringify(params) : '{}'); if(details) { document.querySelector("#confirmable-modal p").innerText = details; } return; }, accept: function () { let btn = document.getElementById("confirm-req-btn"); let req = { type: '', params: {}}; req.type = btn.getAttribute('data-request'); req.params = JSON.parse(btn.getAttribute('data-params')); switch(req.type) { case 'removeAllPromos': window.removeAllPromos(); break; case 'forceStopFaucet': window.forceStopFaucet(); break; default: break; } } } window.removeAllPromos = function removeAllPromos() { var promoCode = document.getElementById("promo-code-new"); var promoObject = { action: "REMOVEALLPROMOS" }; promoCode.innerHTML =JSON.stringify(promoObject); toastr["info"]("Removing all promo codes... please wait"); }; window.forceStopFaucet = function forceStopFaucet() { var promoCode = document.getElementById("promo-code-new"); var promoObject = { action: "FORCESTOPFAUCET" }; promoCode.innerHTML =JSON.stringify(promoObject); toastr["info"]("Trying to stop... Please wait for reload"); }; window.openStatsChart = function openStatsChart() { if(myBarChart) { myBarChart.destroy(); } let statsFragment = document.getElementById("stats-fragment"); if (statsFragment.style.display === "block") { statsFragment.style.display = "none"; document.getElementById("stats-button").innerText = "Lucky Number Stats"; } else { statsFragment.style.display = "block"; document.getElementById("stats-button").innerText = "Close Stats"; var canvas = document.getElementById("barChart"); var ctx = canvas.getContext("2d"); var dataSpan = document.getElementById("rolls-span"); var data = { labels: ["0000-9885", "9886-9985", "9986-9993", "9994-9997", "9998-9999", "10000"], datasets: [ { fill: false, backgroundColor: [ "#990000", "#660066", "#000099", "#ff8000", "#ffff00", "#00ff00"], data: dataSpan.innerText.split(",") } ] }; var options = { plugins: { legend: { display: false } }, title: { display: true, text: "Rolled Numbers", position: "top" }, rotation: -0.3 * Math.PI }; myBarChart = new Chart(ctx, { type: "doughnut", data: data, options: options }); } }; window.shortlinkAlert = { load: function(id, destination) { let hideShortlinkAlerts = localStorage.getItem("hideShortlinkAlerts"); hideShortlinkAlerts = hideShortlinkAlerts ? JSON.parse(hideShortlinkAlerts) : false; if (hideShortlinkAlerts) { } else { document.getElementById(id).classList.remove("d-none"); } }, save: function () { localStorage.setItem("hideShortlinkAlerts", JSON.stringify(document.getElementById("hideShortlinkAlerts").checked)); window.open("https://example.com", "_blank"); } } } }; let logLines = []; function init(cfFaucets, schedules) { appendJavaScript(); appendHtml(schedules); updateSchedulesToggler(); appendEventListeners(); appendWidgets(); setupEventerListeners(); createPromoTable(cfFaucets); try { document.querySelector('.page-title h1').innerHTML = 'Auto Claim'; } catch (err) {} }; function setupEventerListeners() { eventer.on('siteUpdated', (site) => { Site.sortAll(); // en todos los sites... let schedule = Schedule.getById(site.schedule); schedule.sortSites(); // solo en el schedule de este site schedule.setCurrentSite(); // solo en el schedule de este site Site.saveAll(); uiRenderer.sites.renderSiteRow(site); // solo la row de este site uiRenderer.sites.sortSitesTable(); // y reordenar schedule.checkNextRoll(); // solo en el schedule de este site convertToFiat(); }); } function appendWidgets() { $('.tableSortable').sortable({ placeholder:'sort-highlight', handle:'.row-handle', cursor: 'grabbing', axis: 'y', stop: function(event, ui) { $("tbody.ui-sortable tr").each(function(index) { $(this).attr("data-order", index); }); } }); $('#promo-daily').bootstrapSwitch(); $('#bss-log').bootstrapSwitch({ onSwitchChange(event, state) { $('#console-log').collapse('toggle'); }, onInit: function(event, state) { this.$element.closest('.bootstrap-switch-container').find('.bootstrap-switch-handle-on').first().addClass('fa fa-eye').text(''); this.$element.closest('.bootstrap-switch-container').find('.bootstrap-switch-handle-off').first().addClass('fa fa-eye-slash').text(''); } }); }; function updateSchedulesToggler() { let container = document.querySelector('#schedules-toggler'); let html = ''; Schedule.getAll().forEach(x => { html += ``; }); container.innerHTML = html; startSchedulesInterval(Schedule.getAllForCrud().map(x => x.uuid)); uiRenderer.schedules.toggleSchedule('all'); }; function appendEventListeners() { document.querySelector('.dropdown-settings-menu').addEventListener('click', function(e) { let actionElement = e.target.tagName === 'I' ? e.target.parentElement : e.target; if (actionElement.dataset.target) { e.stopPropagation(); uiRenderer.openModal(actionElement.dataset.target); } }); const modalSchedules = document.querySelector('#modal-schedules'); modalSchedules.addEventListener('click', function(e) { let actionElement = e.target.tagName === 'I' ? e.target.parentElement : e.target; if (actionElement.classList.contains('action-schedule-add')) { e.stopPropagation(); let rows = modalSchedules.querySelectorAll('table tbody tr'); let rndColor = helpers.randomHexColor(); let rowTemplate = uiRenderer.schedules.renderRow({ uuid: rndColor, name: rndColor, order: rows.length, added: true }); $(modalSchedules.querySelector('table tbody tr:last-child')).after(rowTemplate); uiRenderer.appendColorPickers('table tbody tr:last-child .color-picker'); } else if (actionElement.classList.contains('action-schedule-remove')) { let rows = modalSchedules.querySelectorAll('table tbody tr:not(.d-none)'); if (rows.length <= 1) { alert('You need to keep at least 1 schedule'); } else { let current = actionElement.closest('tr'); if (current.dataset.added === 'true') { current.remove(); } else { current.dataset.removed = 'true'; current.classList.add('d-none'); } } } else if (actionElement.classList.contains('modal-save')) { let data = uiRenderer.parseTable(modalSchedules.querySelector('table')); let isValid = Schedule.crud(data); updateSchedulesToggler(); manager.resyncAll({withUpdate: true}); if (!isValid) { uiRenderer.toast('Some schedules might have errors/invalid colors', 'warning'); } } }); }; function appendJavaScript() { addJS_Node (null, null, injectables.managerJs); }; function addCardHtml(obj) { return `
${obj.header}
${obj.body}
`; }; function addRandomBetween(propSelect, propMin, propMax) { return `
andminutes
`; } function appendHtml(schedules) { let html =''; let tgt = document.querySelector('div.row.py-3'); if (tgt) { let rowDiv = document.createElement('div'); rowDiv.innerHTML = '
'; tgt.after(rowDiv); } html += ''; html += ''; html += '
'; html += 'Force Stop'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += ''; html += ` `; html += ''; html += ''; html += '
'; html += '
'; html += '
'; html += '
'; html += '
Loading...
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '

Promo Codes

'; html += '
'; html += '
'; html += ''; html += ''; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html +='
'; html += '
'; html += ''; html +='
'; let wrapper = document.createElement('div'); wrapper.innerHTML = html.trim(); let target = document.getElementById('referral-table'); target.parentNode.insertBefore(wrapper, target); document.getElementById('schedule-container').appendChild( createScheduleTable() ); if (document.querySelector('.main-header .navbar-nav.ml-auto')) { let discord = document.createElement('li'); discord.classList.add('nav-item'); discord.innerHTML = '
(new)discord
'; document.querySelector('.main-header .navbar-nav.ml-auto').prepend(discord); } else { let discord = document.createElement('div'); discord.innerHTML = '
(new)discord
'; document.querySelector('.navbar-nav').prepend(discord); } addHtml({ target: '#modal-dlg .modal-dialog', where: 'afterbegin', content: `` }); addTemplateTag({ id: 'tpl-requirement-row', content: `{name}{description}{suggestion}` }); const tempRequirementsList = [ { id: '1', name: 'HCaptcha Solver', description: 'A solver for HCaptcha challenges', suggestion: `Latest github version of hektCaptcha extension (free)
Visit` }, { id: '2', name: 'Recaptcha Solver', description: 'A solver for ReCaptcha challenges', suggestion: `Latest github version of hektCaptcha extension (free)
Visit` }, { id: '3', name: 'Cloudflare Challenge Bypass', description: 'A solver for Cloudflare/Turnstile challenges', suggestion: `Auto clicker user script (free)
Visit` }, { id: '6', name: 'Active Tab/Window', description: 'The site requires the tab to be active. A good option is Tab Revolver Extension, which will loop the tabs opened in a specific window.', suggestion: ` User Script or Extension` }, ]; for(let r=0; r< tempRequirementsList.length; r++) { let req = tempRequirementsList[r]; useTemplate({ templateId: 'tpl-requirement-row', target: '#requirements-table-body', where: 'afterbegin', replacements: req }); } }; function createPromoTable(faucets) { let table = document.createElement('table'); let inner = ''; table.classList.add('table', 'custom-table-striped'); table.setAttribute('id','promo-table'); inner += '⏳ Pending ✔️ Accepted 🕙 Used Before ❌ Invalid code ❗ Unknown error ⚪ No code'; inner += 'CodeAdded'; for (let i = 0, all = faucets.length; i < all; i++) { inner += '' + faucets[i].name + ''; } inner += ''; table.innerHTML = inner document.getElementById('promo-container').appendChild( table ); }; function createScheduleTable() { let table = document.createElement('table'); let inner; table.classList.add('table', 'custom-table-striped', 'table-head-fixed', 'text-nowrap'); table.setAttribute('id','schedule-table'); inner = ''; inner += 'ActiveNext RollNameLast Claim'; inner += 'AggregateBalanceFIAT'; inner += 'Msgs'; inner += ''; inner += `
`; inner += ''; table.innerHTML = inner; return table; }; function renderLogRow(data) { let tr = document.createElement('tr'); tr.dataset.schedule = data.schedule; tr.dataset.ts = data.ts.getTime(); tr.dataset.siteName = data.siteName || ''; tr.dataset.elapsed = data.elapsed || ''; let color = data.schedule ? `#${data.schedule}` : `transparent`; let showIt = !data.schedule || !uiRenderer.schedules.selectedSchedule || uiRenderer.schedules.selectedSchedule == 'all' || uiRenderer.schedules.selectedSchedule == data.schedule; if (!showIt) { tr.classList.add('d-none'); } let tds = ''; tds += `${helpers.getPrintableTime(data.ts)}`; tds += ``; if (data.elapsed) { tds += `${data.msg} [Elapsed time: ${data.elapsed} seconds]`; } else { tds += `${data.msg}`; } tr.innerHTML = tds; document.querySelector('#console-log table').appendChild(tr); }; function log(data) { if (!data || !data.msg) { console.warn(`Log attempt without data or msg!`, data); return; } data.ts = new Date(); data.schedule = data.schedule || false; data.siteName = data.siteName || false; data.elapsed = data.elapsed || false; if(shared.getConfig()['devlog.enabled']) { if (data.schedule) { } else { } }; if (data.elapsed) { let previous = logLines.find(x => x.msg == data.msg && x.schedule == data.schedule); if (previous) { previous.elapsed = data.elapsed; previous.ts = data.ts; logLines.sort( (a, b) => b.ts.getTime() - a.ts.getTime()); } else { logLines.unshift(data); } } else { logLines.unshift(data); } while(logLines.length > 30) { logLines.pop(); } document.querySelector('#console-log table').innerHTML = ''; logLines.forEach(r => renderLogRow(r)); }; function legacyLog(data, elapsed = false) { if (!data || !data.msg) { return; } elapsed = data.elapsed || false; let msg = data.msg; if (data.schedule) { msg = `[${data.schedule}] ${data.msg}`; } if(shared.getConfig()['devlog.enabled']) { shared.devlog(msg, elapsed) }; if(msg) { let waitingIdx = logLines.findIndex(line => { let waitingMsg= line.split(' ')[1]; if (waitingMsg == msg) { return true; } }); let previous = waitingIdx > -1 ? logLines[waitingIdx].split(' ')[1] : ''; if (elapsed && (previous == msg)) { logLines[waitingIdx] = helpers.getPrintableTime() + ' ' + msg + ' [Elapsed time: ' + elapsed + ' seconds]'; } else { while(logLines.length > 20) { logLines.pop(); } logLines.unshift(helpers.getPrintableTime() + ' ' + msg); } document.getElementById('console-log').innerHTML = logLines.map(x => { const regex = /\[([0-9a-fA-F]+)\]/; const match = regex.exec(x); let colorNumber = null; if (match !== null) { colorNumber = match[1]; } let showIt = !colorNumber || !window.selectedSchedule || window.selectedSchedule == 'all' || window.selectedSchedule == colorNumber; const formattedMsg = x.replace(/\[([0-9a-fA-F]+)\]/, ''); let line = `${formattedMsg}`; return line; }).join(''); } }; return { init: init, log: log } } async function init() { eventer = new EventEmitter(); persistence = new Persistence(); shared = objectGenerator.createShared(); useTimer = shared.getConfig()['defaults.extraInterval']; if (location.href.startsWith('https://criptologico.com/tools/cc')) { landing = window.location.host; instance = K.LOCATION.MANAGER; manager = createManager(); CFPromotions = objectGenerator.createCFPromotions(); uiRenderer = new UiRenderer(); uiRenderer.initialize(); ui = createUi(); CFHistory = objectGenerator.createCFHistory(); await manager.start(); try { if (!document.body.classList.contains('sidebar-collapse')) document.querySelector('a[data-widget="pushmenu"]').click() } catch {} setTimeout( () => { window.stop(); }, 10000); } else { instance = K.LOCATION.UNKNOWN; detectWeb(); } } init(); })();