// ==UserScript==
// @name [satology] Auto Claim Multiple Faucets with Monitor UI
// @description Freebitco.in, StormGain Miner, 15 Faucets with Promo Codes + Autologin, FaucetPay PTC, etc.
// @description Automatic activation of StormGain Miner every 4 hours and hourly claim of free ADA, BNB, BCH, BTC, DASH, DGB, DOGE, ETH, FEY, LINK, LTC, NEO, STEAM, TRX, USDC, USDT, XEM, XRP, ZEC
// @version 1.5.15
// @author satology
// @namespace satology.onrender.com
// @homepage https://satology.onrender.com/faucets/referrals
// @note @1.5.13 : > Added 'Ok' (6 hourly faucets with direct payment to FP). Issue: they have popups. This script is not handling them. In case you need an ad blocker, I've created a simple script for this
// @note specific case that you could use and adjust if you need to: (https://greasyfork.org/en/scripts/429739-closewindowbyname)
// @note > Added BigBtc. It's set to run based on 'postponedMinutes' interval but it's a 5 min faucet. You can change the delay in the script if you want to. I wouldn't abuse it as it's easy for a
// @note faucet admin to ban your address @ Fp. Also, it has manual payment (not implemented).
// @note > Added signout at B/K BCH, to force login with address as the faucets have a bug (might use your ERC20 address if you previously claim TRX/USDT, instead of asking to login)
// @note @1.5.12 : > Added some workarounds for those who don't like the script to be waiting when the sites are redirected to an Ad:
// @note 1. Timer/interval that saves the timestamp every 10 seconds when processing/navigating a site. This should avoid waiting too long in case of ad redirects,
// @note BUT it will consume more resources. You can enable it in the script, by setting useTimer to true (almost at the end of the script).
// @note When enabled, it will be used only at B/K, Free-Litecoin and Free-Ethereum.
// @note If a site is closed by this timer, it will display the error 'FORCE_CLOSED' at the schedule
// @note 2. Added a retry logic for this faucets (when FORCE_CLOSED): whenever there's a time window (greater than timeout/2), it will try to run again the last one that failed
// @note > Added ErrorType to a const/enum. Errors from previous versions of the script (were plain strings) will be displayed as '_ERR'
// @note I'm not setting this stuff to be configured at the UI as I don't think it's worth it and might be confusing.
// @note Same goes for enabling individual faucets to run on focus instead of background (as FP PTC does). I've added a line you can uncomment to do the same with StormGain
// @note if you are having trouble with the auto activation when it's on the background (search for RUN STORMGAIN)
// @note - IMPORTANT -------------------------------------------------------------------------------------------------------------------------------------------------------------------
// @note YOU MUST HAVE A hCaptcha solver INSTALLED to claim from the faucets
// @note I recommend this script: https://greasyfork.org/en/scripts/425854-hcaptcha-solver-automatically-solves-hcaptcha-in-browser
// @note At least until version 3.5 of the hCaptcha solver script, to roll Free-ethereum.io, you'd need to add the following two lines, right at the beginning of function getSynonyms(word) [line 232]:
// @note const WORDS_WITH_CYRILLIC = {'аirplane': AIRPLANE, 'bіcycle': BICYCLE, 'bοat': BOAT, 'сar': CAR, 'mοtorbus': MOTORBUS, 'mοtorcycle': MOTORCYCLE, 'trаin': TRAIN, 'truсk': TRUCK };
// @note word = (encodeURIComponent(word).indexOf('%') > -1) ? WORDS_WITH_CYRILLIC[word] : word;
// @note -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// @note - MAIN FEATURES ------------------------------------------------------------------------------------------------------------------------------------------------
// @note > Automatic rolls and claims for faucets/PTCs/miners
// @note > Accepts promotion codes (http://twitter.com/cryptosfaucets, free roll shortlinks) for CF 15 faucets
// @note > Simple Monitor UI on top of a website to track progress (claims, next rolls, promo codes)
// @note - IMPORTANT CONSIDERATIONS -------------------------------------------------------------------------------------------------------------------------------------
// @note 0. You need to enable popups on the Manager UI website to be able to open the faucets
// @note 1. CF FAUCETS WEBSITES MUST OPEN IN ENGLISH TO BE ABLE TO RECOGNIZE IF THE PROMO CODE WAS ACCEPTED
// @note In case you don't want to have them in English, you need to change the 3 strings the code uses for validation and change setToEnglish to false
// @note (Search for localeStrings in the code)
// @note 2. Autorolls will trigger ONLY when the faucet was opened by the Manager UI.
// @note This is to allow users to navigate the websites to get the ShortLinks extra rolls, for example,
// @note without having to stop the script.
// @note 3. You can enable/disable faucets from the UI. By default they are all set to false.
// @note It would be great if you could use my referral links listed below if you need an account.
// @note To disable them, just set enabled: false in the webList array, save the script & refresh the manager
// @note 4. You can change the configuration to enable autologin, RP free roll bonus, etc.
// @note 5. All data stored for tracking and to be displayed is stored locally in your environment. Nothing is uploaded.
// @note Always open to feedback. I'd be glad to hear from you if you find any bugs, have suggestions or new enhancements/features you'd like to see
// @note ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// @note DISCLAIMER: This script is shared to help. Use at your own discretion. I've being using it for months and works fine but I cannot
// @note guarantee that the faucets won't ban your IP or account
// @note ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// @note ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// @note If you wanna team up or just share some ideas, you can contact me at [email protected]
// @note ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// @grant GM_info
// @grant GM_setValue
// @grant GM_getValue
// @grant window.close
// @grant GM_openInTab
// @icon https://www.google.com/s2/favicons?domain=stormgain.com
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @match https://satology.onrender.com/faucets/referrals*
// @match https://app.stormgain.com/crypto-miner/
// @match https://freecardano.com/*
// @match https://freebinancecoin.com/*
// @match https://freebitcoin.io/*
// @match https://freedash.io/*
// @match https://free-doge.com/*
// @match https://freeethereum.com/*
// @match https://freechainlink.io/*
// @match https://free-ltc.com/*
// @match https://freeneo.io/*
// @match https://freesteam.io/*
// @match https://free-tron.com/*
// @match https://freeusdcoin.com/*
// @match https://freetether.com/*
// @match https://freenem.com/*
// @match https://coinfaucet.io/*
// @match https://freebitco.in/
// @match https://faucetpay.io/ptc
// @match https://faucetpay.io/ptc*
// @match https://faucetpay.io/account/login
// @match https://faucetpay.io/account/login/not-logged-in
// @match https://free-litecoin.com/*
// @match https://www.free-ethereum.io/
// @match https://www.free-ethereum.io/free/
// @match https://bagi.co.in/*
// @match https://keran.co/*
// @match https://btc-ok.net/*
// @match https://dash-ok.net/*
// @match https://dgb-ok.net/*
// @match https://doge-ok.net/*
// @match https://eth-ok.net/*
// @match https://ltc-ok.net/*
// @match https://trx-ok.net/*
// @match https://bigbtc.win/*
// ==/UserScript==
(function() {
'use strict';
/**
* Specific string values to check if a promotion code was succesfully processed (used via indexOf).
* Defaults are set for English.
* If you want to view the faucets in another language, you will need to change the following values
*/
const localeConfig = {
setToEnglish: true, // will set the faucets to English
stringSearches: {
promoCodeAccepted: 'roll',
promoCodeUsed: 'already used',
promoCodeInvalid: ['not found', 'only alphanumeric'],
promoCodeExpired: ['ended']
}
};
const WebType = {
CRYPTOSFAUCETS: 1,
STORMGAIN: 2,
FREEBITCOIN: 3,
FAUCETPAY: 4,
FREELITECOIN: 5,
FREEETHEREUMIO: 6,
BAGIKERAN: 7,
OKFAUCET: 8,
BIGBTC: 9
};
const CFUrlType = {
HOME: 0,
FREE: 1,
CONTACTTWITTER: 2,
PROMOTION: 3,
STATS: 4,
SETTINGS: 5,
FREEROLLS: 6,
IGNORE: 99
};
const PromoStatus = {
NOCODE: 0,
PENDING: 1,
ACCEPTED: 2,
USEDBEFORE: 3,
INVALID: 4,
UNKNOWNERROR: 5,
EXPIRED: 6
};
const RandomInteractionLevel = {
NONE: 0,
LOW: 1,
MEDIUM: 2,
HIGH: 3
};
const HS_26_IN_MILLISECONDS = 93600000; //Using 26 hs instead of 24hs
const HS_2_IN_MILLISECONDS = 7200000; //and 2hs gap retry when code is flagged as USEDBEFORE
const USE_DEFAULT = -1;
const CFReusableCodesSuggestion = ['55khv20st4', '90nq6mcmz2', 'lytovoap04', 'vmuph8j0c6', 'ykxlvmg9ja', 'd8fmqxjlma', 'rjnmzjs673'];
const WalletType = {
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
};
const 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
};
let persistence, shared, manager, ui, CFPromotions, interactions, CFHistory, SiteProcessor;
//Extension methods
Element.prototype.isVisible = function() {
return !!(this.offsetWidth||this.offsetHeight||this.getClientRects().length);
};
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;
};
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 = {
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(date, mins) {
return date.setMinutes(date.getMinutes() + parseInt(mins) + 1);
},
randomInt: function(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
},
addMs: function(date, ms) {
return date.setMilliseconds(date.getMilliseconds() + ms);
},
getRandomMs(minute, rangeDiffInPercentage) {
const msCenter = minute * 60 * 1000;
const msRangeDiff = Math.round(msCenter * rangeDiffInPercentage / 100);
return helpers.randomMs(msCenter - msRangeDiff, msCenter + msRangeDiff);
},
hsToMs: function(hours) {
return hours * 60 * 60 * 1000;
},
minToMs: function(min) {
return min * 60 * 1000;
},
getEmojiForPromoStatus: function(promoStatus) {
switch (promoStatus) {
case PromoStatus.NOCODE:
return '⚪';
break;
case PromoStatus.PENDING:
return '⏳';
break;
case PromoStatus.ACCEPTED:
return '✔️';
break;
case PromoStatus.USEDBEFORE:
return '🕙';
break;
case PromoStatus.INVALID:
return '❌';
break;
case PromoStatus.EXPIRED:
return '📅';
break;
case PromoStatus.UNKNOWNERROR:
return '❗';
break;
}
},
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')) {
return CFUrlType.FREE;
}
if (url.includes('/promotion/')) {
return CFUrlType.PROMOTION;
}
if (url.endsWith('/contact-twitter')) {
return CFUrlType.CONTACTTWITTER;
}
if (url.endsWith('/free-rolls')) {
return CFUrlType.FREEROLLS;
}
if (url.endsWith('/settings')) {
return CFUrlType.SETTINGS;
}
if (url.endsWith('/stats')) {
return CFUrlType.STATS;
}
if (url.endsWith('/')) {
url = url.slice(0, -1);
if (url == helpers.getHost(url, true)) {
return CFUrlType.HOME;
}
}
return CFUrlType.IGNORE;
}
}
}
let objectGenerator = {
createPersistence: function() {
const prefix = 'autoWeb_';
function save(key, value, parseIt = false) {
GM_setValue(prefix + key, parseIt ? JSON.stringify(value) : value);
};
function load(key, parseIt = false) {
let value = GM_getValue(prefix + key);
if(value && parseIt) {
value = JSON.parse(value);
}
return value;
};
return {
save: save,
load: load
};
},
createShared: function() {
let flowControl;
let config = {};
function initializeConfig() {
// Defaults:
config['devlog.enabled'] = false;
config['devlog.maxLines'] = 200;
config['defaults.timeout'] = 4;
config['defaults.postponeMinutes'] = 65;
config['defaults.workInBackground'] = true;
config['cf.autologin'] = false;
config['cf.credentials.mode'] = 1;
config['cf.credentials.email'] = '[email protected]';
config['cf.credentials.password'] = 'YOURPASSWORD';
config['cf.sleepHoursIfIpBan'] = 8;
config['fb.activateRPBonus'] = true;
config['fp.hoursBetweenRuns'] = 6;
config['fp.maxTimeInMinutes'] = 15;
config['bk.withdrawMode'] = "1";
config['bk.hoursBetweenWithdraws'] = 4;
config['bk.sleepMinutesIfIpBan'] = 75;
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 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) {
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 isOpenedByManager() {
loadFlowControl();
if(!flowControl) {
return false;
}
if(flowControl.host != window.location.host) {
return false;
}
if(flowControl.opened && flowControl.type != WebType.FAUCETPAY && flowControl.type != WebType.BAGIKERAN) {
return false;
}
if(flowControl.type == WebType.BAGIKERAN && !window.location.href.includes(flowControl.params.trackUrl)) {
return false;
}
return true;
};
function setFlowControl(id, url, webType, params = null) {
flowControl = {
id: id,
changedAt: Date.now(),
url: url,
host: url.host,
type: webType,
opened: false,
error: false,
result: {}
};
if(params) {
flowControl.params = params;
}
saveFlowControl();
};
function wasVisited(expectedId) {
loadFlowControl();
return flowControl.id == expectedId && flowControl.opened;
};
function hasErrors(expectedId) {
return flowControl.id == expectedId && flowControl.error;
};
function getResult() {
return flowControl.result;
};
function getCurrent() {
return flowControl;
};
function saveAndclose(runDetails, delay = 0) {
markAsVisited(runDetails);
shared.devlog(`${window.location.href} closing`);
if(delay) {
setTimeout(window.close, delay);
} else {
window.close();
}
};
function loadFlowControl() {
flowControl = persistence.load('flowControl', true);
};
function saveFlowControl() {
persistence.save('flowControl', flowControl, true);
};
function markAsVisited(runDetails) {
flowControl.opened = true;
flowControl.result = runDetails;
saveFlowControl();
};
function addError(errorType, errorMessage) {
flowControl.error = true;
flowControl.result.errorType = errorType;
flowControl.result.errorMessage = errorMessage;
saveFlowControl();
};
function closeWithError(errorType, errorMessage) {
addError(errorType, errorMessage);
shared.devlog(`${window.location.href} closing with error msg`);
window.close();
};
function clearFlowControl() {
flowControl = {};
saveFlowControl();
};
function clearRetries() {
loadFlowControl();
flowControl.retrying = false;
saveFlowControl();
return false;
};
function isRetrying() {
if(flowControl.retrying) {
return true;
}
flowControl.retrying = true;
saveFlowControl();
return false;
};
initializeConfig();
return {
devlog: devlog,
getDevLog: getDevLog,
setFlowControl: setFlowControl,
wasVisited: wasVisited,
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
};
},
createManager: function() {
const STATUS = {
INITIALIZING: 0,
IDLE: 1,
CLAIMING: 2
};
let timestamp = null;
let timeWaiting = 0;
let uiUpdatesInterval;
let status = STATUS.INITIALIZING;
let processTimer;
let workingTab;
let webList = [];
let userWallet = [];
const sites = [
{ id: '1', name: 'CF ADA', cmc: '2010', coinRef: 'ADA', url: new URL('https://freecardano.com/free'), rf: '?ref=335463', type: WebType.CRYPTOSFAUCETS },
{ id: '2', name: 'CF BNB', cmc: '1839', coinRef: 'BNB', url: new URL('https://freebinancecoin.com/free'), rf: '?ref=161127', type: WebType.CRYPTOSFAUCETS },
{ id: '3', name: 'CF BTC', cmc: '1', coinRef: 'BTC', url: new URL('https://freebitcoin.io/free'), rf: '?ref=490252', type: WebType.CRYPTOSFAUCETS },
{ id: '4', name: 'CF DASH', cmc: '131', coinRef: 'DASH', url: new URL('https://freedash.io/free'), rf: '?ref=124083', type: WebType.CRYPTOSFAUCETS },
{ id: '5', name: 'CF ETH', cmc: '1027', coinRef: 'ETH', url: new URL('https://freeethereum.com/free'), rf: '?ref=204076', type: WebType.CRYPTOSFAUCETS },
{ id: '6', name: 'CF LINK', cmc: '1975', coinRef: 'LINK', url: new URL('https://freechainlink.io/free'), rf: '?ref=78652', type: WebType.CRYPTOSFAUCETS },
{ id: '7', name: 'CF LTC', cmc: '2', coinRef: 'LTC', url: new URL('https://free-ltc.com/free'), rf: '?ref=117042', type: WebType.CRYPTOSFAUCETS },
{ id: '8', name: 'CF NEO', cmc: '1376', coinRef: 'NEO', url: new URL('https://freeneo.io/free'), rf: '?ref=100529', type: WebType.CRYPTOSFAUCETS },
{ id: '9', name: 'CF STEAM', cmc: '1230', coinRef: 'STEEM', url: new URL('https://freesteam.io/free'), rf: '?ref=117686', type: WebType.CRYPTOSFAUCETS },
{ id: '10', name: 'CF TRX', cmc: '1958', coinRef: 'TRX', url: new URL('https://free-tron.com/free'), rf: '?ref=145047', type: WebType.CRYPTOSFAUCETS },
{ id: '11', name: 'CF USDC', cmc: '3408', coinRef: 'USDC', url: new URL('https://freeusdcoin.com/free'), rf: '?ref=100434', type: WebType.CRYPTOSFAUCETS },
{ id: '12', name: 'CF USDT', cmc: '825', coinRef: 'USDT', url: new URL('https://freetether.com/free'), rf: '?ref=181230', type: WebType.CRYPTOSFAUCETS },
{ id: '13', name: 'CF XEM', cmc: '873', coinRef: 'XEM', url: new URL('https://freenem.com/free'), rf: '?ref=295274', type: WebType.CRYPTOSFAUCETS },
{ id: '14', name: 'CF XRP', cmc: '52', coinRef: 'XRP', url: new URL('https://coinfaucet.io/free'), rf: '?ref=808298', type: WebType.CRYPTOSFAUCETS },
{ id: '15', name: 'StormGain', cmc: '1', url: new URL('https://app.stormgain.com/crypto-miner/'), rf: 'friend/BNS27140552', type: WebType.STORMGAIN },
{ id: '16', name: 'CF DOGE', cmc: '74', coinRef: 'DOGE', url: new URL('https://free-doge.com/free'), rf: '?ref=97166', type: WebType.CRYPTOSFAUCETS },
{ id: '17', name: 'FreeBitco.in', cmc: '1', url: new URL('https://freebitco.in/'), rf: '?r=41092365', type: WebType.FREEBITCOIN },
{ id: '18', name: 'FaucetPay PTC', cmc: '1', url: new URL('https://faucetpay.io/ptc'), rf: '?r=41092365', type: WebType.FAUCETPAY },
{ id: '19', name: 'Free-Litecoin.com', cmc: '2', url: new URL('https://free-litecoin.com/'), rf: 'login?referer=1332950', type: WebType.FREELITECOIN },
{ id: '20', name: 'Free-Ethereum.io', cmc: '1027', url: new URL('https://www.free-ethereum.io/'), rf: '?referer=1064662', type: WebType.FREEETHEREUMIO },
{ id: '21', name: 'Bagi BTC', cmc: '1', wallet: WalletType.FP_BTC, url: new URL('https://bagi.co.in/bitcoin/'), rf: ['?ref=53706', '?ref=63428', '?ref=54350'], type: WebType.BAGIKERAN },
{ id: '22', name: 'Bagi BNB', cmc: '1839', wallet: WalletType.FP_BNB, url: new URL('https://bagi.co.in/binance/'), rf: ['?ref=12529', '?ref=23852', '?ref=13847'], type: WebType.BAGIKERAN },
{ id: '23', name: 'Bagi BCH', cmc: '1831', wallet: WalletType.FP_BCH, url: new URL('https://bagi.co.in/bitcoincash/'), rf: ['?ref=44242', '?ref=50185', '?ref=41957'], type: WebType.BAGIKERAN },
{ id: '24', name: 'Bagi DASH', cmc: '131', wallet: WalletType.FP_DASH, url: new URL('https://bagi.co.in/dash/'), rf: ['?ref=32724', '?ref=38540', '?ref=40441'], type: WebType.BAGIKERAN },
{ id: '25', name: 'Bagi DGB', cmc: '109', wallet: WalletType.FP_DGB, url: new URL('https://bagi.co.in/digibyte/'), rf: ['?ref=22664', '?ref=27872', '?ref=29669'], type: WebType.BAGIKERAN },
{ id: '26', name: 'Bagi DOGE', cmc: '74', wallet: WalletType.FP_DOGE, url: new URL('https://bagi.co.in/dogecoin/'), rf: ['?ref=45047', '?ref=54217', '?ref=45568'], type: WebType.BAGIKERAN },
{ id: '27', name: 'Bagi ETH', cmc: '1027', wallet: WalletType.FP_ETH, url: new URL('https://bagi.co.in/ethereum/'), rf: ['?ref=24486', '?ref=27799', '?ref=24847'], type: WebType.BAGIKERAN },
{ id: '28', name: 'Bagi FEY', cmc: '10361', wallet: WalletType.FP_FEY, url: new URL('https://bagi.co.in/feyorra/'), rf: ['?ref=5049', '?ref=7433', '?ref=5318'], type: WebType.BAGIKERAN },
{ id: '29', name: 'Bagi LTC', cmc: '2', wallet: WalletType.FP_LTC, url: new URL('https://bagi.co.in/litecoin/'), rf: ['?ref=48335', '?ref=57196', '?ref=48878'], type: WebType.BAGIKERAN },
{ id: '30', name: 'Bagi TRX', cmc: '1958', wallet: WalletType.FP_TRX, url: new URL('https://bagi.co.in/tron/'), rf: ['?ref=22622', '?ref=31272', '?ref=23075'], type: WebType.BAGIKERAN },
{ id: '31', name: 'Bagi USDT', cmc: '825', wallet: WalletType.FP_USDT, url: new URL('https://bagi.co.in/tether/'), rf: ['?ref=25462', '?ref=32491', '?ref=25981'], type: WebType.BAGIKERAN },
{ id: '32', name: 'Bagi ZEC', cmc: '1437', wallet: WalletType.FP_ZEC, url: new URL('https://bagi.co.in/zcash/'), rf: ['?ref=9181', '?ref=15120', '?ref=9878'], type: WebType.BAGIKERAN },
{ id: '33', name: 'Keran BTC', cmc: '1', wallet: WalletType.FP_BTC, url: new URL('https://keran.co/BTC/'), rf: ['?ref=73729', '?ref=92353', '?ref=79321'], type: WebType.BAGIKERAN },
{ id: '34', name: 'Keran BNB', cmc: '1839', wallet: WalletType.FP_BNB, url: new URL('https://keran.co/BNB/'), rf: ['?ref=19287', '?ref=31242', '?ref=20659'], type: WebType.BAGIKERAN },
{ id: '35', name: 'Keran BCH', cmc: '1831', wallet: WalletType.FP_BCH, url: new URL('https://keran.co/BCH/'), rf: ['?ref=58232', '?ref=67326', '?ref=70759'], type: WebType.BAGIKERAN },
{ id: '36', name: 'Keran DASH', cmc: '131', wallet: WalletType.FP_DASH, url: new URL('https://keran.co/DASH/'), rf: ['?ref=45229', '?ref=53041', '?ref=55716'], type: WebType.BAGIKERAN },
{ id: '37', name: 'Keran DGB', cmc: '109', wallet: WalletType.FP_DGB, url: new URL('https://keran.co/DGB/'), rf: ['?ref=32788', '?ref=39527', '?ref=42014'], type: WebType.BAGIKERAN },
{ id: '38', name: 'Keran DOGE', cmc: '74', wallet: WalletType.FP_DOGE, url: new URL('https://keran.co/DOGE/'), rf: ['?ref=73512', '?ref=85779', '?ref=89613'], type: WebType.BAGIKERAN },
{ id: '39', name: 'Keran ETH', cmc: '1027', wallet: WalletType.FP_ETH, url: new URL('https://keran.co/ETH/'), rf: ['?ref=32226', '?ref=36427', '?ref=32676'], type: WebType.BAGIKERAN },
{ id: '40', name: 'Keran FEY', cmc: '10361', wallet: WalletType.FP_FEY, url: new URL('https://keran.co/FEY/'), rf: ['?ref=6269', '?ref=9019', '?ref=6569'], type: WebType.BAGIKERAN },
{ id: '41', name: 'Keran LTC', cmc: '2', wallet: WalletType.FP_LTC, url: new URL('https://keran.co/LTC/'), rf: ['?ref=69102', '?ref=80726', '?ref=84722'], type: WebType.BAGIKERAN },
{ id: '42', name: 'Keran TRX', cmc: '1958', wallet: WalletType.FP_TRX, url: new URL('https://keran.co/TRX/'), rf: ['?ref=49686', '?ref=46544', '?ref=34485'], type: WebType.BAGIKERAN },
{ id: '43', name: 'Keran USDT', cmc: '825', wallet: WalletType.FP_USDT, url: new URL('https://keran.co/USDT/'), rf: ['?ref=40582', '?ref=48907', '?ref=41009'], type: WebType.BAGIKERAN },
{ id: '44', name: 'Keran ZEC', cmc: '1437', wallet: WalletType.FP_ZEC, url: new URL('https://keran.co/ZEC/'), rf: ['?ref=', '?ref=18976', '?ref=12487'], type: WebType.BAGIKERAN },
{ id: '45', name: 'OK Btc', cmc: '1', wallet: WalletType.FP_BTC, url: new URL('https://btc-ok.net/'), rf: 'index.php?r=1QCD6cWJNVH4Cdnz85SQ2qtTkAwGr9fvUk', type: WebType.OKFAUCET },
{ id: '46', name: 'OK Dash', cmc: '131', wallet: WalletType.FP_DASH, url: new URL('https://dash-ok.net/'), rf: 'index.php?r=Xbyi7Fk2NRmZ32SHpDhmpGHLa4NMokhmGR', type: WebType.OKFAUCET },
{ id: '47', name: 'OK Dgb', cmc: '109', wallet: WalletType.FP_DGB, url: new URL('https://dgb-ok.net/'), rf: 'index.php?r=DSM93hgZuapnjeeDMe8spzwG9rMrw4sdua', type: WebType.OKFAUCET },
{ id: '48', name: 'OK Doge', cmc: '74', wallet: WalletType.FP_DOGE, url: new URL('https://doge-ok.net/'), rf: 'index.php?r=DDaQWmD7vY1NhtK1M5Pno7sdccmgxNUfv1', type: WebType.OKFAUCET },
{ id: '49', name: 'OK Eth', cmc: '1027', wallet: WalletType.FP_ETH, url: new URL('https://eth-ok.net/'), rf: 'index.php?r=0x7636f64a8241257b1edaf65ae943c66de87b1749', type: WebType.OKFAUCET },
{ id: '50', name: 'OK Ltc', cmc: '2', wallet: WalletType.FP_LTC, url: new URL('https://ltc-ok.net/'), rf: 'index.php?r=MEmxLqYzZdMsEswUQkqL5aawT5UsqYwYgr', type: WebType.OKFAUCET },
{ id: '51', name: 'OK Trx', cmc: '1958', wallet: WalletType.FP_TRX, url: new URL('https://trx-ok.net/'), rf: 'index.php?r=TSocuzJ6ADUoQ49v28BXN2jo3By6awwHvj', type: WebType.OKFAUCET },
{ id: '52', name: 'BigBtc', cmc: '1', wallet: WalletType.FP_BTC, url: new URL('https://bigbtc.win/'), rf: '?id=39255652', type: WebType.BIGBTC }
];
const wallet = [
{ id: '101', name: 'FaucetPay BTC (Bitcoin)', type: WalletType.FP_BTC },
{ id: '102', name: 'FaucetPay BNB (Binance Coin)', type: WalletType.FP_BNB },
{ id: '103', name: 'FaucetPay BCH (Bitcoin Cash)', type: WalletType.FP_BCH },
{ id: '104', name: 'FaucetPay DASH (Dash)', type: WalletType.FP_DASH },
{ id: '105', name: 'FaucetPay DGB (DigiByte)', type: WalletType.FP_DGB },
{ id: '106', name: 'FaucetPay DOGE (Dogecoin)', type: WalletType.FP_DOGE },
{ id: '107', name: 'FaucetPay ETH (Ethereum)', type: WalletType.FP_ETH },
{ id: '108', name: 'FaucetPay FEY (Feyorra)', type: WalletType.FP_FEY },
{ id: '109', name: 'FaucetPay LTC (Litecoin)', type: WalletType.FP_LTC },
{ id: '110', name: 'FaucetPay TRX (Tron)', type: WalletType.FP_TRX },
{ id: '111', name: 'FaucetPay USDT (Tether TRC20)', type: WalletType.FP_USDT },
{ id: '112', name: 'FaucetPay ZEC (Zcash)', type: WalletType.FP_ZEC }
];
function start() {
loader.initialize();
ui.init(getCFlist());
update();
ui.refresh(null, null, userWallet);
uiUpdatesInterval = setInterval(readUpdateValues, 10000);
processTimer = setTimeout(manager.process, 2000);
};
let loader = function() {
function initialize() {
setTimestamp();
initializeWebList();
initializeUserWallet();
initializePromotions();
initializeHistory();
};
function initializeWebList() {
addSites();
addStoredSitesData();
};
function addSites() {
sites.forEach(x => webList.push(x));
webList.forEach(function (element, idx, arr) {
arr[idx].enabled = false;
arr[idx].lastClaim = 0;
arr[idx].aggregate = 0;
arr[idx].balance = 0;
arr[idx].stats = {};
arr[idx].nextRoll = null;
arr[idx].workInBackground = (element.id == '18' ? false : USE_DEFAULT);
// UNCOMMENT THE FOLLOWING LINE TO RUN STORMGAIN WITH FOCUS INSTEAD OF BACKGROUND IF YOU ARE HAVING TROUBLE WITH IT'S ACTIVATION
// arr[idx].workInBackground = ((element.id == '15' || element.id == '18') ? false : USE_DEFAULT);
if(arr[idx].type == WebType.BAGIKERAN) {
arr[idx].lastWithdraw = new Date();
}
});
};
function addStoredSitesData() {
let storedData = persistence.load('webList', true);
if(storedData) {
storedData.forEach( function (element) {
let idx = webList.findIndex(x => x.id == element.id);
if(idx != -1) {
webList[idx].name = element.name ?? webList[idx].name;
webList[idx].lastClaim = element.lastClaim ?? webList[idx].lastClaim;
webList[idx].aggregate = element.aggregate ?? webList[idx].aggregate;
webList[idx].balance = element.balance ?? webList[idx].balance;
webList[idx].stats = element.stats ?? webList[idx].stats;
webList[idx].enabled = element.enabled ?? webList[idx].enabled;
if(!webList[idx].enabled) {
webList[idx].nextRoll = null;
} else {
webList[idx].nextRoll = element.nextRoll ? new Date(element.nextRoll) : new Date();
}
if(element.lastWithdraw) {
webList[idx].lastWithdraw = new Date(element.lastWithdraw);
}
//webList[idx].workInBackground = element.workInBackground ?? webList[idx].workInBackground;
}
});
} else {
// webList.shuffle();
}
};
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 ?? webList[idx].address;
}
});
}
};
function initializePromotions() {
let storedData = persistence.load('CFPromotions', true);
if (storedData) {
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;
});
});
CFPromotions.load(storedData);
}
};
function initializeHistory() {
CFHistory.initOrLoad();
};
function setTimestamp() {
timestamp = Date.now();
persistence.save('timestamp', timestamp);
};
function removeDisabledFaucets() {
webList = webList.filter(x => x.enabled);
};
return {
initialize: initialize
};
}();
function readUpdateValues(forceCheck = false) {
readPromoCodeValues();
readModalData();
if(status == STATUS.IDLE || forceCheck) {
let updateDataElement = document.getElementById('update-data');
let updateValues = updateDataElement.innerText.clean();
if (updateValues != '') {
updateDataElement.innerText = '';
let updateObj = JSON.parse(updateValues);
if(updateObj.runAsap.changed) {
updateObj.runAsap.ids.forEach(function (element, idx, arr) {
try {
let itemIndex = webList.findIndex(x => x.id == element)
webList[itemIndex].enabled = true;
webList[itemIndex].nextRoll = new Date(754000 + idx);
ui.log(`${webList[itemIndex].name} updated to run ASAP`);
} catch (err) {
ui.log(`Error setting faucet to run ASAP: ${err}`);
}
});
}
if(updateObj.editSingle.changed) {
updateObj.editSingle.items.forEach(function (element, idx, arr) {
try {
let itemIndex = webList.findIndex(x => x.id == element.id);
webList[itemIndex].name = element.displayName;
if (webList[itemIndex].enabled != element.enabled) {
webList[itemIndex].enabled = element.enabled;
if(webList[itemIndex].enabled) {
webList[itemIndex].nextRoll = new Date(idx);
} else {
webList[itemIndex].nextRoll = null;
}
}
ui.log(`Faucet updated. New name: ${element.displayName}. Active: ${element.enabled}`);
} catch (err) {
ui.log(`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(`Wallet Address updated [${userWallet[itemIndex].name}]: ${userWallet[itemIndex].address}`);
} catch (err) {
ui.log(`Error updating wallet/address: ${err}`);
}
});
document.getElementById('faucets-display-status').innerHTML = '';
ui.refresh(null, null, userWallet);
saveUserWallet();
}
if(updateObj.config.changed) {
try {
shared.updateConfig(updateObj.config.items);
ui.log(`Config updated. Reloading in a few seconds...`);
window.location.reload();
return;
} catch (err) {
ui.log(`Error updating config: ${err}`);
}
document.getElementById('faucets-display-status').innerHTML = '';
}
if(updateObj.runAsap.changed || updateObj.editSingle.changed) {
document.getElementById('faucets-display-status').innerHTML = '';
update(true);
process();
return;
}
}
}
if(forceCheck) {
process();
}
};
function readModalData() {
if(document.getElementById('modal-spinner').isVisible()) {
let target = document.getElementById('target-spinner').innerHTML;
if (target == 'modal-ereport') {
let temp = shared.getDevLog();
document.getElementById('log-textarea').value = temp.join('\n');
} else if (target == 'modal-config') {
ui.refresh(null, null, null, shared.getConfig());
}
document.getElementById('modal-spinner').classList.toggle('d-none');
document.getElementById(target).classList.toggle('d-none'); //$('#' + target).toggleClass('d-none');
document.getElementById('target-spinner').innerHTML = '';
}
}
function update(sortIt = true) {
let updateRollStats = webList[0].type == WebType.CRYPTOSFAUCETS;
if(sortIt) {
webList.sort( function(a,b) {
if (a === b) {
return 0;
} else if (a.nextRoll === null) {
return 1;
} else if (b.nextRoll === null) {
return -1;
} else {
return a.nextRoll.getTime() < b.nextRoll.getTime() ? -1 : 1;
}
});
}
saveWebList();
ui.refresh(webList, CFPromotions.getAll());
if(updateRollStats) {
updateRollStatsSpan();
}
};
function saveWebList() {
const data = webList.map(function(x) {
let ret = {
id: x.id,
name: x.name,
lastClaim: x.lastClaim,
aggregate: x.aggregate,
balance: x.balance,
stats: x.stats,
nextRoll: x.nextRoll,
enabled: x.enabled
};
if (x.lastWithdraw) {
ret.lastWithdraw = x.lastWithdraw;
}
return ret;
});
persistence.save('webList', data, true);
}
function saveUserWallet() {
const data = userWallet.map(x => {
return {
id: x.id,
address: x.address
};});
persistence.save('userWallet', data, true);
}
function process() {
if(isObsolete()) {
return;
}
timer.stopCheck();
if(webList[0].nextRoll == null) {
ui.log(`All faucets are disabled. Click edit and select those you want to run...`);
clearTimeout(processTimer);
status = STATUS.IDLE;
return;
}
if(webList[0].nextRoll.getTime() < Date.now()) {
ui.log(`Opening ${webList[0].name}`);
clearTimeout(processTimer);
status = STATUS.CLAIMING;
open();
} else {
let timeUntilNext = webList[0].nextRoll.getTime() - Date.now() + helpers.randomMs(1000, 2000);
// PROCESSING AGAIN LAST 'FORCE CLOSED' IN CASE WE HAVE A WINDOW OF TIME (MORE THAN TIMEOUT/2):
if (timeUntilNext > (shared.getConfig()['defaults.timeout'] * 60 * 1000 / 2)) {
let idx = -1;
for (let i = webList.length - 1; i >= 0; i--) {
if (webList[i].enabled && webList[i].stats && webList[i].stats.errors && webList[i].stats.errors.errorType == ErrorType.FORCE_CLOSED) {
idx = i;
break;
}
}
if (idx > -1) {
webList[idx].nextRoll = new Date(-20);
update(true);
process();
return;
}
}
ui.log(`Waiting ${(timeUntilNext/1000/60).toFixed(2)} minutes...`);
clearTimeout(processTimer);
processTimer = setTimeout(manager.process, timeUntilNext);
status = STATUS.IDLE;
}
};
function isObsolete() {
let savedTimestamp = persistence.load('timestamp');
if (savedTimestamp && savedTimestamp > timestamp) {
ui.log('<b>STOPING EXECUTION!<b> A new Manager UI window was opened. Process should continue there');
clearInterval(uiUpdatesInterval);
return true;
}
return false;
};
function open(promoCode) {
let navUrl = webList[0].url;
try {
if(promoCode) {
navUrl = new URL('promotion/' + promoCode, webList[0].url.origin);
ui.log(`Opening ${webList[0].name} with Promo Code [${promoCode}]`);
}
if(Array.isArray(webList[0].rf)) {
navUrl = new URL(navUrl.href + webList[0].rf[helpers.randomInt(0, webList[0].rf.length - 1)]);
}
let params = {};
if (webList[0].wallet) {
//TODO: VALIDATE THAT ADDRESS EXISTS AND IS VALID!!!
try {
params.address = userWallet.find(x => x.type == webList[0].wallet).address;
} catch {
params.address = '123'; //not available @ wallet
}
}
if(webList[0].type == WebType.BAGIKERAN) {
params.doWithdraw = getDoWithdraw(webList[0].lastWithdraw);
params.doSignOut = (webList[0].wallet == WalletType.FP_BCH ? true : false);
params.trackUrl = webList[0].url;
}
shared.setFlowControl(webList[0].id, navUrl, webList[0].type, params);
setTimeout(manager.resultReader, 15000);
// Try to close old workingTab if still opened
if (workingTab && !workingTab.closed) {
try {
shared.devlog(`Tab closed from Manager`);
workingTab.close();
} catch {
shared.devlog(`ERROR: unable to close tab from Manager`);
}
} else {
shared.devlog(`No open tabs detected`);
}
timer.startCheck(webList[0].type);
workingTab = GM_openInTab(navUrl.href, { active: (webList[0].workInBackground == USE_DEFAULT ? !shared.getConfig()['defaults.workInBackground'] : !webList[0].workInBackground) });
} catch(err) {
ui.log(`Error opening tab: ${err}`)
}
};
function getDoWithdraw(lastWithdraw) {
switch (shared.getConfig()['bk.withdrawMode']) {
case "0":
return false;
break;
case "2":
return true;
break;
case "1":
if(lastWithdraw == null) {
return true;
}
return (lastWithdraw && ( (Date.now() - lastWithdraw.getTime()) > helpers.hsToMs(shared.getConfig()['bk.hoursBetweenWithdraws'])));
break;
default:
return false;
}
return false;
}
// REFACTOR
function resultReader() {
if(isObsolete()) {
return;
}
if (webList[0].type == WebType.FAUCETPAY && workingTab && !workingTab.closed
&& timeWaiting < helpers.minToMs(shared.getConfig()['fp.maxTimeInMinutes'])) {
timeWaiting += 15;
ui.log(`Waiting for ${webList[0].name} results...`, timeWaiting);
setTimeout(manager.resultReader, 15000);
return;
}
if(shared.wasVisited(webList[0].id)) {
let result = shared.getResult();
if (result) {
updateWebListItem(result);
if ( (webList[0].type == WebType.CRYPTOSFAUCETS) &&
( (result.claimed) || (result.promoStatus && result.promoStatus != PromoStatus.ACCEPTED) )) {
let promoCode = CFPromotions.hasPromoAvailable(webList[0].id);
if (promoCode) {
timeWaiting = 0;
update(false);
open(promoCode);
return;
}
}
if ( webList[0].type == WebType.BAGIKERAN && shared.getCurrent().params.doWithdraw && !result.withdrawnAmount) {
if(!result.withdrawing) {
shared.updateWithoutClosing({ withdrawing: true });
update(false);
timeWaiting = 0;
}
if (hasTimedOut()) {
if(webList[0].stats.countTimeouts) {
webList[0].stats.countTimeouts += 1;
} else {
webList[0].stats.countTimeouts = 1;
}
ui.log(`Waited too much time for ${webList[0].name} results: triggering timeout`);
moveNext();
return;
}
if (shared.hasErrors(webList[0].id)) {
webList[0].stats.errors = shared.getResult();
ui.log(`${webList[0].name} closed with error: ${helpers.getEnumText(ErrorType, webList[0].stats.errors.errorType)} ${webList[0].stats.errors.errorMessage}`);
if(sleepIfBan()) {
return;
}
moveNext();
return;
}
timeWaiting += 15;
ui.log(`Waiting for ${webList[0].name} withdraw...`, timeWaiting);
setTimeout(manager.resultReader, 15000);
return;
}
} else {
ui.log(`Unable to read last run result, for ID: ${webList[0].id} > ${webList[0].name}`);
}
timeWaiting = 0;
update(true);
readUpdateValues(true);
return;
} else {
timeWaiting += 15;
if (!shared.hasErrors(webList[0].id) && !hasTimedOut()) {
ui.log(`Waiting for ${webList[0].name} results...`, timeWaiting);
setTimeout(manager.resultReader, 15000);
return;
}
if (shared.hasErrors(webList[0].id)) {
webList[0].stats.errors = shared.getResult();
ui.log(`${webList[0].name} closed with error: ${helpers.getEnumText(ErrorType,webList[0].stats.errors.errorType)} ${webList[0].stats.errors.errorMessage}`);
if(sleepIfBan()) {
return;
}
}
if (hasTimedOut()) {
if(webList[0].stats.countTimeouts) {
webList[0].stats.countTimeouts += 1;
} else {
webList[0].stats.countTimeouts = 1;
}
ui.log(`Waited too much time for ${webList[0].name} results: triggering timeout`);
}
moveNext();
return;
}
};
function sleepIfBan() {
if( (webList[0].stats.errors.errorType == ErrorType.IP_BAN && shared.getConfig()['cf.sleepHoursIfIpBan'] > 0)
|| ( webList[0].stats.errors.errorType == ErrorType.IP_RESTRICTED && shared.getConfig()['bk.sleepMinutesIfIpBan'] > 0) ) {
if(webList[0].type == WebType.CRYPTOSFAUCETS) {
webList.filter(x => x.enabled && x.type == WebType.CRYPTOSFAUCETS)
.forEach( function(el) {
el.nextRoll = new Date(helpers.addMs(el.nextRoll, helpers.getRandomMs(shared.getConfig()['cf.sleepHoursIfIpBan'] * 60, 2)));
});
}
if(webList[0].type == WebType.BAGIKERAN) {
webList.filter(x => x.enabled && x.type == WebType.BAGIKERAN && x.url.host == webList[0].url.host)
.forEach( function(el) {
el.nextRoll = new Date(helpers.addMs(el.nextRoll, helpers.getRandomMs(shared.getConfig()['bk.sleepMinutesIfIpBan'], 2)));
});
}
shared.clearFlowControl();
update(true);
timeWaiting = 0;
readUpdateValues(true);
return true;
}
return false;
}
function moveNext() {
let millisecondsDelay = helpers.getRandomMs(shared.getConfig()['defaults.postponeMinutes'], 5);
webList[0].nextRoll = new Date(helpers.addMs(new Date(), millisecondsDelay));
shared.clearFlowControl();
update(true);
timeWaiting = 0;
readUpdateValues(true);
}
function hasTimedOut() {
return shared.getConfig()['defaults.timeout'] != -1 && (timeWaiting > (shared.getConfig()['defaults.timeout'] * 60));
};
function updateWebListItem(result) {
if (result.withdrawing) {
return;
}
ui.log(`Updating data: ${JSON.stringify(result)}`);
webList[0].stats.countTimeouts = 0;
webList[0].stats.errors = null;
if (result.withdrawnAmount && result.withdrawnAmount > 0) {
webList[0].lastWithdraw = new Date();
webList[0].balance += result.withdrawnAmount;
webList[0].lastClaim = 0;
webList[0].aggregate = 0;
return;
}
if (result.claimed) {
try {
result.claimed = parseFloat(result.claimed);
} catch { }
if(!isNaN(result.claimed)) {
webList[0].lastClaim = result.claimed;
webList[0].aggregate += result.claimed;
// if (!result.balance) {
// webList[0].balance = webList[0].aggregate;
// }
}
}
if(result.balance) {
webList[0].balance = result.balance;
}
if(result.nextRoll) {
webList[0].nextRoll = new Date(result.nextRoll);
}
if(result.promoStatus) {
CFPromotions.updateFaucetForCode(result.promoCode, webList[0].id, result.promoStatus);
}
if(result.rolledNumber) {
CFHistory.addRoll(result.rolledNumber);
}
};
function readPromoCodeValues() {
let promoCodeElement = document.getElementById('promo-code-new');
let promoDataStr = promoCodeElement.innerText.clean();
let promoDisplayStatus = document.getElementById('promo-display-status');
if (promoDataStr == '') {
promoDisplayStatus.innerHTML = '';
return;
}
let promoData = JSON.parse(promoDataStr);
if(promoData.action) {
switch (promoData.action) {
case 'ADD':
CFPromotions.addNew(promoData.code, promoData.repeatDaily);
promoCodeElement.innerText = '';
document.getElementById('promo-text-input').value = '';
promoDisplayStatus.innerHTML = 'Code ' + promoData.code + ' added!';
ui.log(`Promo code ${promoData.code} added`);
ui.refresh(null, CFPromotions.getAll());
break;
case 'REMOVEALLPROMOS':
CFPromotions.removeAll();
promoCodeElement.innerText = '';
promoDisplayStatus.innerHTML = 'Promo codes removed!';
ui.log(`Promo codes removed`);
ui.refresh(null, CFPromotions.getAll());
break;
case 'REMOVE':
if(CFPromotions.remove(promoData.id, promoData.code) != -1) {
ui.log(`Promo code ${promoData.code} removed`);
} else {
ui.log(`Unable to remove code ${promoData.code}`);
}
promoCodeElement.innerText = '';
ui.refresh(null, CFPromotions.getAll());
break;
}
}
};
function updateRollStatsSpan() {
let rollsSpanElement = document.getElementById('rolls-span');
rollsSpanElement.innerText = CFHistory.getRollsMeta().join(',');
};
function getCFlist() {
let items;
items = webList.filter(f => f.type === 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() {
workingTab.close();
};
return{
init:start,
process: process,
resultReader: resultReader,
getFaucetsForPromotion: getCFlist,
readPromoCodeValues: readPromoCodeValues,
closeWorkingTab: closeWorkingTab
};
},
createUi: function() {
let logLines = ['', '', '', '', ''];
function init(cfFaucets) {
appendCSS();
appendJavaScript();
appendHtml();
createPromoTable(cfFaucets);
document.querySelector('.page-title h1').innerHTML = 'Auto Claim';
};
function appendCSS() {
let css = document.createElement('style');
css.innerHTML = `
td.em-input {
padding-top: 0;
padding-bottom: 0;
}
`;
document.head.appendChild(css);
};
function appendJavaScript() {
// let js = document.createElement('script');
// js.setAttribute('language', 'text/javascript');
let js = '<script language="text/javascript">'
js += 'var myBarChart;';
js += 'function sendErrorReport() {';
js += ' try {';
js += ' let header = new Headers();';
js += ' header.append("Content-Type", "application/json");';
js += ' let description = document.getElementById("log-message").value;';
js += ' let log = document.getElementById("log-textarea").value.split(\'\\n\');';
js += ' let content = {"description":description, "log":log};';
js += ' let opt = { method: "POST", header, mode: "cors", body: JSON.stringify(content) };';
js += ' fetch("https://1d0103ec5a621b87ea27ffed3c072796.m.pipedream.net", opt).then(response => {';
js += ' console.log(response);';
js += ' }).catch(err => {';
js += ' console.error("[error] " + err.message);';
js += ' });';
js += ' } catch { }';
js += '}';
js += 'function loadDlg(id) {';
js += ' $(".modal-content").addClass("d-none");';
js += ' if (id == "modal-ereport" || id == "modal-config") {';
js += ' document.getElementById("target-spinner").innerHTML = id;';
js += ' $(document.getElementById("modal-spinner")).removeClass("d-none");';
js += ' return;';
js += ' } else {';
js += ' $(document.getElementById(id)).removeClass("d-none");';
js += ' }';
js += '}';
js += 'function savePromoCode() {';
js += 'var promoText = document.getElementById("promo-text-input");';
js += 'var promoCode = document.getElementById("promo-code-new");';
js += 'var promoDisplayStatus = document.getElementById("promo-display-status");';
js += 'var promoDaily = document.getElementById("promo-daily");';
js += 'var promoObject = { action: "ADD", code: promoText.value.trim(), repeatDaily: promoDaily.checked };'
js += 'promoCode.innerHTML =JSON.stringify(promoObject);';
js += 'promoDisplayStatus.innerHTML = "Adding  "<b>" + promoObject.code + "</b>"...<br>This could take around a minute. Please wait..."';
js += '}';
js += 'function removePromoCode(id, code) {';
js += 'var promoCode = document.getElementById("promo-code-new");';
js += 'var promoDisplayStatus = document.getElementById("promo-display-status");';
js += 'var promoObject = { action: "REMOVE", id: id, code: code };'
js += 'promoCode.innerHTML =JSON.stringify(promoObject);';
js += 'promoDisplayStatus.innerHTML = "Removing code  "<b>" + code + "</b>"...<br>This could take around a minute. Please wait..."';
js += '}';
js += 'function getUpdateObject() {';
js += 'let updateObject;';
js += 'var updateData = document.getElementById("update-data");';
js += 'if (updateData.innerHTML != "") {';
js += 'updateObject = JSON.parse(updateData.innerHTML);';
js += '} else {';
js += 'updateObject = { runAsap: { ids: [], changed: false}, editSingle: { changed: false, items: [] }, wallet: { changed: false, items: []}, config: { changed: false, items: []} };';
js += '}';
js += 'return updateObject;';
js += '}';
js += 'function editList() {';
js += '$.each($("#schedule-table-body td.em-input"), function(x, y) {';
js += 'let val = y.innerHTML;';
js += 'y.innerHTML = "<input type=\'text\' data-original=\'" + val + "\' value=\'" + val + "\' />";});';
js += '$.each($("#schedule-table-body td.edit-status"), function(x, y) {';
js += 'let activeSwitch = y.querySelector("input");';
js += 'y.classList.remove("d-none");';
js += '});';
js += '$.each($(".em-only"), (x, y) => y.classList.remove("d-none"));';
js += '$.each($(".em-hide"), (x, y) => y.classList.add("d-none"));';
js += '}';
js += 'function editListSave() {';
js += ' let updateObject = getUpdateObject();';
js += ' $.each($("#schedule-table-body tr"), function(x, row) {';
js += ' let textInputCell = row.querySelector(".em-input");';
js += ' let textInput = textInputCell.querySelector("input");';
js += ' let activeSwitch = row.querySelector("td.edit-status input");';
js += ' let single = { id: row.dataset.id, displayName: textInput.dataset.original, enabled: activeSwitch.dataset.original };';
js += ' textInputCell.innerHTML = textInput.value;';
js += ' if(textInput.dataset.original != textInput.value) {';
js += ' single.displayName = textInput.value;';
js += ' }';
js += ' if(activeSwitch.dataset.original != Boolean(activeSwitch.checked)) {';
js += ' single.enabled = Boolean(activeSwitch.checked);';
js += ' }';
js += ' if(textInput.dataset.original != textInput.value || activeSwitch.dataset.original != Boolean(activeSwitch.checked)) {';
js += ' updateObject.editSingle.items.push(single);';
js += ' updateObject.editSingle.changed = true;';
js += ' }';
js += ' });';
js += ' if(updateObject.editSingle.changed) {';
js += ' document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);';
js += ' document.getElementById("faucets-display-status").innerHTML = "Data will be updated as soon as possible...";';
js += ' }';
js += '$.each($(".em-only"), (x, y) => y.classList.add("d-none"));';
js += '$.each($(".em-hide"), (x, y) => y.classList.remove("d-none"));';
js += '}';
js += 'function editListCancel() {';
js += '$.each($("#schedule-table-body td.em-input input"), function(x, y) {';
js += 'let val = y.dataset.original;';
js += 'y.parentNode.innerHTML = val;});';
js += '$.each($(".em-only"), (x, y) => y.classList.add("d-none"));';
js += '$.each($(".em-hide"), (x, y) => y.classList.remove("d-none"));';
js += '}';
js += 'let editWallet = {';
js += ' save: function() {';
js += ' let updateObject = getUpdateObject();';
js += ' $.each($("#wallet-table-body tr"), function(x, row) {';
js += ' let textInput = row.querySelector(".em-input input");';
js += ' if(textInput.dataset.original != textInput.value) {';
js += ' let single = { id: row.dataset.id, address: textInput.value.trim() };';
js += ' updateObject.wallet.items.push(single);';
js += ' updateObject.wallet.changed = true;';
js += ' }';
js += ' });';
js += ' if(updateObject.wallet.changed) {';
js += ' document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);';
js += ' document.getElementById("faucets-display-status").innerHTML = "Wallet will be updated as soon as possible...";';
js += ' }';
js += ' },';
js += ' cancel: function() {';
js += ' $.each($("#wallet-table-body .em-input input"), function(x, y) {';
js += ' y.value = y.dataset.original;});';
js += ' }';
js += '};';
js += 'let editConfig = {';
js += ' save: function() {';
js += ' let updateObject = getUpdateObject();';
js += ' document.querySelectorAll("#modal-config [data-original][data-prop]").forEach(function(elm) {';
js += ' let single = { prop: elm.dataset.prop, value: elm.dataset.value };';
js += ' if(elm.dataset.original != elm.value && (elm.type == "select-one" || elm.type == "text" || elm.type == "password") ) { ';
js += ' single.value = elm.value;';
js += ' updateObject.config.items.push(single);';
js += ' updateObject.config.changed = true;';
js += ' } else if (elm.type == "checkbox" && ((elm.dataset.original == "0" && elm.checked) || (elm.dataset.original == "1" && !elm.checked)) ) {';
js += ' single.value = elm.checked;';
js += ' updateObject.config.items.push(single);';
js += ' updateObject.config.changed = true;';
js += ' }';
js += ' });';
js += ' if(updateObject.config.changed) {';
js += ' document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);';
js += ' document.getElementById("faucets-display-status").innerHTML = "Config will be updated as soon as possible...";';
js += ' }';
js += ' },';
js += ' cancel: function() {';
js += ' document.querySelectorAll("#modal-config [data-original][data-prop]").forEach(function(elm) {';
js += ' if(elm.type == "select-one" || elm.type == "text" || elm.type == "password") { ';
js += ' elm.value = elm.dataset.original;';
js += ' } else if (elm.type == "checkbox") {';
js += ' elm.checked = (elm.dataset.original == "1" ? true : false)';
js += ' }';
js += ' });';
js += ' }';
js += '};';
js += 'let editEreport = {';
js += ' save: function() {';
js += ' sendErrorReport();';
js += ' },';
js += ' cancel: function() {';
js += ' }';
js += '};';
js += 'function modalSave(content) {';
js += ' if(content == "wallet") {';
js += ' editWallet.save();';
js += ' } else if (content == "ereport") {';
js += ' editEreport.save();';
js += ' } else if (content == "config") {';
js += ' editConfig.save();';
js += ' }';
js += '}';
js += 'function modalCancel(content) {';
js += ' if(content == "wallet") {';
js += ' editWallet.cancel();';
js += ' } else if ("ereport") {';
js += ' editEreport.cancel();';
js += ' }';
js += ' $("modal-content").addClass("d-none")';
js += '}';
js += 'function updateValues(type, values) {';
js += ' let updateObject = getUpdateObject();';
js += ' if (type == "runAsap") {';
js += ' updateObject.runAsap.ids.push(values.id);';
js += ' updateObject.runAsap.changed = true;';
js += ' document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);';
js += ' document.getElementById("faucets-display-status").innerHTML = "Faucet will be updated to run as soon as possible...";';
js += ' }';
js += '}';
js += 'function removeAllPromos() {';
js += 'var promoCode = document.getElementById("promo-code-new");';
js += 'var promoDisplayStatus = document.getElementById("promo-display-status");';
js += 'var promoObject = { action: "REMOVEALL" };'
js += 'promoCode.innerHTML =JSON.stringify(promoObject);';
js += 'promoDisplayStatus.innerHTML = "Removing all promotion codes...<br>This could take around a minute. Please wait..."';
js += '}';
js += 'function openStatsChart() {';
js += 'if(myBarChart) { myBarChart.destroy(); }';
js += 'let statsFragment = document.getElementById("stats-fragment");';
js += 'if (statsFragment.style.display === "block") { statsFragment.style.display = "none"; document.getElementById("stats-button").innerText = "Lucky Number Stats"; } else {';
js += 'statsFragment.style.display = "block"; document.getElementById("stats-button").innerText = "Close Stats";';
js += 'var canvas = document.getElementById("barChart");';
js += 'var ctx = canvas.getContext("2d");';
js += 'var dataSpan = document.getElementById("rolls-span");';
js += 'var data = {';
js += 'labels: ["0000-9885", "9886-9985", "9986-9993", "9994-9997", "9998-9999", "10000"],';
js += 'datasets: [ { fill: false, backgroundColor: [ "#990000", "#660066", "#000099", "#ff8000", "#ffff00", "#00ff00"],';
js += 'data: dataSpan.innerText.split(",") } ] };';
js += 'var options = { plugins: { legend: { display: false } }, title: { display: true, text: "Rolled Numbers", position: "top" }, rotation: -0.3 * Math.PI };';
js += 'myBarChart = new Chart(ctx, { type: "pie", data: data, options: options }); } }';
js += '</script>'
// document.head.appendChild(js);
$('head').append(js);
};
function appendHtml() {
let html ='';
html += '<div class="fixed-bottom" style="display: table;line-height: 42px;padding: 5px 30px;font-weight: 700;font-size: 17px;">';
if (shared.getConfig()['devlog.enabled']) {
html += '<div><a class="btn m-2 anchor btn-outline-primary align-middle" data-toggle="modal" data-target="#modal-dlg" onclick="loadDlg(\'modal-ereport\')"><i class="fa fa-bug"></i> Send Log</a></div>';
}
html += '<div><a class="btn m-2 anchor btn-outline-primary align-middle" data-toggle="modal" data-target="#modal-dlg" onclick="loadDlg(\'modal-config\')"><i class="fa fa-cog"></i> Edit Config</a></div>';
html += '</div>';
html += '<div class="modal fade" id="modal-dlg" tabindex="-1" role="dialog" data-backdrop="static" aria-hidden="true">';
html += ' <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable" role="document">';
// MODAL CONTENTS
//[Loading]
html += '<div class="modal-content bg-beige" id="modal-spinner"><div class="modal-body"><div class="d-flex justify-content-center"><span id="target-spinner" class="d-none"></span><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>Loading data</div></div></div>';
//Error report
html += ' <div class="modal-content bg-beige d-none" id="modal-ereport">';
html += ' <div class="modal-header"><h5 class="modal-title">Submit an Error</h5></div>';
html += ' <div class="modal-body">';
html += ' <div class="alert alert-danger">Don\'t send private information as data might be publicly access.</div>';
html += ' <textarea rows="4" id="log-message" class="form-control" placeholder="Please describe the error..."></textarea>';
html += ' <label for="log-textarea">Log</label>';
html += ' <textarea rows="10" id="log-textarea" class="form-control"></textarea>';
html += ' </div>';
html += ' <div class="modal-footer"><a class="btn m-2 anchor btn-outline-danger align-middle" onclick="modalCancel(\'ereport\')" data-dismiss="modal"><i class="fa fa-times-circle"></i> Cancel</a>';
html += ' <a class="btn m-2 anchor btn-outline-success align-middle" onclick="modalSave(\'ereport\')" data-dismiss="modal"><i class="fa fa-paper-plane"></i> Send</a></div>';
html += ' </div>';
//Wallet
html += ' <div class="modal-content bg-beige d-none" id="modal-wallet">';
html += ' <div class="modal-header"><h5 class="modal-title">Your Addresses</h5></div>';
html += ' <div class="modal-body">';
html += ' <div><table class="table table-striped" id="wallet-table">';
html += ' <thead><tr><th class="">Name</th><th class="">Address</th></tr></thead>';
html += ' <tbody class="overflow-auto" id="wallet-table-body"></tbody></table>';
html += ' </div>';
html += ' </div>';
html += '<div class="modal-footer"><a class="btn m-2 anchor btn-outline-danger align-middle" onclick="modalCancel(\'wallet\')" data-dismiss="modal"><i class="fa fa-times-circle"></i> Cancel</a>';
html += '<a class="btn m-2 anchor btn-outline-success align-middle" onclick="modalSave(\'wallet\')" data-dismiss="modal"><i class="fa fa-check-circle"></i> Save</a></div>';
html += ' </div>';
//Config
html += '<div class="modal-content bg-beige d-none" id="modal-config">';
html += ' <div class="modal-header"><h5 class="modal-title">Edit Configuration</h5></div>';
html += ' <div class="modal-body">';
html += ' <div class="alert alert-danger alert-dismissible fade show">This form does not upload data. Values are added to a span, then read by the script and locally stored by Tampermonkey using GM_setValue.<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button></div>';
html += ' <div class="alert alert-danger alert-dismissible fade show">Time values are estimated and will be randomly modified by +/-2% aprox.<br>The script will trigger a reload of the page after updating the data.<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button></div>';
html += ' <div class="row">';
html += ' <div class="col-md-6 col-sm-12">';
html += ' <div class="card m-1" data-level="defaults"><div class="card-body px-4">';
html += ' <h6>Defaults</h6>';
html += ' <div><label class="switch"><input type="checkbox" data-prop="defaults.workInBackground"><span class="slider round"></span></label> Open tabs in background</div>';
html += ' <label class="control-label">Timeout after:</label>';
html += ' <select class="custom-select" data-prop="defaults.timeout">';
html += ' <option value="-1">Never</option><option value="1">1 minute</option><option value="2">2 minutes</option><option value="4">4 minutes</option><option value="5">5 minutes</option><option value="10">10 minutes</option><option value="20">20 minutes</option>';
html += ' </select>';
html += ' <label class="control-label">After error postpone for:</label>';
html += ' <select class="custom-select" data-prop="defaults.postponeMinutes">';
html += ' <option value="15">15 minutes</option><option value="30">30 minutes</option><option value="45">45 minutes</option><option value="65">65 minutes</option><option value="90">90 minutes</option><option value="120">2 hours</option>';
html += ' </select>';
html += ' </div></div>';
html += ' <div class="card m-1"><div class="card-body px-4">';
html += ' <h6>Logging</h6>';
html += ' <div><label class="switch"><input type="checkbox" data-prop="devlog.enabled" ><span class="slider round"></span></label> Store log (enables the \'Send Log\' button)</div>';
html += ' <label class="control-label">Max log size in lines:</label>';
html += ' <select class="custom-select" data-prop="devlog.maxLines">';
html += ' <option value="50">50 lines</option><option value="100">100 lines</option><option value="200">200 lines</option><option value="500">500 lines</option><option value="1000">1000 lines</option><option value="2000">2000 lines</option>';
html += ' </select>';
html += ' </div></div>';
html += ' <div class="card m-1"><div class="card-body px-4">';
html += ' <h6>Bagi/Keran</h6>';
html += ' <label class="control-label">Auto withdraw:</label>';
html += ' <select class="custom-select" data-prop="bk.withdrawMode">';
html += ' <option value="0">Disabled</option><option value="1">Once every X hours</option><option value="2">After each successful claim</option>';
html += ' </select>';
html += ' <label class="control-label">Hours (X) between withdraws:</label>';
html += ' <select class="custom-select" data-prop="bk.hoursBetweenWithdraws">';
html += ' <option value="0">Disabled</option><option value="2">2</option><option value="4">4</option><option value="6">6</option><option value="8">8</option><option value="12">12</option><option value="24">24</option>';
html += ' </select>';
html += ' <label class="control-label">Time to wait If IP is restricted:</label>';
html += ' <select class="custom-select" data-prop="bk.sleepMinutesIfIpBan">';
html += ' <option value="0">Disabled</option><option value="45">45 minutes</option><option value="60">1hr</option><option value="75">1hr 15min</option><option value="90">1hr 30min</option><option value="120">2hrs</option><option value="180">3hrs</option><option value="240">4hrs</option>';
html += ' </select>';
html += ' </div></div>';
html += ' </div>';
html += ' <div class="col-md-6 col-sm-12">';
html += ' <div class="card m-1"><div class="card-body px-4">';
html += ' <h6>CryptosFaucets</h6>';
html += ' <div><label class="switch"><input type="checkbox" data-prop="cf.autologin" ><span class="slider round"></span></label> Autologin when neccessary</div>';
html += ' <select class="custom-select" data-prop="cf.credentials.mode">';
html += ' <option value="1">Use Email and Password</option><option value="2">Filled by 3rd party software/extension</option>';
html += ' </select>';
html += ' <label class="control-label">E-Mail</label>';
html += ' <input maxlength="200" type="text" data-prop="cf.credentials.email" required="required" class="form-control" placeholder="Email address..."/>';
html += ' <label class="control-label">Password</label>';
html += ' <input maxlength="200" type="password" data-prop="cf.credentials.password" required="required" class="form-control" placeholder="Password..."/>';
html += ' <label class="control-label">Hours to wait If IP is banned:</label>';
html += ' <select class="custom-select" data-prop="cf.sleepHoursIfIpBan">';
html += ' <option value="0">Disabled</option><option value="2">2</option><option value="4">4</option><option value="8">8</option><option value="16">16</option><option value="24">24</option><option value="26">26</option>';
html += ' </select>';
html += ' </div></div>';
html += ' <div class="card m-1"><div class="card-body px-4">';
html += ' <h6>FreeBitco.in</h6>';
html += ' <div><label class="switch"><input type="checkbox" data-prop="fb.activateRPBonus" checked><span class="slider round"></span></label> Activate RP Bonus</div>';
html += ' </div></div>';
html += ' <div class="card m-1"><div class="card-body px-4">';
html += ' <h6>FaucetPay PTC</h6>';
html += ' <label class="control-label">Hours between runs:</label>';
html += ' <select class="custom-select" data-prop="fp.hoursBetweenRuns">';
html += ' <option value="1">1</option><option value="2">2</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="8">8</option><option value="12">12</option><option value="24">24</option>';
html += ' </select>';
html += ' <label class="control-label">Max duration per run:</label>';
html += ' <select class="custom-select" data-prop="fp.maxTimeInMinutes">';
html += ' <option value="5">5 minutes</option><option value="10">10 minutes</option><option value="15">15 minutes</option><option value="30">30 minutes</option>';
html += ' </select>';
html += ' </div></div>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += '<div class="modal-footer"><a class="btn m-2 anchor btn-outline-danger align-middle" onclick="modalCancel(\'config\')" data-dismiss="modal"><i class="fa fa-times-circle"></i> Cancel</a>';
html += '<a class="btn m-2 anchor btn-outline-success align-middle" onclick="modalSave(\'config\')" data-dismiss="modal"><i class="fa fa-check-circle"></i> Save</a></div>';
html += ' </div>';
//END OF MODAL CONTENTS
html += '</div>';
html += '</div>';
html += '<pre style="width:100%;" id="console-log"><b>Loading...</b></pre>';
html += '<section id="table-struct" class="fragment "><div class="container-fluid bg-dark "><div class="container py-1 "><div class="row mx-0"><div class="title col-3 px-0 text-white"><h2>Schedule</h2></div>';
html += '<div class="title col-6 w-100 text-white"><span id="faucets-display-status" class="text-white"></span></div><div class="title col-3 text-right">';
html += '<div class="em-only d-none"><a class="btn m-2 anchor btn-outline-success align-middle" onclick="editListSave()"><i class="fa fa-check-circle"></i> Save</a>';
html += '<a class="btn m-2 anchor btn-outline-danger align-middle" onclick="editListCancel()"><i class="fa fa-times-circle"></i> Cancel</a></div>';
html += '<div class="em-hide"><a class="btn m-2 anchor btn-outline-primary align-middle" data-toggle="modal" data-target="#modal-dlg" onclick="loadDlg(\'modal-wallet\')"><i class="fa fa-wallet"></i> Wallet</a><a class="btn m-2 anchor btn-outline-primary align-middle" onclick="editList()"><i class="fa fa-edit"></i> Edit</a></div>';
html += '</div></div>';
html += '<div class="row align-items-center text-center justify-content-end">';
html += '<div class="col-12 order-lg-1 text-center"><div class="row justify-content-center"><div class="col table-responsive" id="schedule-container"></div></div></div></div></div></div>';
html += '<span id="update-data" style="display:none;"></span></section>';
html +='<section id="table-struct-promo" class="fragment "><div class="container-fluid bg-dark "><div class="container py-1 "><div class="row mx-0 mb-1">';
html +='<div class="title col-3 px-0 text-white"><h2>Promo Codes</h2></div><div class="title col-4 w-100 text-white">';
html +='<div class="input-group my-0"><div class="mx-2"><label class="switch" title="Check if the code can be reused every 24hs"><input id="promo-daily" type="checkbox"><span class="slider round"></span>Daily</label></div><input type="text" class="form-control py-1" id="promo-text-input" list="promoCode_list" placeholder="Type a Promo code...">';
html += '<datalist id="promoCode_list">';
CFReusableCodesSuggestion.forEach( function(x) { html += '<option>' + x + '</option>' });
html += '</datalist>';
html +='<div class="input-group-append"><button class="btn btn-success" id="promo-button" onclick="savePromoCode()"><i class="fa fa-plus"></i></button>';
html +='</div></div></div>';
html +='<div class="title col-3 text-white justify-content-end"><span id="promo-display-status" class="text-white"></span>';
html +='<span id="promo-code-new" style="display:none;"></span></div><div class="title col-2 text-right"><a class="btn m-2 anchor btn-outline-danger" id="promo-button" onclick="removeAllPromos()">Remove All</a>';
html +='</div></div><div class="row align-items-center text-center justify-content-end"><div class="col-12 order-lg-1 text-center">';
html +='<div class="row justify-content-center"><div class="col table-responsive" id="promo-container"></div></div></div></div></div></div></section>';
html += '<section class="fragment"><div class="container-fluid bg-dark ">';
html += '<div class="row justify-content-center"><a class="btn m-2 anchor btn-outline-primary" id="stats-button" onclick="openStatsChart()">CF Lucky Number Stats</a></div>';
html +='<div class="container py-1" id="stats-fragment" style="display:none;"><div class="row align-items-center text-center justify-content-center">';
html += '<div class="col-md-3"><canvas id="barChart"></canvas><span id="rolls-span" style="display:none;"></span></div></div></div></div></div></section>';
$('#referral-table').before(html);
$('#schedule-container').append( createScheduleTable() );
$(document.querySelector('.navbar-nav')).prepend('<div><a class="btn m-2 btn-primary" href="https://discord.gg/23s9fDgHqe" target="_blank"><div class="">discord</div></a></div>');
};
function createPromoTable(faucets) {
let tableStructure = '';
tableStructure += '<table class="table table-striped table-dark" id="promo-table">';
tableStructure += '<caption style="text-align: -webkit-center;">⏳ Pending ✔️ Accepted 🕙 Used Before ❌ Invalid code ❗ Unknown error ⚪ No code</caption>';
tableStructure += '<thead><tr><th class="">Code</th><th class="">Added</th>';
for (let i = 0, all = faucets.length; i < all; i++) {
tableStructure += '<th data-faucet-id="' + faucets[i].id + '">' + faucets[i].name + '</th>';
}
tableStructure += '</tr></thead><tbody id="promo-table-body"></tbody></table>';
$('#promo-container').append( tableStructure );
};
function createScheduleTable() {
let tableStructure = '';
tableStructure += '<table class="table table-striped table-dark" id="schedule-table"><thead><tr>';
tableStructure += '<th scope="col" class="edit-status d-none em-only" style="">Active</th><th class="">#</th><th class="">Name</th><th class="">Site</th><th class="">Last Claim</th>';
tableStructure += '<th class="">Aggregate</th><th class="">Balance</th><th class="" id="converted-balance-col">FIAT</th><th class="">Next Roll</th>';
tableStructure += '<th scope="col" class="">Msgs</th><th scope="col" class="em-hide" style="">Run ASAP</th></tr></thead><tbody id="schedule-table-body"></tbody></table>';
return tableStructure;
};
function loadScheduleTable(data) {
let tableBody = '';
for(let i=0, all = data.length; i < all; i++) {
tableBody += '<tr class="align-middle" data-id="' + data[i].id + '" data-cmc="' + data.find(x => x.id == data[i].id).cmc + '" data-balance="';
if (data[i].balance) {
if(typeof data[i].balance == 'string') {
tableBody += data[i].balance.split(' ')[0];
} else {
tableBody += data[i].balance.toFixed(8);
}
}
tableBody += '">';
tableBody +='<td class="align-middle edit-status d-none em-only"><label class="switch"><input type="checkbox" data-original="' + (data[i].enabled ? '1' : '0') + '" ' + (data[i].enabled ? 'checked' : ' ') + '><span class="slider round"></span></label></td>';
tableBody +='<td class="align-middle">' + (data[i].enabled ? (i + 1).toString() : '-') + '</td>';
tableBody +='<td class="align-middle em-input text-left" data-field="displayName">' + data[i].name + '</td>';
tableBody +='<td class="align-middle text-left" style="width: 20%">';
if (Array.isArray(data[i].rf)) {
tableBody +='<a class="edit-site" title="Visit site" target="_blank" href="' + data[i].url.href + data[i].rf[helpers.randomInt(0, data[i].rf.length -1)] + '"><i class="fa fa-external-link-alt"></i></a> ';
} else {
tableBody +='<a class="edit-site" title="Visit site" target="_blank" href="' + (new URL(data[i].rf, data[i].url.origin)).href + '"><i class="fa fa-external-link-alt"></i></a> ';
}
tableBody += (data[i].type == WebType.BAGIKERAN ? data[i].url.host + data[i].url.pathname : data[i].url.host) + '</td>';
tableBody +='<td class="align-middle">' + data[i].lastClaim.toFixed(8) + '</td>';
tableBody +='<td class="align-middle">' + data[i].aggregate.toFixed(8) + '</td>';
tableBody +='<td class="align-middle">';
if (data[i].balance) {
if(typeof data[i].balance == 'string') {
tableBody += data[i].balance.split(' ')[0];
} else {
tableBody += data[i].balance.toFixed(8);
}
}
tableBody + '</td>';
tableBody +='<td class="align-middle fiat-conversion"></td>';
tableBody +='<td class="align-middle">' + helpers.getPrintableTime(data[i].nextRoll) + '</td>';
tableBody +='<td class="align-middle">' + addBadges(data[i].stats) + '</td>';
tableBody +='<td class="align-middle em-hide"><a class="edit-site" data-toggle="tooltip" data-placement="left" title="Run ASAP" href="javascript:updateValues(\'runAsap\', { id: ' + data[i].id + ' })" onclick=""><i class="fa fa-redo"></i></a></td>';
tableBody +='</tr>';
}
$('#schedule-table-body').html(tableBody);
location.href = 'javascript:convertToFiat();';
};
function addBadges(stats) {
let consecutiveTimeout = stats.countTimeouts;
let otherErrors = stats.errors;
let html = ' ';
if (consecutiveTimeout) {
html += `<span class="badge badge-pill badge-warning" title="${consecutiveTimeout} consecutive timeouts">${consecutiveTimeout}</span>`;
}
if (otherErrors) {
html += `<span class="badge badge-pill badge-warning" title="${otherErrors.errorMessage}">${helpers.getEnumText(ErrorType, otherErrors.errorType)}</span>`;
}
return html;
}
function loadPromotionTable(codes) {
let tableBody = '';
for(let c=0; c < codes.length; c++) {
let data = codes[c];
tableBody += '<tr data-promotion-id="' + data.id + '">';
tableBody += '<td class="align-middle text-left ' + (data.repeatDaily ? 'text-warning' : '') + '">';
tableBody += '<a data-toggle="tooltip" data-placement="left" title="Remove" href="javascript:removePromoCode(' + data.id + ', \'' + data.code + '\')" onclick=""><i class="fa fa-times-circle"></i></a> ';
tableBody += '<span title="' + (data.repeatDaily ? 'Reusable Code' : 'One-time-only Code') + '">' + data.code + '</span></td>';
tableBody +='<td class="align-middle" title="' + (data.repeatDaily ? 'Reusable Code' : 'One-time-only Code') + '">' + helpers.getPrintableDateTime(data.added) + '</td>';
for(let i=0, all = data.statusPerFaucet.length; i < all; i++) {
tableBody +='<td class="align-middle" title="Runned @' + helpers.getPrintableDateTime(data.statusPerFaucet[i].execTimeStamp) + '">' + helpers.getEmojiForPromoStatus(data.statusPerFaucet[i].status ?? 0) + '</td>';
}
tableBody +='</tr>';
}
$('#promo-table-body').html(tableBody);
};
function loadWalletTable(data) {
let tableBody = '';
for(let i=0, all = data.length; i < all; i++) {
tableBody += '<tr class="align-middle" data-id="'+ data[i].id + '">';
tableBody += '<td class="align-middle">' + data[i].name + '</td>';
tableBody += '<td class="align-middle em-input"><input type="text" class="w-100" data-field="address" data-original="' + data[i].address + '" value="' + data[i].address + '"></td>';
tableBody += '</tr>';
}
$('#wallet-table-body').html(tableBody);
};
function loadConfigData(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.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 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 elWithdrawMode = document.querySelector('[data-prop="bk.withdrawMode"]');
let elHoursBetweenWithdraws = document.querySelector('[data-prop="bk.hoursBetweenWithdraws"]');
let elDevlogEnabled = document.querySelector('[data-prop="devlog.enabled"]');
let elDevlogMaxLines = document.querySelector('[data-prop="devlog.maxLines"]');
elCredentialsMode.disabled = !elCredentialsAutologin.checked;
elCredentialsEmail.disabled = ( (!elCredentialsAutologin.checked || elCredentialsMode.value == "2") ? true : false);
elCredentialsPassword.disabled = ( (!elCredentialsAutologin.checked || elCredentialsMode.value == "2") ? true : false);
elHoursBetweenWithdraws.disabled = ( (elWithdrawMode.value == "0" || elWithdrawMode.value == "2") ? true : false);
elDevlogMaxLines.disabled = !elDevlogEnabled.checked;
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;
}
}
elWithdrawMode.onchange = function (e) {
if (e.target.value == "0" || e.target.value == "2") {
document.querySelector('[data-prop="bk.hoursBetweenWithdraws"]').disabled = true;
} else {
document.querySelector('[data-prop="bk.hoursBetweenWithdraws"]').disabled = false;
}
}
elDevlogEnabled.onchange = function (e) {
document.querySelector('[data-prop="devlog.maxLines"]').disabled = !e.target.checked;
}
};
function refresh(scheduleData, promotionData, walletData, configData) {
if (scheduleData) {
loadScheduleTable(scheduleData);
}
if (promotionData) {
loadPromotionTable(promotionData);
}
if (walletData) {
loadWalletTable(walletData);
}
if (configData) {
loadConfigData(configData);
}
};
function log(msg, elapsed = false) {
if(shared.getConfig()['devlog.enabled']) { shared.devlog(msg, elapsed) };
if(msg) {
let previous = logLines[0].split(' ')[1];
if(elapsed && (previous == msg)) {
logLines[0] = helpers.getPrintableTime() + ' ' + msg + ' [Elapsed time: ' + elapsed + ' seconds]';
} else {
logLines.pop();
logLines.unshift(helpers.getPrintableTime() + ' ' + msg);
}
$('#console-log').html(logLines.join('<br>'));
}
};
return {
init: init,
refresh: refresh,
loadPromotionTable: loadPromotionTable,
log: log
}
},
createCFPromotions: function() {
let codes = [];
function PromotionCode(id, code, repeatDaily = false) {
this.id = id;
this.code = code;
this.added = new Date();
this.statusPerFaucet = [];
this.repeatDaily = repeatDaily;
this.lastExecTimeStamp = null;
};
function getFaucetStatusInPromo(promo, faucetId) {
let faucet = promo.statusPerFaucet.find(x => x.id == faucetId);
if (faucet.status && promo.repeatDaily) {
//Using 26 hs instead of 24hs, and 2hs gap retry when code is flagged as USEDBEFORE
if((faucet.status == PromoStatus.ACCEPTED && (Date.now() - faucet.execTimeStamp.getTime()) > HS_26_IN_MILLISECONDS)
|| (faucet.status == PromoStatus.USEDBEFORE && (Date.now() - faucet.execTimeStamp.getTime()) > HS_2_IN_MILLISECONDS)) {
faucet.status = PromoStatus.PENDING;
}
}
return faucet.status ?? PromoStatus.NOCODE;
};
function addNew(code, repeatDaily = false) {
let newPromo = new PromotionCode(codes.length, code, repeatDaily);
newPromo.statusPerFaucet = manager.getFaucetsForPromotion().map(x => {
return {
id: x.id,
};});
newPromo.statusPerFaucet.forEach(function (element, idx, arr) {
arr[idx].status = PromoStatus.PENDING;
arr[idx].execTimeStamp = null;
});
codes.push(newPromo);
codes.sort((a, b) => (a.id < b.id) ? 1 : -1);
save();
};
function getAll() {
return codes;
};
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 = false;
codes.forEach(function (promotion, idx, arr) {
let status = getFaucetStatusInPromo(promotion, faucetId);
if (status == PromoStatus.PENDING) {
resp = promotion.code;
return;
}
});
return resp;
};
function save() {
persistence.save('CFPromotions', getAll(), true);
};
function load(data) {
codes = data;
};
function removeAll() {
codes = [];
save();
};
function remove(id, code) {
let idx = codes.findIndex(x => x.id == id && x.code == code);
if(idx != -1) {
codes.splice(idx, 1);
save();
}
return idx;
};
return {
addNew: addNew,
removeAll: removeAll,
remove: remove,
getAll: getAll,
load: load,
updateFaucetForCode: updateFaucetForCode,
hasPromoAvailable: hasPromoAvailable
}
},
createInteractions: function(){
let randomInteractionLevel = RandomInteractionLevel.MEDIUM;
let maxActions = 0;
let performedActions = -1;
let selectableElements;
let actions = {
available: [
function() {
$('html, body').animate({
scrollTop: helpers.randomInt(0, $('html, body').get(0).scrollHeight)
}, {
complete: setTimeout(interactions.addPerformed, helpers.randomMs(100, 3000)),
duration: helpers.randomMs(100, 1500)
});
},
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 RandomInteractionLevel.NONE:
maxActions = 0;
break;
case RandomInteractionLevel.LOW:
maxActions = helpers.randomInt(2, 4);
break;
case RandomInteractionLevel.MEDIUM:
maxActions = helpers.randomInt(5, 8);
break;
case 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
};
},
createSGProcessor: function() {
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 {
activateMiner();
}
}
};
function hasPopup() {
return $('.wrapper.grid.min-h-0.md-min-h-1-2.md-relative.md-rounded-lg.md-bg-dark-4 svg circle').length > 0;
};
function closePopup() {
try {
$('svg.flex.w-8.h-8.fill-current')[0].parentElement.click();
} catch { }
};
function isLoading() {
return $('#loader-logo').length;
};
function isMinerActive() {
timerSpans = $('.mb-8 .wrapper .mb-1 span');
if(timerSpans.length > 0) {
shared.devlog(`SG: Miner is active`);
return true;
} else {
shared.devlog(`SG: Miner is inactive`);
return false;
}
return (timerSpans.length === 0);
};
function activateMiner() {
const activateButton = document.querySelector('.mb-8 .wrapper button');
if (activateButton) {
activateButton.click();
shared.devlog(`SG: Activate miner clicked`);
// setTimeout(processRunDetails, helpers.randomMs(10000, 20000));
setTimeout(run, helpers.randomMs(10000, 20000));
} else {
processRunDetails()
}
};
function processRunDetails() {
let result = {};
result.nextRoll = helpers.addMinutes(new Date(), readCountdown().toString());
result.balance = readBalance();
shared.closeWindow(result);
};
function readCountdown() {
let mins = 15;
try {
let timeLeft = timerSpans.last().text().split(':');
shared.devlog(`SG Countdown timeLeft spans:`);
shared.devlog(timeLeft);
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 = $('span.text-accent').first().text() + " BTC";
} catch (err) { }
return balance;
};
return {
run: run,
processRunDetails: processRunDetails
};
},
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;
function init() {
let urlType = helpers.cf.getUrlType(window.location.href);
switch(urlType) {
case CFUrlType.FREE:
if(localeConfig.setToEnglish) {
let refValue = $('.nav-item a')[4].innerHTML;
if (refValue != 'Settings') {
window.location.href = '/set-language/en';
}
}
addJS_Node (null, null, overrideSelectNativeJS_Functions);
interactions = objectGenerator.createInteractions();
run();
break;
case CFUrlType.PROMOTION:
interactions = objectGenerator.createInteractions();
runPromotion();
break;
case CFUrlType.HOME:
if (shared.getConfig()['cf.autologin']) {
addJS_Node (null, null, overrideSelectNativeJS_Functions);
doLogin();
} else {
shared.closeWithError(ErrorType.NEED_TO_LOGIN, '');
}
break;
case CFUrlType.CONTACTTWITTER:
shared.closeWithError(ErrorType.IP_BAN, '');
break;
default:
break;
}
return;
}
function run() {
navigationProcess = NavigationProcess.ROLLING;
displayStatusUi();
setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
};
function doLogin() {
navigationProcess = NavigationProcess.LOGIN;
displayStatusUi();
setTimeout(findLoginForm, helpers.randomMs(2000, 5000));
};
function isFullyLoaded() { //Waits 55 seconds max
if(document.readyState == 'complete' || timeWaiting == -1) {
document.getElementById('process-status').innerHTML = 'Interacting';
timeWaiting = 0;
interact();
} else {
timeWaiting = -1;
document.getElementById('process-status').innerHTML = 'Waiting for document fully loaded';
setTimeout(isFullyLoaded, helpers.randomMs(45000, 55000));
}
};
function runPromotion() {
navigationProcess = NavigationProcess.PROCESSING_PROMOTION
displayStatusUi();
setTimeout(findPromotionTag, helpers.randomMs(1000, 3000));
};
function findCountdownOrRollButton() {
if( isCountdownVisible() && !isRollButtonVisible() ) {
timeWaiting = 0;
processRunDetails();
} else if ( !isCountdownVisible() && isRollButtonVisible() ) {
timeWaiting = 0;
setTimeout(isFullyLoaded, helpers.randomMs(1000, 5000));
} else {
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return;
}
timeWaiting += 3000;
setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
}
};
function findLoginForm() {
if ( document.getElementById('div.login-wrapper').isVisible() ) {
//Other possible error is if recaptcha did not load yet... so maybe wait til the web is fully loaded for low connection issues
let errElement = document.querySelector('.login-wrapper .error');
if( errElement && errElement.innerHTML != '') {
let errorMessage = errElement.innerText;
shared.closeWithError(ErrorType.LOGIN_ERROR, errorMessage);
return;
}
if(!loopingForErrors) {
if(shared.getConfig()['cf.credentials.mode'] == 1) {
timeWaiting = 0;
$('.login-wrapper input[name="email"]').val(shared.getConfig()['cf.credentials.email']);
$('.login-wrapper input[name="password"]').val(shared.getConfig()['cf.credentials.password']);
$('.login-wrapper button.login').click();
loopingForErrors = true;
} else {
if($('.login-wrapper input[name="email"]').val() != '' && $('.login-wrapper input[name="password"]').val() != '') {
$('.login-wrapper button.login').click();
$('#process-status')[0].innerHTML = 'Processing';
loopingForErrors = true;
} else {
$('#process-status')[0].innerHTML = 'Waiting for credentials...';
if (timeWaiting/1000 > (shared.getConfig()['defaults.timeout'] / 1.5) * 60) {
shared.closeWithError(ErrorType.LOGIN_ERROR, 'No credentials were provided');
return;
}
}
}
}
}
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return;
}
timeWaiting += 3000;
setTimeout(findLoginForm, helpers.randomMs(2000, 5000));
};
function interact() {
let selectables = []
selectables = selectables.concat($('td').toArray());
selectables = selectables.concat($('p').toArray());
selectables = selectables.concat($('th').toArray());
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 = $('.timeout-wrapper');
return ($(countdown).length > 0 && $(countdown[0]).is(':visible'));
};
function isRollButtonVisible() {
rollButton = $('.main-button-2.roll-button.bg-2');
return ($(rollButton).length > 0 && $(rollButton[0]).is(':visible'));
};
function roll() {
$('#process-status')[0].innerHTML = 'Roll triggered';
$(rollButton[0]).click();
setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 3000));
}
function isPromotionTagVisible() {
let pTags = $('p');
if (pTags.length > 0) {
promotionTag = $('p')[0];
return true;
}
return false;
};
function findPromotionTag() {
if( isPromotionTagVisible() ) {
processRunDetails();
} else {
setTimeout(cfProcessor.findPromotionTag, helpers.randomMs(2000, 5000));
}
};
function processRunDetails() {
let result = {};
if(navigationProcess == NavigationProcess.ROLLING) {
result.nextRoll = readCountdown();
result.claimed = readClaimed();
result.balance = readBalance();
if(result.claimed != 0) {
result.rolledNumber = readRolledNumber();
}
result.balance = readBalance();
} else if (navigationProcess == NavigationProcess.PROCESSING_PROMOTION) {
result.promoStatus = readPromoStatus();
result.promoCode = readPromoCode();
if (result.promoStatus == PromoStatus.ACCEPTED) {
result.nextRoll = helpers.addMinutes(new Date(-20), "0");
}
}
shared.closeWindow(result);
};
function readCountdown() {
let minsElement = $('.timeout-container .minutes .digits');
let mins = "0";
if ($(minsElement).length > 0) {
mins = $(minsElement)[0].innerHTML;
}
if (mins) {
return helpers.addMinutes(new Date(), mins.toString());
} else {
return null;
}
};
function readClaimed() {
let claimed = 0;
try {
claimed = $('.result')[0].innerHTML;
claimed = claimed.trim();
claimed = claimed.slice(claimed.lastIndexOf(" ") + 1);
} catch(err) { }
return claimed;
};
function readRolledNumber() {
let number = 0;
try {
number = $('.lucky-number').toArray().map(x => x.innerText).join('');
number = parseInt(number);
} catch(err) { }
return number;
};
function readBalance() {
let balance = "";
try {
balance = $('.navbar-coins.bg-1 a').first().text();
} catch(err) { }
return balance;
};
function readPromoStatus() {
let promoStatus = PromoStatus.UNKNOWNERROR;
try {
if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeAccepted) > 0) {
return PromoStatus.ACCEPTED;
} else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeUsed) > 0) {
return PromoStatus.USEDBEFORE;
} else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeExpired) > 0) {
return PromoStatus.EXPIRED;
} else if(localeConfig.stringSearches.promoCodeInvalid.findIndex(x => promotionTag.innerHTML.indexOf(x) > -1) == -1) {
return PromoStatus.INVALID;
}
} catch ( err ) { }
return promoStatus;
};
function validatePromoString() {
};
function readPromoCode() {
var urlSplit = window.location.href.split('/');
return urlSplit[urlSplit.length - 1];
};
function displayStatusUi() {
$( 'body' ).prepend( '<div class="withdraw-button bg-2" style="top:30%; z-index:1500;" href="#">⚙️ <span id="process-status">Processing</span></div>' );
};
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
}
},
createFBProcessor: function() {
let countdownMinutes;
let timeWaiting= 0;
function timedOut(addMs) {
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return true;
}
timeWaiting += addMs;
return false;
}
function run() {
setTimeout(findCountdownOrRollButton, helpers.randomMs(12000, 15000));
};
function findCountdownOrRollButton() {
if ( isCountdownVisible() ) {
timeWaiting = 0;
countdownMinutes = +document.querySelectorAll('.free_play_time_remaining.hasCountdown .countdown_amount')[0].innerHTML + 1;
let result = {};
result.balance = readBalance();
result.nextRoll = helpers.addMinutes(new Date(), countdownMinutes.toString());
shared.closeWindow(result);
return;
}
if ( isRollButtonVisible() ) {
if (shared.getConfig()['fb.activateRPBonus']) {
if (!document.getElementById('bonus_container_free_points')) {
document.querySelector('a.rewards_link').click();
activateBonus(0);
}
}
if (isHCaptchaVisible()) {
waitForCaptcha();
} else {
clickRoll();
}
} else {
setTimeout(findCountdownOrRollButton, helpers.randomMs(12000, 15000));
}
};
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).is(':visible')) {
return true;
}
return false;
};
function isRollButtonVisible() {
return $(document.getElementById('free_play_form_button')).is(':visible');
};
function waitForCaptcha() {
if ( document.querySelector('.h-captcha > iframe').getAttribute('data-hcaptcha-response').length > 0) {
clickRoll();
} else {
if (timedOut(10000)) {
return;
}
setTimeout(waitForCaptcha, helpers.randomMs(10000, 12000));
}
};
function clickRoll() {
try {
document.getElementById('free_play_form_button').click();
setTimeout(processRunDetails, helpers.randomMs(3000, 10000));
} catch (err) {
shared.closeWithError(ErrorType.CLICK_ROLL_ERROR, err);
}
};
function processRunDetails() {
if ($(document.getElementById('winnings')).is(':visible')) {
closePopup();
let result = {};
result.claimed = readClaimed();
result.balance = readBalance();
if(result.claimed != 0) {
result.rolledNumber = readRolledNumber();
result.nextRoll = helpers.addMinutes(new Date(), "60");
}
shared.closeWindow(result);
return;
}
if ($('.free_play_result_error').is(':visible')) {
shared.closeWithError(ErrorType.ROLL_ERROR, $('.free_play_result_error')[0].innerHTML);
return;
}
if($('#free_play_error').is(':visible')) {
shared.closeWithError(ErrorType.ROLL_ERROR, $('.free_play_error')[0].innerHTML);
return;
}
if ($(document.getElementById('same_ip_error')).is(':visible')) {
shared.closeWithError(ErrorType.ROLL_ERROR, document.getElementById('same_ip_error').innerHTML);
return;
}
if (timedOut(5000)) {
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;
};
function activateBonus(i) {
if($(document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_error')).is(':visible')) {
let closeBtn = document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_box_close')
if ($(closeBtn).is(':visible')) {
closeBtn.click();
}
} else if ($(document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_success')).is(':visible')) {
let closeBtn = document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_box_close')
if ($(closeBtn).is(':visible')) {
closeBtn.click();
document.querySelector('#free_play_link_li a').click();
setTimeout(findCountdownOrRollButton, helpers.randomMs(10000, 12000));
return;
}
}
try {
let redeemButtons = document.querySelectorAll('#free_points_rewards button');
redeemButtons[i].click();
i = i + 1;
} catch (err) {
}
if(i > 4) {
document.querySelector('#free_play_link_li a').click();
setTimeout(findCountdownOrRollButton, helpers.randomMs(10000, 12000));
return;
}
setTimeout(activateBonus.bind(null, i), 5000);
};
return {
run: run
};
},
createFPProcessor: function() {
let timeWaiting= 0;
function timedOut(addMs) {
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return true;
}
timeWaiting += addMs;
return false;
}
function init() {
if(window.location.href.includes('ptc/view')) {
ptcSingle();
} else if (window.location.href.includes('ptc')) {
ptcList();
} else if (window.location.href.includes('account/login')) {
shared.closeWithError(ErrorType.NEED_TO_LOGIN, '');
}
return;
}
function ptcList() {
let result;
let runMsgDiv = document.querySelector('.alert.alert-info');
if (runMsgDiv) {
let runMsg = runMsgDiv.innerHTML;
if (runMsg.includes('invalid captcha')) {
// Warn? Usually a error if ptcList is refreshed
} else if (runMsg.includes('Good job')) {
// "Good job! You have been credited with 0.00000001 BTC."
try {
let idx = runMsg.search(/\d/);
let claimed = parseFloat(runMsg.slice(idx, idx + 10));
result = shared.getResult();
result.claimed = (result.claimed ?? 0) + claimed;
result.nextRoll = helpers.addMs(new Date(), helpers.getRandomMs(shared.getConfig()['fp.hoursBetweenRuns'] * 60, 2)); // Wait hoursBetweenRuns +/- 1%
shared.updateWithoutClosing(result);
} catch { }
}
}
if ($('b:contains("Whoops!")').length) {
result = shared.getResult();
result.nextRoll = helpers.addMs(new Date(), helpers.getRandomMs(shared.getConfig()['fp.hoursBetweenRuns'] * 60, 2)); // Wait hoursBetweenRuns +/- 2%
shared.closeWindow(result);
return;
}
let adButtons = $('button').filter(function(idx) {
return this.innerHTML.includes('VISIT AD FOR') > 0;
});
if (adButtons.length > 0) {
adButtons[0].click();
return;
}
if (timedOut(10000)) {
return;
}
setTimeout(ptcList, helpers.randomMs(10000, 12000));
}
function ptcSingle() {
if($('input[name="complete"]').is(':visible')) {
setTimeout(waitForCaptcha, 15000);
} else if (document.querySelector('body').innerText.toLowerCase().includes('ad does not exist')) {
window.location.href = 'https://faucetpay.io/ptc';
} else {
if (timedOut(5000)) {
return;
}
setTimeout(ptcSingle, helpers.randomMs(5000, 6000));
}
}
function waitForCaptcha() {
if ( document.querySelector('.h-captcha > iframe').getAttribute('data-hcaptcha-response').length > 0 ) {
clickClaim();
} else {
if (timedOut(9000)) {
return;
}
setTimeout(waitForCaptcha, helpers.randomMs(9000, 11000));
}
}
function clickClaim() {
$('input[name="complete"]').focus();
$($('input[name="complete"]')[0]).attr("onclick", "");
$('input[name="complete"]').click();
//force close with timeout in case it's still opened
setTimeout(shared.closeWithError.bind(null, 'TIMEOUT', 'Timed out after clicking a CLAIM button.'), helpers.minToMs(shared.getConfig()['defaults.timeout']));
}
return {
init: init
};
},
// TODO: refactor to add more faucets to this processor:
createGenericFaucetProcessor: function(wt) {
let webType = wt;
let countdownMinutes;
let timeWaiting= 0;
let selectElement = {
rollButton: function() {
switch (webType) {
case WebType.FREELITECOIN:
return document.getElementById('roll');
break;
case WebType.FREEETHEREUMIO:
return document.querySelector('#rollform button');
break;
default:
return;
break;
}
},
balance: function() {
switch (webType) {
case WebType.FREELITECOIN:
return document.getElementById('money');
break;
case WebType.FREEETHEREUMIO:
return document.getElementById('cryptovalue')
break;
default:
return;
break;
}
}
};
function timedOut(addMs) {
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return true;
}
timeWaiting += addMs;
return false;
}
function init() {
let url = new URL(window.location.href);
switch (webType) {
case WebType.FREELITECOIN:
if (url.pathname == '/') {
run();
} else if (url.pathname.includes('/login')) {
shared.closeWithError(ErrorType.NEED_TO_LOGIN, '');
}
break;
case WebType.FREEETHEREUMIO:
if (url.pathname == '/free/') {
run();
} else if (url.pathname == '/') {
shared.closeWithError(ErrorType.NEED_TO_LOGIN, '');
}
break;
}
return;
}
function run() {
setTimeout(findCountdownOrRollButton, helpers.randomMs(12000, 15000));
};
function findCountdownOrRollButton() {
if ( isCountdownVisible() ) {
timeWaiting = 0;
let countdownMinutes = document.getElementById('cislo1');
let result = {};
result.balance = readBalance();
result.nextRoll = helpers.addMinutes(new Date(), countdownMinutes.innerHTML.toString());
shared.closeWindow(result);
return;
}
if ( isRollButtonVisible() ) {
if (isHCaptchaVisible()) {
waitForCaptcha();
} else {
clickRoll();
}
} else {
setTimeout(findCountdownOrRollButton, helpers.randomMs(10000, 12000));
}
};
function isCountdownVisible() {
return $(document.getElementById('cislo1')).is(':visible') || $(document.getElementById('cislo2')).is(':visible');
};
function isHCaptchaVisible() {
let hCaptchaFrame = document.querySelector('.h-captcha > iframe');
if (hCaptchaFrame && $(hCaptchaFrame).is(':visible')) {
return true;
}
return false;
};
function isRollButtonVisible() {
let rollButton = selectElement.rollButton();
return rollButton && $(rollButton).is(':visible');
};
function waitForCaptcha() {
if ( document.querySelector('.h-captcha > iframe').getAttribute('data-hcaptcha-response').length > 0) {
clickRoll();
} else {
if (timedOut(10000)) {
return;
}
setTimeout(waitForCaptcha, helpers.randomMs(10000, 12000));
}
};
function clickRoll() {
try {
shared.devlog('Clicking roll button');
selectElement.rollButton().click();
setTimeout(processRunDetails, helpers.randomMs(10000, 12000));
} catch (err) {
shared.closeWithError(ErrorType.CLICK_ROLL_ERROR, err);
}
};
function processRunDetails() {
let info = document.getElementById('info');
if (info && $(info).is(':visible')) {
let result = {};
result.claimed = readClaimed();
result.balance = readBalance();
if(result.claimed != 0) {
result.rolledNumber = readRolledNumber();
result.nextRoll = helpers.addMinutes(new Date(), "60");
}
shared.closeWindow(result);
return;
}
if (timedOut(5000)) {
return;
}
setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
};
function readRolledNumber() {
let rolled = 0;
try {
rolled = parseInt(document.getElementById('numberroll').innerHTML);
} catch { }
return rolled;
};
function readBalance() {
let balance = 0;
try {
balance = selectElement.balance().innerHTML;
} catch { }
return balance;
};
function readClaimed() {
let claimed = 0;
try {
let info = document.getElementById('info').innerHTML;
let idx = info.search(/0\./);
claimed = parseFloat(info.slice(idx, idx + 10));
} catch { }
return claimed;
};
return {
init: init
};
},
createBagiKeranProcessor: function() {
let timeWaiting= 0;
let elements = {
errorDivs: function() {
return document.querySelectorAll('.alert.alert-danger');
},
warningDivs: function() {
return document.querySelectorAll('.alert.alert-warning');
},
successDivs: function() {
return document.querySelectorAll('.alert.alert-success');
},
errorCloudflare: function() {
return document.querySelector('#cf-error-details p');
},
openLoginModalButton: function() {
return document.getElementById('submit');
},
modal: function() {
return document.querySelector('#myModal.show');
},
addressInput: function() {
return document.querySelector('input[name="address"]');
},
submitButton: function() {
return document.querySelector('#myModal button[type="submit"]');
},
openClaimModalButton: function() {
return document.querySelector('form button[type="submit"]');
},
openWithdrawModal: function() {
return document.getElementById('submit');
},
linkWithdrawMinNotReached: function() {
return document.querySelector('a.btn.btn-primary.btn-block');
}
};
function timedOut(addMs) {
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return true;
}
timeWaiting += addMs;
return false;
}
function init() {
if(shared.getCurrent().params.doSignOut) { // Unexpected behavior with BCH @ Bagi: seems it didn't login when the previous run was TRX/USDT so it saved the roll with that address and you couldn't withdraw:
//Before you can receive payments at FaucetPay.io with this address you must link it to an account. Create an account at FaucetPay.io and link your address, then come back and claim again
shared.devlog(`${window.location.href} signing out`);
shared.getCurrent().params.doSignOut = false;
shared.saveFlowControl();
window.location.href = (new URL('signout.php', window.location.href)).href;;
return;
}
if (window.location.href.includes('captha.php')) {
setTimeout(runCaptchaPage, helpers.randomMs(1000, 2000));
return;
} else if (window.location.href.includes('withdraw.php')) {
setTimeout(runWithdraw, helpers.randomMs(1000, 2000));
return;
} else {
setTimeout(run, helpers.randomMs(1000, 2000));
return;
}
}
function run() {
readAlerts();
processIndex();
};
function runCaptchaPage() {
readAlerts();
shared.clearRetries();
processCaptchaPage();
}
function runWithdraw() {
readAlerts();
shared.clearRetries();
processWithdraw();
}
function readAlerts() {
let elm;
elements.warningDivs().forEach(function (elem) {
if (elem && elem.innerText.includes('already claimed')) { // "You have already claimed in the last 60 minutes.<br>You can claim again in 59 minutes.<br>"
let result = {};
try {
let mins = elem.innerText.split('\n')[1].replace(/\D/g, '');
result.nextRoll = helpers.addMinutes(new Date(), mins);
} catch {
result.nextRoll = helpers.addMinutes(new Date(), "60");
}
if (shared.getCurrent().params.doWithdraw) {
shared.updateWithoutClosing(result);
window.location.href = (new URL('withdraw.php', window.location.href)).href;
} else {
shared.closeWindow(result);
}
return;
}
});
elements.successDivs().forEach(function (elem) {
if (elem) {
if (elem.innerText.includes('claimed successfully')) { // "You've claimed successfully 2 Satoshi BTC." ...
let result = {};
result.nextRoll = helpers.addMinutes(new Date(), "60");
result.claimed = 0;
try {
let val = elem.innerText.split('\n')[0].replace(/\D/g, '');
if (typeof val == 'string') {
val = +val;
}
if (Number.isInteger(val)) {
val = val / 100000000;
}
result.claimed = val;
} catch { }
try {
let mins = elem.innerText.split('\n')[1].replace(/\D/g, '');
result.nextRoll = helpers.addMinutes(new Date(), mins);
} catch { }
if (shared.getCurrent().params.doWithdraw) {
shared.updateWithoutClosing(result);
let link = elem.querySelector('a');
if (link && link.innerText.includes('withdraw')) {
link.click();
return;
} else {
window.location.href = (new URL('withdraw.php', window.location.href)).href;;
}
}
shared.closeWindow(result);
return;
} else if (elem.innerText.includes('was sent to')) { //2 satoshi was sent to <a target="_blank" href="https://faucetpay.io/page/user-admin">your account at FaucetPay.io</a>
let result = {};
result.withdrawnAmount = 0;
let val = elem.innerHTML.split(' ')[0];
if (typeof val == 'string') {
val = +val;
}
if (Number.isInteger(val)) {
val = val / 100000000;
}
result.withdrawnAmount = val;
shared.closeWindow(result);
return;
}
}
});
elm = elements.errorCloudflare();
if (elm) {
// "Access denied | bagi.co.in used Cloudflare to restrict access" @document.title
shared.closeWithError(ErrorType.IP_RESTRICTED, document.title + ' | ' + elm.innerText);
return;
}
elements.errorDivs().forEach(function (elem) {
if (elem) {
if (elem.innerText.toLowerCase().includes('vpn/proxy/tor')) { // "VPN/Proxy/Tor is not allowed on this faucet." ...
shared.closeWithError(ErrorType.IP_ERROR, elem.innerText);
return;
} else if (elem.innerText.toLowerCase().includes('look valid')) { // The Bitcoin Address doesn't look valid
//invalid address
shared.closeWithError(ErrorType.ADDRESS_ERROR, elem.innerText);
return;
} else if (elem.innerText.toLowerCase().includes('login not valid')) { // Login Not Valid, Please reLogin
// TODO: FIX => ITS NOT WORKING BECAUSE B/K REALOADS ITSELF TOO MANY TIMES
// FORCE 1 RETRY as sometimes it might work
if(shared.isRetrying()) {
shared.devlog(`${window.location.href} login retry failed`);
shared.closeWithError(ErrorType.LOGIN_ERROR, elem.innerText);
} else {
shared.devlog(`${window.location.href} will retry to login`);
}
return;
} else if (elem.innerText.toLowerCase().includes('claim not valid')) { // Claim not Valid, Please reClaim. Try again
// FORCE 1 RETRY
if(shared.isRetrying()) {
shared.devlog(`${window.location.href} claim retry failed`);
shared.closeWithError(ErrorType.CLAIM_ERROR, elem.innerText);
} else {
shared.devlog(`${window.location.href} will retry to claim`);
}
return;
} else {
// Unknown issue
shared.closeWithError(ErrorType.ERROR, elem.innerText);
return;
}
}
});
elm = elements.linkWithdrawMinNotReached();
if (elm) {
if(elm.innerText.toLowerCase().includes('minimum withdraw')) { // Minimum Withdraw is ...
shared.closeWithError(ErrorType.MIN_WITHDRAW_ERROR, elm.innerText);
return;
}
}
}
function processIndex() {
if (elements.modal() && elements.addressInput() && elements.submitButton()) { // 2. Fill address & click Login
if(elements.addressInput().value != '') {
shared.devlog('Clicking LOGIN');
elements.submitButton().click(); // shoud redirect but check for timeout
} else {
elements.addressInput().value = shared.getCurrent().params.address;
}
setTimeout(run, helpers.randomMs(2000, 4000));
return;
}
if (elements.openLoginModalButton()) { // 1. Click the Get Started Button
elements.openLoginModalButton().click();
timeWaiting = 0;
setTimeout(processIndex, helpers.randomMs(1000, 3000));
return;
}
if (elements.openClaimModalButton()) { // Claim Bitcoin Button
elements.openClaimModalButton().click();
timeWaiting = 0;
setTimeout(processIndex, helpers.randomMs(2000, 4000));
return;
}
setTimeout(run, helpers.randomMs(2000, 4000));
};
function processCaptchaPage() {
if(elements.modal()) {
setTimeout(waitForCaptcha, helpers.randomMs(2000, 4000));
return;
}
if (elements.openLoginModalButton()) { // 1. Click the Claim Button to open the modal w/the hCaptcha
elements.openLoginModalButton().click();
timeWaiting = 0;
setTimeout(processCaptchaPage, helpers.randomMs(1000, 3000));
return;
}
setTimeout(runCaptchaPage, helpers.randomMs(2000, 4000));
}
function processWithdraw() {
if(elements.modal()) {
setTimeout(waitForCaptcha, helpers.randomMs(2000, 4000));
return;
}
if (elements.openWithdrawModal()) { // 1. Click the Withdraw to FaucetPay submit button to open the modal w/the hCaptcha
elements.openWithdrawModal().click();
timeWaiting = 0;
setTimeout(processWithdraw, helpers.randomMs(2000, 4000));
return;
}
setTimeout(runWithdraw, helpers.randomMs(2000, 4000));
}
function waitForCaptcha() {
let iframe = document.querySelector('.h-captcha > iframe');
if (!iframe) {
iframe = document.querySelector('.g-recaptcha > iframe');
}
if(iframe && iframe.getAttribute('data-hcaptcha-response').length > 0) {
//claim after hCaptcha
if(elements.submitButton()) {
elements.submitButton().click(); // should redirect
return;
}
}
if (timedOut(5000)) {
return;
}
setTimeout(waitForCaptcha, helpers.randomMs(5000, 6000));
};
return {
init: init
};
},
createOkFaucetProcessor: function() {
let countdownMinutes;
let timeWaiting= 0;
let selectElement = {
addressInput: function() {
return document.querySelector('input[type="text"]');
},
rollButton: function() {
return document.querySelector('input[type="submit"');
},
countdown: function() { // "You have to wait\n60 minutes"
let successDivs = document.querySelectorAll(".alert.alert-success");
if(successDivs.length == 1 && successDivs[0].isVisible()) {
return parseInt(successDivs[0].innerText.replace(/\D/g, ''));
}
return null;
},
rolledNumber: function() {
let successDivs = document.querySelectorAll(".alert.alert-success");
if(successDivs && successDivs.length > 1 && successDivs[0].isVisible()) {
return parseInt(successDivs[0].innerText);
} else {
return null;
}
},
claimedAmount: function() {
let successDivs = document.querySelectorAll(".alert.alert-success");
if(successDivs && successDivs.length > 1 && successDivs[0].isVisible()) {
let val = parseInt(successDivs[1].innerText.replace(/\D/g, ''));
if (Number.isInteger(val)) {
val = val / 100000000;
}
return val;
} else {
return null;
}
},
error: function () {
let errorDiv = document.querySelector(".alert.alert-danger");
if(errorDiv) {
if (errorDiv.innerText.toLowerCase().includes('not have sufficient funds')) {
shared.closeWithError(ErrorType.NO_FUNDS, errorDiv.innerText);
} else {
shared.closeWithError(ErrorType.ERROR, errorDiv.innerText);
}
} else {
return null;
}
}
};
function timedOut(addMs) {
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return true;
}
timeWaiting += addMs;
return false;
}
function init() {
run();
}
function run() {
try {
setTimeout(findResultCountdownOrRollButton, helpers.randomMs(12000, 15000));
} catch (err) {
shared.closeWithErrors(ErrorType.ERROR, err);
}
};
function findResultCountdownOrRollButton() {
selectElement.error();
if ( selectElement.countdown() ) {
shared.devlog(`Ok: countdown found`);
timeWaiting = 0;
let result = {};
result.nextRoll = helpers.addMinutes(new Date(), selectElement.countdown().toString());
shared.closeWindow(result);
return;
}
if ( isRollButtonVisible() ) {
startRoll();
return;
}
if (selectElement.claimedAmount()) {
processRunDetails();
return;
}
setTimeout(findResultCountdownOrRollButton, helpers.randomMs(10000, 12000));
};
function startRoll() {
shared.devlog(`Ok: rollbutton found`);
let addressInput = selectElement.addressInput();
if (addressInput && addressInput.value != shared.getCurrent().params.address) {
addressInput.value = shared.getCurrent().params.address;
shared.devlog(`Ok: address filled`);
}
if (isHCaptchaVisible()) {
waitForCaptcha();
}
};
function isHCaptchaVisible() {
let hCaptchaFrame = document.querySelector('.h-captcha > iframe');
if (hCaptchaFrame && hCaptchaFrame.isVisible()) {
return true;
}
return false;
};
function isRollButtonVisible() {
let rollButton = selectElement.rollButton();
return rollButton && rollButton.isVisible();
};
function waitForCaptcha() {
if ( document.querySelector('.h-captcha > iframe').getAttribute('data-hcaptcha-response').length > 0) {
clickRoll();
} else {
if (timedOut(10000)) {
return;
}
setTimeout(waitForCaptcha, helpers.randomMs(10000, 12000));
}
};
function clickRoll() {
try {
shared.devlog('Clicking roll button');
selectElement.rollButton().click();
return;
} catch (err) {
shared.closeWithError(ErrorType.CLICK_ROLL_ERROR, err);
}
};
function processRunDetails() {
shared.devlog(`Ok: claimedAmount found`);
let claimedAmount = selectElement.claimedAmount();
let rolledNumber = selectElement.rolledNumber();
if (claimedAmount && rolledNumber) {
let result = {};
result.claimed = claimedAmount;
result.rolledNumber = rolledNumber;
result.nextRoll = helpers.addMinutes(new Date(), "60");
shared.closeWindow(result);
return;
}
if (timedOut(5000)) {
return;
}
setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
};
return {
init: init
};
},
createBigBtcProcessor: function() {
let countdownMinutes;
let timeWaiting= 0;
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);
if (Number.isInteger(val)) {
val = val / 100000000;
}
return val;
} else {
return null;
}
},
error: function () {
return null;
}
};
function timedOut(addMs) {
if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
shared.closeWithError(ErrorType.TIMEOUT, '');
return true;
}
timeWaiting += addMs;
return false;
}
function init() {
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(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() ) {
shared.devlog(`BigBtc: doing log in`);
doLogin();
return;
} else {
shared.devlog(`BigBtc: waiting for login form`);
if (timedOut(10000)) {
return;
}
}
setTimeout(waitIfLoading, helpers.randomMs(5000, 7000));
};
function runFaucet() {
let claimedAmount = selectElement.claimedAmount();
if(claimedAmount) {
processRunDetails();
return;
} else if (selectElement.countdown()) {
// need to wait
let result = {};
result.nextRoll = helpers.addMinutes(new Date(), shared.getConfig()['defaults.postponeMinutes']);
shared.closeWindow(result);
} else {
shared.devlog(`BigBtc: waiting for captcha`);
setTimeout(waitForCaptcha, helpers.randomMs(4000, 8000));
}
}
function waitForCaptcha() {
if ( document.querySelector('.h-captcha > iframe').getAttribute('data-hcaptcha-response').length > 0) {
clickClaim();
} else {
if (timedOut(10000)) {
return;
}
setTimeout(waitForCaptcha, helpers.randomMs(10000, 12000));
}
};
function clickClaim() {
try {
shared.devlog('Clicking roll button');
selectElement.claimButton().click();
return;
} catch (err) {
shared.closeWithError(ErrorType.CLICK_ROLL_ERROR, err);
}
};
function processRunDetails() {
shared.devlog(`BigBtc: processing results`);
let claimedAmount = selectElement.claimedAmount();
let balance = selectElement.balance();
let countdown = selectElement.countdown();
if (claimedAmount && balance) {
let result = {};
result.claimed = claimedAmount;
result.balance = balance;
result.nextRoll = helpers.addMinutes(new Date(), shared.getConfig()['defaults.postponeMinutes']);
shared.closeWindow(result);
return;
}
if (timedOut(5000)) {
return;
}
setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
};
return {
init: init
};
}
};
function overrideSelectNativeJS_Functions () {
window.alert = function alert (message) {
console.log (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 detectWeb() {
if(!shared.isOpenedByManager()) {
shared.devlog(`${window.location.href} dismissed`);
return;
}
shared.devlog(`${window.location.href} accepted`);
let typeFromManager = shared.getCurrent().type;
timer = new Timer(false, 10, typeFromManager);
switch( typeFromManager ) {
case WebType.STORMGAIN:
SiteProcessor = objectGenerator.createSGProcessor();
setTimeout(SiteProcessor.run, helpers.randomMs(10000, 20000));
break;
case WebType.CRYPTOSFAUCETS:
SiteProcessor = objectGenerator.createCFProcessor();
setTimeout(SiteProcessor.init, helpers.randomMs(1000, 3000));
break;
case WebType.FREEBITCOIN:
SiteProcessor = objectGenerator.createFBProcessor();
setTimeout(SiteProcessor.run, helpers.randomMs(2000, 5000));
break;
case WebType.FREELITECOIN: case WebType.FREEETHEREUMIO:
SiteProcessor = objectGenerator.createGenericFaucetProcessor(typeFromManager);
setTimeout(SiteProcessor.init, helpers.randomMs(2000, 5000));
break;
case WebType.BAGIKERAN:
SiteProcessor = objectGenerator.createBagiKeranProcessor();
setTimeout(SiteProcessor.init, helpers.randomMs(8000, 12000));
break;
case WebType.FAUCETPAY:
SiteProcessor = objectGenerator.createFPProcessor();
setTimeout(SiteProcessor.init, helpers.randomMs(2000, 5000));
break;
case WebType.OKFAUCET:
SiteProcessor = objectGenerator.createOkFaucetProcessor();
setTimeout(SiteProcessor.init, helpers.randomMs(4000, 6000));
break;
case WebType.BIGBTC:
SiteProcessor = objectGenerator.createBigBtcProcessor();
setTimeout(SiteProcessor.init, helpers.randomMs(4000, 6000));
break;
default:
break;
}
}
class Timer {
constructor(isManager, delaySeconds, webType) {
if(!useTimer || (webType && !Timer.webTypes().includes(webType))) {
return;
}
this.delay = delaySeconds * 1000;
if(!isManager) {
this.tick();
this.interval = setInterval(
() => { this.tick() }, this.delay);
}
}
static webTypes() { return [WebType.FREELITECOIN, WebType.FREEETHEREUMIO, WebType.BAGIKERAN, WebType.BIGBTC] };
startCheck(webType) {
if(!useTimer || (webType && !Timer.webTypes().includes(webType))) {
return;
}
persistence.save('lastAccess', Date.now());
this.interval = setInterval(
() => { this.isAlive() }, this.delay);
}
stopCheck() {
if(!useTimer) {
return;
}
clearInterval(timer.interval);
}
tick() {
if(!useTimer) {
return;
}
persistence.save('lastAccess', Date.now());
}
isAlive() {
if(!useTimer) {
return;
}
let now = Date.now();
let newAccess = persistence.load('lastAccess');
if(newAccess && (now - newAccess > this.delay)) {
//Close working tab and force restart
shared.devlog(`Timer is closing the working tab`);
shared.addError(ErrorType.FORCE_CLOSED, 'Site was unresponsive or redirected');
manager.closeWorkingTab();
}
}
}
let timer;
let useTimer = false; // ENABLE/DISABLE TIMER HERE
function init() {
persistence = objectGenerator.createPersistence();
shared = objectGenerator.createShared();
if(window.location.host === 'satology.onrender.com') {
timer = new Timer(true, 30);
shared.devlog('Manager Reloaded');
manager = objectGenerator.createManager();
CFPromotions = objectGenerator.createCFPromotions();
ui = objectGenerator.createUi();
CFHistory = objectGenerator.createCFHistory();
manager.init();
} else {
detectWeb();
}
}
init();
})();