17 faucets crypto bot & StormGain miner Trigger [$100 Per Year Or More]


SUBMITTED BY: PimpDaddy

DATE: July 2, 2021, 1:24 p.m.

UPDATED: July 2, 2021, 2:24 p.m.

FORMAT: Text only

SIZE: 81.3 kB

HITS: 1222

  1. SIgn Up TO facuets
  2. @note Links to create new accounts using my referral:
  3. // @note https://faucetpay.io/?r=1140585
  4. // @note https://freebitco.in/?r=46334826
  5. // @note https://app.stormgain.com/friend/BNS17722452
  6. // @note https://freecardano.com/?ref=346495
  7. // @note https://freebinancecoin.com/?ref=176633
  8. // @note https://freebitcoin.io/?ref=506599
  9. // @note https://freedash.io/?ref=132684
  10. // @note https://free-doge.com/?ref=199022
  11. // @note https://freeethereum.com/?ref=218020
  12. // @note https://freechainlink.io/?ref=84537
  13. // @note https://free-ltc.com/?ref=127524
  14. // @note https://freeneo.io/?ref=107888
  15. // @note https://freesteam.io/?ref=122086
  16. // @note https://free-tron.com/?ref=237317
  17. // @note https://freeusdcoin.com/?ref=139322
  18. // @note https://freetether.com/?ref=190533
  19. // @note https://freenem.com/?ref=300886
  20. // @note https://coinfaucet.io/?ref=822473
  21. OU MUST HAVE A hCaptcha solver INSTALLED to claim from the faucets
  22. // @note I recommend this script: https://greasyfork.org/en/scripts/425854-hcaptcha-solver-automatically-solves-hcaptcha-in-browser
  23. Download tampermoney plugin
  24. Create new scritp
  25. SAVE.
  26. Go To: https://satology.onrender.com/faucets/referrals
  27. Faucet bot starts working
  28. // ==UserScript==
  29. // @name [satology] Auto Claim Multiple Faucets with Monitor UI
  30. // @description Freebitco.in, StormGain Miner, 15 Faucets + Promo Codes + Autologin.
  31. // @description Automatic activation of StormGain Miner every 4 hours and hourly claim of free ADA, BNB, BTC, DASH, DOGE, ETH, LINK, LTC, NEO, STEAM, TRX, USDC, USDT, XEM, XRP
  32. // @version 1.1.4
  33. // @author satology
  34. // @namespace satology.onrender.com
  35. // @homepage https://satology.onrender.com/faucets/referrals
  36. // @note ----------------------------------------I M P O R T A N T---------------------------------------------------------------------------------------
  37. // @note YOU MUST HAVE A hCaptcha solver INSTALLED to claim from the faucets
  38. // @note I recommend this script: https://greasyfork.org/en/scripts/425854-hcaptcha-solver-automatically-solves-hcaptcha-in-browser
  39. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  40. // @note ---------------------------------------- LAST UPDATES ------------------------------------------------------------------------------------------
  41. // @note [@1.1.0] Added Freebitco.in and autologin for @cryptosfaucets
  42. // @note > You can enable autologin/credentials in the config object
  43. // @note > You can enable activation of daily RPBonus for FreeBitco.in in the config object
  44. // @note > Added boolean setToEnglish (DEFAULT TRUE) at localeConfig object, to change the language of the faucets to English.
  45. // @note ---------------------------------------- LAST UPDATES ------------------------------------------------------------------------------------------
  46. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  47. // @note MAIN FEATURES:
  48. // @note > Automatic hourly rolls for 16 faucets: Freebitco.in and @CryptosFaucets (ADA, BNB, BTC, DASH, DOGE, ETH, LINK, LTC, NEO, STEAM, TRX, USDC, USDT, XEM, XRP)
  49. // @note > Automatic activation of StormGain Miner (free BTC every 4 hours)
  50. // @note > Accepts promotion codes (http://twitter.com/cryptosfaucets, free roll shortlinks) for the 15 faucets
  51. // @note > Simple Monitor UI on top of a website to track progress (claims, next rolls, promo codes)
  52. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  53. // @note IMPORTANT CONSIDERATIONS:
  54. // @note 0. You need to enable popups on the Manager UI website to be able to open the faucets
  55. // @note 2. FAUCETS WEBSITES MUST OPEN IN ENGLISH TO BE ABLE TO RECOGNIZE IF THE PROMO CODE WAS ACCEPTED
  56. // @note In case you don't want to have them in English, you need to change the 3 strings the code uses for validation
  57. // @note (Search for localeStrings in the code and replace them)
  58. // @note 3. Autorolls will trigger ONLY when the faucet was opened by the Manager UI.
  59. // @note This is to allow users to navigate the websites to get the ShortLinks extra rolls, for example,
  60. // @note without having to stop the script.
  61. // @note 5. You can disable faucets from the script in case you need to or you are not registered yet.
  62. // @note It would be great if you could use my referral links listed below if you need an account.
  63. // @note To disable them, just set enabled: false in the webList array, save the script & refresh the manager
  64. // @note 6. All data stored for tracking and to be displayed is stored locally in your environment. Nothing is uploaded.
  65. // @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
  66. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  67. // @note ----------------------------------------I M P O R T A N T---------------------------------------------------------------------------------------
  68. // @note [@1.0.11] Modified timeouts and removed auto refresh. YOU MUST HAVE A hCaptcha solver INSTALLED to claim from the faucets now as they've added it and it's working.
  69. // @note I recommend this script: https://greasyfork.org/en/scripts/425854-hcaptcha-solver-automatically-solves-hcaptcha-in-browser
  70. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  71. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  72. // @note Requested for upcoming updates:
  73. // @note - Enable/Disable faucet from the Manager UI, add extra column with conversion
  74. // @note - Implement FaucetPay PTC autoclicker (https://faucetpay.io/?r=1140585)
  75. // @note - Add bagi.co.in
  76. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  77. // @note Links to create new accounts using my referral:
  78. // @note https://faucetpay.io/?r=1140585
  79. // @note https://freebitco.in/?r=46334826
  80. // @note https://app.stormgain.com/friend/BNS17722452
  81. // @note https://freecardano.com/?ref=346495
  82. // @note https://freebinancecoin.com/?ref=176633
  83. // @note https://freebitcoin.io/?ref=506599
  84. // @note https://freedash.io/?ref=132684
  85. // @note https://free-doge.com/?ref=199022
  86. // @note https://freeethereum.com/?ref=218020
  87. // @note https://freechainlink.io/?ref=84537
  88. // @note https://free-ltc.com/?ref=127524
  89. // @note https://freeneo.io/?ref=107888
  90. // @note https://freesteam.io/?ref=122086
  91. // @note https://free-tron.com/?ref=237317
  92. // @note https://freeusdcoin.com/?ref=139322
  93. // @note https://freetether.com/?ref=190533
  94. // @note https://freenem.com/?ref=300886
  95. // @note https://coinfaucet.io/?ref=822473
  96. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  97. // @note If you wanna team up or just share some ideas, you can contact me at satology@protonmail.com
  98. // @note ------------------------------------------------------------------------------------------------------------------------------------------------
  99. // @grant GM_setValue
  100. // @grant GM_getValue
  101. // @grant window.close
  102. // @grant GM_openInTab
  103. // @icon https://www.google.com/s2/favicons?domain=stormgain.com
  104. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
  105. // @match https://satology.onrender.com/faucets/referrals*
  106. // @match https://app.stormgain.com/crypto-miner/
  107. // @match https://freecardano.com/*
  108. // @match https://freebinancecoin.com/*
  109. // @match https://freebitcoin.io/*
  110. // @match https://freedash.io/*
  111. // @match https://free-doge.com/*
  112. // @match https://freeethereum.com/*
  113. // @match https://freechainlink.io/*
  114. // @match https://free-ltc.com/*
  115. // @match https://freeneo.io/*
  116. // @match https://freesteam.io/*
  117. // @match https://free-tron.com/*
  118. // @match https://freeusdcoin.com/*
  119. // @match https://freetether.com/*
  120. // @match https://freenem.com/*
  121. // @match https://coinfaucet.io/*
  122. // @match https://freebitco.in/
  123. // ==/UserScript==
  124. (function() {
  125. 'use strict';
  126. /**
  127. * Specific string values to check if a promotion code was succesfully processed (used via indexOf).
  128. * Defaults are set for English.
  129. * If you want to view the faucets in another language, you will need to change the following values
  130. */
  131. const localeConfig = {
  132. setToEnglish: true, // will set the faucets to English
  133. stringSearches: {
  134. promoCodeAccepted: 'roll',
  135. promoCodeUsed: 'already used',
  136. promoCodeInvalid: 'not found',
  137. promoCodeInvalid2: 'only alphanumeric',
  138. promoCodeInvalid3: 'ended'
  139. }
  140. };
  141. const WebType = {
  142. CRYPTOSFAUCETS: 1,
  143. STORMGAIN: 2,
  144. FREEBITCOIN: 3
  145. };
  146. const CFUrlType = {
  147. HOME: 0,
  148. FREE: 1,
  149. CONTACTTWITTER: 2,
  150. PROMOTION: 3,
  151. STATS: 4,
  152. SETTINGS: 5,
  153. FREEROLLS: 6,
  154. IGNORE: 99
  155. };
  156. const PromoStatus = {
  157. NOCODE: 0,
  158. PENDING: 1,
  159. ACCEPTED: 2,
  160. USEDBEFORE: 3,
  161. INVALID: 4,
  162. UNKNOWNERROR: 5
  163. };
  164. const RandomInteractionLevel = {
  165. NONE: 0,
  166. LOW: 1,
  167. MEDIUM: 2,
  168. HIGH: 3
  169. };
  170. let config = {
  171. timeout: 4, // Use -1 to disable the timeout functionality. In minutes. Max time the monitor will wait for a result/roll.
  172. // After timeout is reached, the Manager/Monitor will assume something is wrong
  173. // (usually faucet tab being accidentally closed or failed to connect)
  174. // Will trigger a refresh on the Monitor website and carry on the process
  175. postponeMinutes: 65, // Minutes to wait before retrying a faucet that timed out
  176. cf: {
  177. autologin: false,
  178. credentials: {
  179. mode: 1, // POSSIBLE VALUES:
  180. // 1: Use email/password saved through the script
  181. // 2: Waits for the credentials to be added manually or by a third party software/extension.
  182. // Useful if you use different email/password combinations on each faucet
  183. email: 'YOUR@EMAIL.com',
  184. password: 'YOURPASSWORD'
  185. }
  186. },
  187. fb: {
  188. activateRPBonus: false // will try to activate the highest RP Roll Bonus available for the account (100, 50 25, ... points per roll),
  189. }
  190. }
  191. let persistence, shared, manager, ui, CFPromotions, interactions, SGProcessor, CFProcessor, CFHistory, FBProcessor;
  192. let helpers = {
  193. cleanString: function(input) {
  194. var output = "";
  195. for (var i=0; i<input.length; i++) {
  196. if (input.charCodeAt(i) <= 127) {
  197. output += input.charAt(i);
  198. }
  199. }
  200. return output;
  201. },
  202. shuffle: function (array) {
  203. let currentIndex = array.length, temporaryValue, randomIndex;
  204. while (0 !== currentIndex) {
  205. randomIndex = Math.floor(Math.random() * currentIndex);
  206. currentIndex -= 1;
  207. temporaryValue = array[currentIndex];
  208. array[currentIndex] = array[randomIndex];
  209. array[randomIndex] = temporaryValue;
  210. }
  211. return array;
  212. },
  213. getPrintableTime: function (date = new Date()) {
  214. return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2) + ':' + ('0' + date.getSeconds()).slice(-2)
  215. },
  216. getPrintableDateTime: function (date) {
  217. if (date != null) {
  218. return ('0' + date.getDate()).slice(-2) + '/' + ('0' + (date.getMonth() + 1)).slice(-2) + ' ' + ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2);
  219. } else {
  220. return '';
  221. }
  222. },
  223. getEnumText: function (enm, value) {
  224. return Object.keys(enm).find(key => enm[key] === value);
  225. },
  226. randomMs: function (a, b){
  227. return a + (b - a) * Math.random();
  228. },
  229. addMinutes: function(date, mins) {
  230. return date.setMinutes(date.getMinutes() + parseInt(mins) + 1);
  231. },
  232. randomInt: function(min, max) {
  233. return Math.floor(Math.random() * (max - min + 1) + min);
  234. },
  235. addMilliseconds: function(date, ms) {
  236. return date.setMilliseconds(date.getMilliseconds() + ms);
  237. },
  238. getRandomMillisecondsFromMinutesRange(minute, rangeDiffInPercentage) {
  239. const msCenter = minute * 60 * 1000;
  240. const msRangeDiff = Math.round(msCenter * rangeDiffInPercentage / 100);
  241. return helpers.randomMs(msCenter - msRangeDiff, msCenter + msRangeDiff);
  242. },
  243. getEmojiForPromoStatus: function(promoStatus) {
  244. switch (promoStatus) {
  245. case PromoStatus.NOCODE:
  246. return '⚪';
  247. break;
  248. case PromoStatus.PENDING:
  249. return '⏳';
  250. break;
  251. case PromoStatus.ACCEPTED:
  252. return '✔️';
  253. break;
  254. case PromoStatus.USEDBEFORE:
  255. return '🕙';
  256. break;
  257. case PromoStatus.INVALID:
  258. return '❌';
  259. break;
  260. case PromoStatus.UNKNOWNERROR:
  261. return '❗';
  262. break;
  263. }
  264. },
  265. getHost: function(url, withHttps = false) {
  266. if (url.includes('//')) {
  267. url = url.split('//')[1];
  268. }
  269. url = url.split('/')[0];
  270. return withHttps ? ('https://' + url) : url;
  271. },
  272. cf: {
  273. getUrlType: function(url) {
  274. if (url.endsWith('/free')) {
  275. return CFUrlType.FREE;
  276. }
  277. if (url.includes('/promotion/')) {
  278. return CFUrlType.PROMOTION;
  279. }
  280. if (url.endsWith('/contact-twitter')) {
  281. return CFUrlType.CONTACTTWITTER;
  282. }
  283. if (url.endsWith('/free-rolls')) {
  284. return CFUrlType.FREEROLLS;
  285. }
  286. if (url.endsWith('/settings')) {
  287. return CFUrlType.SETTINGS;
  288. }
  289. if (url.endsWith('/stats')) {
  290. return CFUrlType.STATS;
  291. }
  292. if (url.endsWith('/')) {
  293. url = url.slice(0, -1);
  294. if (url == helpers.getHost(url, true)) {
  295. return CFUrlType.HOME;
  296. }
  297. }
  298. return CFUrlType.IGNORE;
  299. }
  300. }
  301. }
  302. let objectGenerator = {
  303. createPersistence: function() {
  304. const prefix = 'autoWeb_';
  305. function save(key, value, parseIt = false) {
  306. GM_setValue(prefix + key, parseIt ? JSON.stringify(value) : value);
  307. };
  308. function load(key, parseIt = false) {
  309. let value = GM_getValue(prefix + key);
  310. if(value && parseIt) {
  311. value = JSON.parse(value);
  312. }
  313. return value;
  314. };
  315. return {
  316. save: save,
  317. load: load
  318. };
  319. },
  320. createShared: function() {
  321. let flowControl;
  322. function isOpenedByManager(currentHost) {
  323. loadFlowControl();
  324. if(!flowControl) {
  325. return false;
  326. }
  327. let millisecondsDistance = new Date() - flowControl.requestedTime;
  328. // if(flowControl.opened || flowControl.host != currentHost || millisecondsDistance > 120000) {
  329. if(flowControl.opened || (flowControl.host != currentHost && !flowControl.expectedHosts.includes(currentHost)) || millisecondsDistance > 120000) {
  330. return false;
  331. }
  332. return true;
  333. };
  334. function setFlowControl(id, url, webType, expectedHosts) {
  335. flowControl = {
  336. id: id,
  337. url: url,
  338. host: helpers.getHost(url),
  339. type: webType,
  340. requestedTime: new Date(),
  341. opened: false,
  342. expectedHosts: expectedHosts,
  343. error: false,
  344. result: {}
  345. };
  346. persistence.save('flowControl', flowControl, true);
  347. };
  348. function wasVisited(expectedId) {
  349. loadFlowControl();
  350. return flowControl.id == expectedId && flowControl.opened;
  351. };
  352. function hasErrors(expectedId) {
  353. return flowControl.id == expectedId && flowControl.error;
  354. };
  355. function getResult() {
  356. return flowControl.result;
  357. };
  358. function getCurrent() {
  359. let current = {};
  360. current.url = flowControl.url;
  361. current.host = flowControl.host;
  362. current.type = flowControl.type;
  363. return current;
  364. };
  365. function saveAndclose(runDetails, delay = 0) {
  366. markAsVisited(runDetails);
  367. if(delay) {
  368. setTimeout(window.close, delay);
  369. } else {
  370. window.close();
  371. }
  372. };
  373. function loadFlowControl() {
  374. flowControl = persistence.load('flowControl', true);
  375. };
  376. function markAsVisited(runDetails) {
  377. flowControl.opened = true;
  378. flowControl.result = runDetails;
  379. persistence.save('flowControl', flowControl, true);
  380. };
  381. function closeWithError(errorType, errorMessage) {
  382. flowControl.error = true;
  383. flowControl.result = {
  384. errorType: errorType,
  385. errorMessage: errorMessage
  386. };
  387. persistence.save('flowControl', flowControl, true);
  388. window.close();
  389. };
  390. return {
  391. setFlowControl: setFlowControl,
  392. wasVisited: wasVisited,
  393. isOpenedByManager: isOpenedByManager,
  394. getCurrent: getCurrent,
  395. getResult: getResult,
  396. closeWindow: saveAndclose,
  397. closeWithError: closeWithError,
  398. hasErrors: hasErrors
  399. };
  400. },
  401. createManager: function() {
  402. let timestamp = null;
  403. let timeWaiting = 0;
  404. let promoInterval;
  405. let webList = [
  406. { id: '1', name: 'ADA', url: 'https://freecardano.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  407. { id: '2', name: 'BNB', url: 'https://freebinancecoin.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  408. { id: '3', name: 'BTC', url: 'https://freebitcoin.io/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  409. { id: '4', name: 'DASH', url: 'https://freedash.io/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  410. { id: '5', name: 'ETH', url: 'https://freeethereum.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  411. { id: '6', name: 'LINK', url: 'https://freechainlink.io/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  412. { id: '7', name: 'LTC', url: 'https://free-ltc.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  413. { id: '8', name: 'NEO', url: 'https://freeneo.io/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  414. { id: '9', name: 'STEAM', url: 'https://freesteam.io/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  415. { id: '10', name: 'TRX', url: 'https://free-tron.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  416. { id: '11', name: 'USDC', url: 'https://freeusdcoin.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  417. { id: '12', name: 'USDT', url: 'https://freetether.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  418. { id: '13', name: 'XEM', url: 'https://freenem.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  419. { id: '14', name: 'XRP', url: 'https://coinfaucet.io/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  420. { id: '15', name: 'StormGain', url: 'https://app.stormgain.com/crypto-miner/', type: WebType.STORMGAIN, enabled: true },
  421. { id: '16', name: 'DOGE', url: 'https://free-doge.com/free', type: WebType.CRYPTOSFAUCETS, enabled: true },
  422. { id: '17', name: 'FreeBitco.in', url: 'https://freebitco.in/', type: WebType.FREEBITCOIN, enabled: true }
  423. ];
  424. function start(){
  425. loader.initialize();
  426. ui.init(getCFlist());
  427. update();
  428. promoInterval = setInterval(manager.readNewPromoCode, 5000);
  429. setTimeout(manager.process, 10000);
  430. };
  431. let loader = function() {
  432. function initialize() {
  433. setTimestamp();
  434. initializeWebList();
  435. initializePromotions();
  436. initializeHistory();
  437. };
  438. function initializeWebList() {
  439. let storedData = persistence.load('webList', true);
  440. if(storedData) {
  441. let newOnes = addNewOnes(storedData);
  442. if (newOnes) {
  443. newOnes.forEach( function (element, idx, arr) {
  444. storedData.push(element);
  445. });
  446. }
  447. let disabledList = webList.filter( x => !x.enabled ).map( x => x.id );
  448. storedData.forEach( function (element, idx, arr) {
  449. arr[idx].nextRoll = element.nextRoll ? new Date(element.nextRoll) : new Date();
  450. arr[idx].enabled = !disabledList.includes(element.id);
  451. });
  452. webList = storedData;
  453. setup();
  454. } else {
  455. setup(true);
  456. }
  457. };
  458. function addNewOnes(storedData) {
  459. let allIds = webList.map( x => x.id );
  460. let storedIds = storedData.map( x => x.id );
  461. let newOnes = allIds.filter( x => !storedIds.includes(x) );
  462. return webList.filter( x => newOnes.includes(x.id) );
  463. };
  464. function initializePromotions() {
  465. let storedData = persistence.load('CFPromotions', true);
  466. if (storedData) {
  467. storedData.forEach( function (element, idx, arr) {
  468. arr[idx].added = new Date(element.added);
  469. arr[idx].statusPerFaucet.forEach( function (el, i, a) {
  470. a[i].execTimeStamp = (el.execTimeStamp != null) ? new Date(el.execTimeStamp) : null;
  471. });
  472. });
  473. CFPromotions.load(storedData);
  474. }
  475. };
  476. function initializeHistory() {
  477. CFHistory.initOrLoad();
  478. };
  479. function setTimestamp() {
  480. timestamp = new Date().getTime();
  481. persistence.save('timestamp', timestamp);
  482. };
  483. function removeDisabledFaucets() {
  484. webList = webList.filter(x => x.enabled);
  485. };
  486. function setup(reset = false) {
  487. removeDisabledFaucets();
  488. if(reset) {
  489. helpers.shuffle(webList);
  490. }
  491. let timeDistance = 0;
  492. webList.forEach( function (element, idx, arr) {
  493. if (reset || !element.lastClaim) {
  494. arr[idx].lastClaim = 0;
  495. }
  496. if (reset || !element.aggregate) {
  497. arr[idx].aggregate = 0;
  498. }
  499. if (reset || !element.balance) {
  500. arr[idx].balance = 0;
  501. }
  502. if (reset || !element.stats) {
  503. arr[idx].stats = {};
  504. }
  505. if (reset || !element.nextRoll) {
  506. timeDistance += helpers.randomMs(10000, 15000);
  507. arr[idx].nextRoll = new Date(helpers.addMilliseconds(new Date(), timeDistance));
  508. }
  509. });
  510. };
  511. return {
  512. initialize: initialize
  513. };
  514. }();
  515. function update(sortIt = true) {
  516. if(sortIt) {
  517. webList.sort((a,b) => a.nextRoll.getTime() - b.nextRoll.getTime());
  518. }
  519. persistence.save('webList', webList, true);
  520. ui.refresh(webList, CFPromotions.getAll());
  521. updateRollStatsSpan();
  522. };
  523. function process() {
  524. if(isObsolete()) {
  525. return;
  526. }
  527. if(webList[0].nextRoll.getTime() < (new Date()).getTime()) {
  528. ui.log(`Opening ${webList[0].name}`);
  529. open();
  530. } else {
  531. let timeUntilNext = webList[0].nextRoll.getTime() - (new Date()).getTime() + helpers.randomMs(1000, 2000);
  532. ui.log(`Waiting ${(timeUntilNext/1000/60).toFixed(2)} minutes...`);
  533. setTimeout(manager.process, timeUntilNext);
  534. }
  535. };
  536. function isObsolete() {
  537. let savedTimestamp = persistence.load('timestamp');
  538. if (savedTimestamp && savedTimestamp > timestamp) {
  539. ui.log('<b>STOPING EXECUTION!<b> A new Manager UI window was opened. Process should continue there');
  540. clearInterval(promoInterval);
  541. return true;
  542. }
  543. return false;
  544. };
  545. function open(promoCode) {
  546. let navUrl = webList[0].url;
  547. if(promoCode) {
  548. navUrl = getPromoUrl(promoCode);
  549. ui.log(`Opening ${webList[0].name} with Promo Code [${promoCode}]`);
  550. }
  551. let expectedHosts = [];
  552. expectedHosts.push((new URL(navUrl)).host);
  553. if(webList[0].type == webList[0].type == WebType.STORMGAIN) {
  554. expectedHosts.push((new URL('https://www.google.com').host));
  555. expectedHosts.push((new URL('https://www.recaptcha.net').host));
  556. }
  557. shared.setFlowControl(webList[0].id, navUrl, webList[0].type, expectedHosts);
  558. setTimeout(manager.resultReader, 15000);
  559. // GM_openInTab(navUrl, 'loadInBackground');
  560. GM_openInTab(navUrl, { active: false});
  561. };
  562. function getPromoUrl(promoCode) {
  563. let url = webList[0].url;
  564. url = url.slice(0, url.length - 4);
  565. return url + "promotion/" + promoCode;
  566. }
  567. function resultReader() {
  568. if(isObsolete()) {
  569. return;
  570. }
  571. if(shared.wasVisited(webList[0].id)) {
  572. timeWaiting = 0;
  573. let result = shared.getResult();
  574. if (result) {
  575. updateWebListItem(result);
  576. if ( (webList[0].type == WebType.CRYPTOSFAUCETS) &&
  577. ( (result.claimed) || (result.promoStatus && result.promoStatus != PromoStatus.ACCEPTED) )) {
  578. let promoCode = CFPromotions.hasPromoAvailable(webList[0].id);
  579. if (promoCode) {
  580. update(false);
  581. open(promoCode);
  582. return;
  583. }
  584. }
  585. } else {
  586. ui.log(`Unable to read last run result, for ID: ${webList[0].id} > ${webList[0].name}`);
  587. }
  588. update(true);
  589. process();
  590. return;
  591. } else {
  592. timeWaiting += 15;
  593. if (!shared.hasErrors(webList[0].id) && !hasTimedOut()) {
  594. ui.log(`Waiting for ${webList[0].name} results...`, timeWaiting);
  595. setTimeout(manager.resultReader, 15000);
  596. return;
  597. // Handle Error
  598. let errorDetails = shared.getResult();
  599. ui.log(`${webList[0].name} closed with error: ${errorDetails.errorType} ${errorDetails.errorMessage}`);
  600. let millisecondsDelay = helpers.getRandomMillisecondsFromMinutesRange(config.postponeMinutes, 5);
  601. webList[0].nextRoll = new Date(helpers.addMilliseconds(new Date(), millisecondsDelay));
  602. update(true);
  603. window.location.reload();
  604. return;
  605. }
  606. if (shared.hasErrors(webList[0].id)) {
  607. webList[0].stats.errors = shared.getResult();
  608. ui.log(`${webList[0].name} closed with error: ${webList[0].stats.errors.errorType} ${webList[0].stats.errors.errorMessage}`);
  609. }
  610. if (hasTimedOut()) {
  611. if(webList[0].stats.countTimeouts) {
  612. webList[0].stats.countTimeouts += 1;
  613. } else {
  614. webList[0].stats.countTimeouts = 1;
  615. }
  616. ui.log(`Waited too much time for ${webList[0].name} results: triggering timeout`);
  617. }
  618. let millisecondsDelay = helpers.getRandomMillisecondsFromMinutesRange(config.postponeMinutes, 5);
  619. webList[0].nextRoll = new Date(helpers.addMilliseconds(new Date(), millisecondsDelay));
  620. update(true);
  621. window.location.reload();
  622. return;
  623. }
  624. };
  625. function hasTimedOut() {
  626. return config.timeout != -1 && (timeWaiting > (config.timeout * 60));
  627. };
  628. function updateWebListItem(result) {
  629. ui.log(`Updating data: ${JSON.stringify(result)}`);
  630. webList[0].stats.countTimeouts = 0;
  631. webList[0].stats.errors = null;
  632. if (result.claimed) {
  633. result.claimed = parseFloat(result.claimed);
  634. if(!isNaN(result.claimed)) {
  635. webList[0].lastClaim = result.claimed;
  636. webList[0].aggregate += result.claimed;
  637. }
  638. }
  639. if(result.balance) {
  640. webList[0].balance = result.balance;
  641. }
  642. if(result.nextRoll) {
  643. webList[0].nextRoll = new Date(result.nextRoll);
  644. }
  645. if(result.promoStatus) {
  646. CFPromotions.updateFaucetForCode(result.promoCode, webList[0].id, result.promoStatus);
  647. }
  648. if(result.rolledNumber) {
  649. CFHistory.addRoll(result.rolledNumber);
  650. }
  651. };
  652. function readNewPromoCode() {
  653. let promoCodeElement = $('#promo-code-new')[0];
  654. let promoCode = helpers.cleanString(promoCodeElement.innerText);
  655. let promoDisplayStatus = $('#promo-display-status')[0];
  656. if (promoCode == 'REMOVEALLPROMOS' ) {
  657. CFPromotions.removeAll();
  658. promoCodeElement.innerText = '';
  659. promoDisplayStatus.innerHTML = 'Promo codes removed!';
  660. ui.refresh(null, CFPromotions.getAll());
  661. } else if(promoCode != '') {
  662. CFPromotions.addNew(promoCode);
  663. promoCodeElement.innerText = '';
  664. $('#promo-text-input').val('');
  665. promoDisplayStatus.innerHTML = 'Code ' + promoCode + ' added!';
  666. ui.log(`Promo code ${promoCode} added`);
  667. ui.refresh(null, CFPromotions.getAll());
  668. }
  669. };
  670. function updateRollStatsSpan() {
  671. let rollsSpanElement = $('#rolls-span')[0];
  672. rollsSpanElement.innerText = CFHistory.getRollsMeta().join(',');
  673. };
  674. function getCFlist() {
  675. let items;
  676. items = webList.filter(f => f.type === WebType.CRYPTOSFAUCETS);
  677. items = items.map(x => {
  678. return {
  679. id: x.id,
  680. name: x.name
  681. };});
  682. items.sort((a, b) => (a.name > b.name) ? 1 : -1);
  683. return items;
  684. };
  685. return{
  686. init:start,
  687. process: process,
  688. resultReader: resultReader,
  689. getFaucetsForPromotion: getCFlist,
  690. readNewPromoCode: readNewPromoCode
  691. };
  692. },
  693. createUi: function() {
  694. let logLines = ['', '', '', '', ''];
  695. function init(cfFaucets) {
  696. appendCSS();
  697. appendJavaScript();
  698. appendHtml();
  699. createPromoTable(cfFaucets);
  700. };
  701. function appendCSS() {
  702. let css = '';
  703. $('head').append(css);
  704. };
  705. function appendJavaScript() {
  706. let js = '';
  707. js += '<script language="text/javascript">';
  708. js += 'var myBarChart;';
  709. js += 'function savePromoCode() {';
  710. js += 'var promoText = document.getElementById("promo-text-input");';
  711. js += 'var promoCode = document.getElementById("promo-code-new");';
  712. js += 'var promoDisplayStatus = document.getElementById("promo-display-status");';
  713. js += 'promoCode.innerHTML = promoText.value.trim();';
  714. js += 'promoDisplayStatus.innerHTML = "Adding code&nbsp&quot;<b>" + promoCode.innerHTML + "</b>&quot;... This could take around a minute. Please wait..."';
  715. js += '}';
  716. js += 'function removeAllPromos() {';
  717. js += 'var promoCode = document.getElementById("promo-code-new");';
  718. js += 'var promoDisplayStatus = document.getElementById("promo-display-status");';
  719. js += 'promoCode.innerHTML = "REMOVEALLPROMOS";';
  720. js += 'promoDisplayStatus.innerHTML = "Removing all promotion codes... This could take around a minute. Please wait..."';
  721. js += '}';
  722. js += 'function openStatsChart() {';
  723. js += 'if(myBarChart) { myBarChart.destroy(); }';
  724. js += 'let statsFragment = document.getElementById("stats-fragment");';
  725. js += 'if (statsFragment.style.display === "block") { statsFragment.style.display = "none"; document.getElementById("stats-button").innerText = "Lucky Number Stats"; } else {';
  726. js += 'statsFragment.style.display = "block"; document.getElementById("stats-button").innerText = "Close Stats";';
  727. js += 'var canvas = document.getElementById("barChart");';
  728. js += 'var ctx = canvas.getContext("2d");';
  729. js += 'var dataSpan = document.getElementById("rolls-span");';
  730. js += 'var data = {';
  731. js += 'labels: ["0000-9885", "9886-9985", "9986-9993", "9994-9997", "9998-9999", "10000"],';
  732. js += 'datasets: [ { fill: false, backgroundColor: [ "#990000", "#660066", "#000099", "#ff8000", "#ffff00", "#00ff00"],';
  733. js += 'data: dataSpan.innerText.split(",") } ] };';
  734. js += 'var options = { plugins: { legend: { display: false } }, title: { display: true, text: "Rolled Numbers", position: "top" }, rotation: -0.3 * Math.PI };';
  735. js += 'myBarChart = new Chart(ctx, { type: "pie", data: data, options: options }); } }';
  736. js += '</script>';
  737. $('head').append(js);
  738. };
  739. function appendHtml() {
  740. let html ='';
  741. html += '<pre style="width:100%;" id="console-log"><b>Loading...</b></pre>';
  742. html += '<section id="stats-fragment" class="fragment" style="display:none;"><div class="container-fluid bg-dark "><div class="container py-1 "><div class="row align-items-center text-center justify-content-center">';
  743. html += '<div class="col-md-3"><canvas id="barChart"></canvas><span id="rolls-span" style="display:none;"></span></div></div></div></div></div></section>';
  744. 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>';
  745. html += '<div class="title col-6 w-100 text-white"></div><div class="title col-3 text-right"><a class="btn m-2 anchor btn-outline-primary" id="stats-button" onclick="openStatsChart()">Lucky Number Stats</a></div></div>';
  746. html += '<div class="row align-items-center text-center justify-content-end">';
  747. 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></section>';
  748. html +='<section id="table-struct-promo" class="fragment "><div class="container-fluid bg-dark "><div class="container py-1 "><div class="row mx-0">';
  749. html +='<div class="title col-3 px-0 text-white"><h2>Promo Codes</h2></div><div class="title col-3 w-100 text-white">';
  750. html +='<div class="input-group my-0"><input type="text" class="form-control py-1" id="promo-text-input" placeholder="Type a Promo code...">';
  751. html +='<div class="input-group-append"><button class="btn btn-success" id="promo-button" onclick="savePromoCode()"><i class="fa fa-plus"></i></button>';
  752. html +='</div></div></div><div class="title col-4 text-white justify-content-end"><span id="promo-display-status" class="text-white"></span>';
  753. 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>';
  754. html +='</div></div><div class="row align-items-center text-center justify-content-end"><div class="col-12 order-lg-1 text-center">';
  755. html +='<div class="row justify-content-center"><div class="col table-responsive" id="promo-container"></div></div></div></div></div></div></section>';
  756. $('#referral-table').before(html);
  757. $('#schedule-container').append( createScheduleTable() );
  758. };
  759. function createPromoTable(faucets) {
  760. let tableStructure = '';
  761. tableStructure += '<table class="table table-bordered text-white" id="promo-table">';
  762. tableStructure += '<caption style="text-align: -webkit-center;">⏳ Pending ✔️ Accepted 🕙 Used Before ❌ Invalid code ❗ Unknown error ⚪ No code</caption>';
  763. tableStructure += '<thead><tr><th class="">Code</th><th class="">Added</th>';
  764. for (let i = 0, all = faucets.length; i < all; i++) {
  765. tableStructure += '<th data-faucet-id="' + faucets[i].id + '">' + faucets[i].name + '</th>';
  766. }
  767. tableStructure += '</tr></thead><tbody id="promo-table-body"></tbody></table>';
  768. $('#promo-container').append( tableStructure );
  769. };
  770. function createScheduleTable() {
  771. let tableStructure = '';
  772. tableStructure += '<table class="table table-bordered text-white" id="schedule-table"><thead><tr>';
  773. tableStructure += '<th class="hide-on-mobile">#</th><th class="">Name</th><th class="">Last Claim</th>';
  774. tableStructure += '<th class="hide-on-mobile">Aggregate</th><th class="hide-on-mobile">Balance</th><th class="">Next Roll</th>';
  775. tableStructure += '</tr></thead><tbody id="schedule-table-body"></tbody></table>';
  776. return tableStructure;
  777. };
  778. function loadScheduleTable(data) {
  779. let tableBody = '';
  780. for(let i=0, all = data.length; i < all; i++) {
  781. tableBody += '<tr class="align-middle" data-id="' + data[i].id + '">';
  782. tableBody +='<td class="align-middle hide-on-mobile">' + (i + 1).toString() + '</td>';
  783. tableBody +='<td class="align-middle">' + data[i].name + '</td>';
  784. tableBody +='<td class="align-middle">' + data[i].lastClaim.toFixed(8) + '</td>';
  785. tableBody +='<td class="align-middle hide-on-mobile">' + data[i].aggregate.toFixed(8) + '</td>';
  786. tableBody +='<td class="align-middle hide-on-mobile">' + (data[i].balance ? data[i].balance.split(' ')[0] : "") + '</td>';
  787. tableBody +='<td class="align-middle">' + helpers.getPrintableTime(data[i].nextRoll) + addBadges(data[i].stats) + '</td>';
  788. tableBody +='</tr>';
  789. }
  790. $('#schedule-table-body').html(tableBody);
  791. };
  792. function addBadges(stats) {
  793. let consecutiveTimeout = stats.countTimeouts;
  794. let otherErrors = stats.errors;
  795. let html = ' ';
  796. if (consecutiveTimeout) {
  797. html += `<span class="badge badge-pill badge-warning" title="${consecutiveTimeout} consecutive timeouts">${consecutiveTimeout}</span>`;
  798. }
  799. if (otherErrors) {
  800. html += `<span class="badge badge-pill badge-warning" title="${otherErrors.errorMessage}">${otherErrors.errorType}</span>`;
  801. }
  802. return html;
  803. }
  804. function loadPromotionTable(codes) {
  805. let tableBody = '';
  806. for(let c=0; c < codes.length; c++) {
  807. let data = codes[c];
  808. tableBody += '<tr data-promotiobn-id="' + data.id + '">';
  809. tableBody += '<td class="align-middle">' + data.code + '</td>';
  810. tableBody +='<td class="align-middle">' + helpers.getPrintableDateTime(data.added) + '</td>';
  811. for(let i=0, all = data.statusPerFaucet.length; i < all; i++) {
  812. tableBody +='<td class="align-middle" title="Runned @' + helpers.getPrintableDateTime(data.statusPerFaucet[i].execTimeStamp) + '">' + helpers.getEmojiForPromoStatus(data.statusPerFaucet[i].status ?? 0) + '</td>';
  813. }
  814. tableBody +='</tr>';
  815. }
  816. $('#promo-table-body').html(tableBody);
  817. };
  818. function refresh(scheduleData, promotionData) {
  819. if (scheduleData) {
  820. loadScheduleTable(scheduleData);
  821. }
  822. if (promotionData) {
  823. loadPromotionTable(promotionData);
  824. }
  825. };
  826. function log(msg, elapsed = false) {
  827. if(msg) {
  828. let previous = logLines[0].split('&nbsp')[1];
  829. if(elapsed && (previous == msg)) {
  830. logLines[0] = helpers.getPrintableTime() + '&nbsp' + msg + '&nbsp[Elapsed time:&nbsp' + elapsed + '&nbspseconds]';
  831. } else {
  832. logLines.pop();
  833. logLines.unshift(helpers.getPrintableTime() + '&nbsp' + msg);
  834. }
  835. $('#console-log').html(logLines.join('<br>'));
  836. }
  837. };
  838. return {
  839. init: init,
  840. refresh: refresh,
  841. loadPromotionTable: loadPromotionTable,
  842. log: log
  843. }
  844. },
  845. createCFPromotions: function() {
  846. let codes = [];
  847. function PromotionCode(id, code, repeatDaily = false) {
  848. this.id = id;
  849. this.code = code;
  850. this.added = new Date();
  851. this.statusPerFaucet = [];
  852. this.repeatDaily = repeatDaily;
  853. this.lastExecTimeStamp = null;
  854. };
  855. function getFaucetStatusInPromo(promo, faucetId) {
  856. let faucet = promo.statusPerFaucet.find(x => x.id == faucetId);
  857. return faucet.status ?? PromoStatus.NOCODE;
  858. };
  859. function addNew(code) {
  860. let newPromo = new PromotionCode(codes.length, code);
  861. newPromo.statusPerFaucet = manager.getFaucetsForPromotion();
  862. newPromo.statusPerFaucet.forEach(function (element, idx, arr) {
  863. arr[idx].status = PromoStatus.PENDING;
  864. arr[idx].execTimeStamp = null;
  865. });
  866. codes.push(newPromo);
  867. codes.sort((a, b) => (a.id < b.id) ? 1 : -1);
  868. save();
  869. };
  870. function getAll() {
  871. return codes;
  872. };
  873. function updateFaucetForCode(code, faucetId, newStatus) {
  874. let promo = codes.find(x => x.code == code);
  875. let faucet = promo.statusPerFaucet.find(x => x.id == faucetId);
  876. if(faucet) {
  877. faucet.status = newStatus;
  878. faucet.execTimeStamp = new Date();
  879. promo.lastExecTimeStamp = faucet.execTimeStamp;
  880. }
  881. save();
  882. };
  883. function hasPromoAvailable(faucetId) {
  884. let resp = false;
  885. codes.forEach(function (promotion, idx, arr) {
  886. let status = getFaucetStatusInPromo(promotion, faucetId);
  887. if (status == PromoStatus.PENDING) {
  888. resp = promotion.code;
  889. return;
  890. }
  891. });
  892. return resp;
  893. };
  894. function save() {
  895. persistence.save('CFPromotions', getAll(), true);
  896. };
  897. function load(data) {
  898. codes = data;
  899. };
  900. function removeAll() {
  901. codes = [];
  902. save();
  903. };
  904. return {
  905. addNew: addNew,
  906. removeAll: removeAll,
  907. getAll: getAll,
  908. load: load,
  909. updateFaucetForCode: updateFaucetForCode,
  910. hasPromoAvailable: hasPromoAvailable
  911. }
  912. },
  913. createInteractions: function(){
  914. let randomInteractionLevel = RandomInteractionLevel.MEDIUM;
  915. let maxActions = 0;
  916. let performedActions = -1;
  917. let selectableElements;
  918. let actions = {
  919. available: [
  920. function() {
  921. $('html, body').animate({
  922. scrollTop: helpers.randomInt(0, $('html, body').get(0).scrollHeight)
  923. }, {
  924. complete: setTimeout(interactions.addPerformed, helpers.randomMs(100, 3000)),
  925. duration: helpers.randomMs(100, 1500)
  926. });
  927. },
  928. function() {
  929. let element = interactions.selectableElements[helpers.randomInt(0, interactions.selectableElements.length - 1)];
  930. try {
  931. if (document.body.createTextRange) {
  932. const range = document.body.createTextRange();
  933. range.moveToElementText(element);
  934. range.select();
  935. } else if (window.getSelection) {
  936. const selection = window.getSelection();
  937. const range = document.createRange();
  938. range.selectNodeContents(element);
  939. selection.removeAllRanges();
  940. selection.addRange(range);
  941. }
  942. } catch (err) { }
  943. interactions.addPerformed();
  944. }
  945. ]
  946. };
  947. function start(selectableElements) {
  948. performedActions = 0;
  949. switch(randomInteractionLevel) {
  950. case RandomInteractionLevel.NONE:
  951. maxActions = 0;
  952. break;
  953. case RandomInteractionLevel.LOW:
  954. maxActions = helpers.randomInt(2, 4);
  955. break;
  956. case RandomInteractionLevel.MEDIUM:
  957. maxActions = helpers.randomInt(5, 8);
  958. break;
  959. case RandomInteractionLevel.HIGH:
  960. maxActions = helpers.randomInt(12, 16);
  961. break;
  962. }
  963. interactions.selectableElements = selectableElements;
  964. performActions();
  965. }
  966. function performActions() {
  967. if(performedActions >= maxActions) {
  968. return;
  969. }
  970. let delay = 0;
  971. for(let i = 0; i < maxActions; i++) {
  972. delay += helpers.randomMs(350, 1500);
  973. setTimeout(actions.available[helpers.randomInt(0, actions.available.length - 1)], delay);
  974. }
  975. }
  976. function addPerformed() {
  977. performedActions++;
  978. }
  979. function completed() {
  980. return (performedActions >= maxActions);
  981. }
  982. return {
  983. start: start,
  984. completed: completed,
  985. addPerformed: addPerformed,
  986. selectableElements: selectableElements
  987. };
  988. },
  989. createSGProcessor: function() {
  990. let timerSpans;
  991. function run() {
  992. if(isLoading()) {
  993. setTimeout(SGProcessor.run, helpers.randomMs(5000, 10000));
  994. return;
  995. } else {
  996. if(isMinerActive()) {
  997. processRunDetails();
  998. } else {
  999. activateMiner();
  1000. }
  1001. }
  1002. };
  1003. function isLoading() {
  1004. return $('#loader-logo').length;
  1005. };
  1006. function isMinerActive() {
  1007. timerSpans = $('.mb-8 .wrapper .mb-1 span');
  1008. if(timerSpans.length > 0) {
  1009. return true;
  1010. } else {
  1011. return false;
  1012. }
  1013. return (timerSpans.length === 0);
  1014. };
  1015. function activateMiner() {
  1016. const activateButton = document.querySelector('.mb-8 .wrapper button');
  1017. if (activateButton) {
  1018. activateButton.click();
  1019. setTimeout(SGProcessor.processRunDetails, helpers.randomMs(10000, 20000));
  1020. } else {
  1021. if(!is404Error()) {
  1022. SGProcessor.processRunDetails()
  1023. }
  1024. }
  1025. };
  1026. function is404Error() {
  1027. const h1 = document.getElementsByTagName('h1');
  1028. if (h1.length > 0 && h1[0].innerText.includes('404')) {
  1029. window.location.reload();
  1030. return true;
  1031. }
  1032. return false;
  1033. }
  1034. function processRunDetails() {
  1035. let result = {};
  1036. result.nextRoll = helpers.addMinutes(new Date(), readCountdown().toString());
  1037. result.balance = readBalance();
  1038. shared.closeWindow(result);
  1039. };
  1040. function readCountdown() {
  1041. let mins = 15;
  1042. try {
  1043. let timeLeft = timerSpans.last().text().split(':');
  1044. if(timeLeft.length === 3) {
  1045. mins = parseInt(timeLeft[0]) * 60 + parseInt(timeLeft[1]);
  1046. }
  1047. } catch (err) { }
  1048. return mins;
  1049. };
  1050. function readBalance() {
  1051. let balance = "";
  1052. try {
  1053. balance = $('span.text-accent').first().text() + " BTC";
  1054. } catch (err) { }
  1055. return balance;
  1056. };
  1057. return {
  1058. run: run,
  1059. processRunDetails: processRunDetails
  1060. };
  1061. },
  1062. createCFProcessor: function() {
  1063. const NavigationProcess = {
  1064. ROLLING: 1,
  1065. PROCESSING_PROMOTION: 2,
  1066. LOGIN: 3
  1067. };
  1068. let navigationProcess;
  1069. let countdown;
  1070. let rollButton;
  1071. let promotionTag;
  1072. let timeWaiting= 0;
  1073. let loopingForErrors = false;
  1074. function run() {
  1075. navigationProcess = NavigationProcess.ROLLING;
  1076. displayStatusUi();
  1077. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
  1078. };
  1079. function doLogin() {
  1080. navigationProcess = NavigationProcess.LOGIN;
  1081. displayStatusUi();
  1082. setTimeout(findLoginForm, helpers.randomMs(2000, 5000));
  1083. };
  1084. function isFullyLoaded() { //Waits 55 seconds max
  1085. if(document.readyState == 'complete' || timeWaiting == -1) {
  1086. $('#process-status')[0].innerHTML = 'Interacting';
  1087. timeWaiting = 0;
  1088. interact();
  1089. } else {
  1090. timeWaiting = -1;
  1091. $('#process-status')[0].innerHTML = 'Waiting for document fully loaded';
  1092. setTimeout(CFProcessor.isFullyLoaded, helpers.randomMs(45000, 55000));
  1093. }
  1094. };
  1095. function runPromotion() {
  1096. navigationProcess = NavigationProcess.PROCESSING_PROMOTION
  1097. displayStatusUi();
  1098. setTimeout(CFProcessor.findPromotionTag, helpers.randomMs(1000, 3000));
  1099. };
  1100. function findCountdownOrRollButton() {
  1101. if( isCountdownVisible() && !isRollButtonVisible() ) {
  1102. timeWaiting = 0;
  1103. processRunDetails();
  1104. } else if ( !isCountdownVisible() && isRollButtonVisible() ) {
  1105. timeWaiting = 0;
  1106. setTimeout(CFProcessor.isFullyLoaded, helpers.randomMs(1000, 5000));
  1107. } else {
  1108. if (timeWaiting/1000 > config.timeout * 60) {
  1109. shared.closeWithError('TIMEOUT', '');
  1110. return;
  1111. }
  1112. timeWaiting += 3000;
  1113. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
  1114. }
  1115. };
  1116. function findLoginForm() {
  1117. if ( $('div.login-wrapper').is(':visible') ) {
  1118. //Other possible error is if recaptcha did not load yet... so maybe wait til the web is fully loaded for low connection issues
  1119. if( $('.login-wrapper .error').length > 0 && $('.login-wrapper .error')[0].innerHTML != '') {
  1120. let errorMessage = $('.login-wrapper .error').text();
  1121. shared.closeWithError('LOGIN_ERROR', errorMessage);
  1122. return;
  1123. }
  1124. if(!loopingForErrors) {
  1125. if(config.cf.credentials.mode == 1) {
  1126. timeWaiting = 0;
  1127. $('.login-wrapper input[name="email"]').val(config.cf.credentials.email);
  1128. $('.login-wrapper input[name="password"]').val(config.cf.credentials.password);
  1129. $('.login-wrapper button.login').click();
  1130. loopingForErrors = true;
  1131. } else {
  1132. if($('.login-wrapper input[name="email"]').val() != '' && $('.login-wrapper input[name="password"]').val() != '') {
  1133. $('.login-wrapper button.login').click();
  1134. $('#process-status')[0].innerHTML = 'Processing';
  1135. loopingForErrors = true;
  1136. } else {
  1137. $('#process-status')[0].innerHTML = 'Waiting for credentials...';
  1138. if (timeWaiting/1000 > (config.timeout / 1.5) * 60) {
  1139. shared.closeWithError('LOGIN_ERROR', 'No credentials were provided');
  1140. return;
  1141. }
  1142. }
  1143. }
  1144. }
  1145. }
  1146. if (timeWaiting/1000 > config.timeout * 60) {
  1147. shared.closeWithError('TIMEOUT', '');
  1148. return;
  1149. }
  1150. timeWaiting += 3000;
  1151. setTimeout(findLoginForm, helpers.randomMs(2000, 5000));
  1152. };
  1153. function interact() {
  1154. let selectables = []
  1155. selectables = selectables.concat($('td').toArray());
  1156. selectables = selectables.concat($('p').toArray());
  1157. selectables = selectables.concat($('th').toArray());
  1158. interactions.start(selectables);
  1159. setTimeout(CFProcessor.waitInteractions, helpers.randomMs(2000, 4000));
  1160. }
  1161. function waitInteractions() {
  1162. if(interactions.completed()) {
  1163. roll();
  1164. } else {
  1165. setTimeout(CFProcessor.waitInteractions, helpers.randomMs(2000, 4000));
  1166. }
  1167. }
  1168. function isCountdownVisible() {
  1169. countdown = $('.timeout-wrapper');
  1170. return ($(countdown).length > 0 && $(countdown[0]).is(':visible'));
  1171. };
  1172. function isRollButtonVisible() {
  1173. rollButton = $('.main-button-2.roll-button.bg-2');
  1174. return ($(rollButton).length > 0 && $(rollButton[0]).is(':visible'));
  1175. };
  1176. function roll() {
  1177. $('#process-status')[0].innerHTML = 'Roll triggered';
  1178. $(rollButton[0]).click();
  1179. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 3000));
  1180. }
  1181. function isPromotionTagVisible() {
  1182. let pTags = $('p');
  1183. if (pTags.length > 0) {
  1184. promotionTag = $('p')[0];
  1185. return true;
  1186. }
  1187. return false;
  1188. };
  1189. function findPromotionTag() {
  1190. if( isPromotionTagVisible() ) {
  1191. processRunDetails();
  1192. } else {
  1193. setTimeout(CFProcessor.findPromotionTag, helpers.randomMs(2000, 5000));
  1194. }
  1195. };
  1196. function processRunDetails() {
  1197. let result = {};
  1198. if(navigationProcess == NavigationProcess.ROLLING) {
  1199. result.nextRoll = readCountdown();
  1200. result.claimed = readClaimed();
  1201. result.balance = readBalance();
  1202. if(result.claimed != 0) {
  1203. result.rolledNumber = readRolledNumber();
  1204. }
  1205. result.balance = readBalance();
  1206. } else if (navigationProcess == NavigationProcess.PROCESSING_PROMOTION) {
  1207. result.promoStatus = readPromoStatus();
  1208. result.promoCode = readPromoCode();
  1209. if (result.promoStatus == PromoStatus.ACCEPTED) {
  1210. result.nextRoll = helpers.addMinutes(new Date(), "-120");
  1211. }
  1212. }
  1213. shared.closeWindow(result);
  1214. };
  1215. function readCountdown() {
  1216. let minsElement = $('.timeout-container .minutes .digits');
  1217. let mins = "0";
  1218. if ($(minsElement).length > 0) {
  1219. mins = $(minsElement)[0].innerHTML;
  1220. }
  1221. if (mins) {
  1222. return helpers.addMinutes(new Date(), mins.toString());
  1223. } else {
  1224. return null;
  1225. }
  1226. };
  1227. function readClaimed() {
  1228. let claimed = 0;
  1229. try {
  1230. claimed = $('.result')[0].innerHTML;
  1231. claimed = claimed.trim();
  1232. claimed = claimed.slice(claimed.lastIndexOf(" ") + 1);
  1233. } catch(err) { }
  1234. return claimed;
  1235. };
  1236. function readRolledNumber() {
  1237. let number = 0;
  1238. try {
  1239. number = $('.lucky-number').toArray().map(x => x.innerText).join('');
  1240. number = parseInt(number);
  1241. } catch(err) { }
  1242. return number;
  1243. };
  1244. function readBalance() {
  1245. let balance = "";
  1246. try {
  1247. balance = $('.navbar-coins.bg-1 a').first().text();
  1248. } catch(err) { }
  1249. return balance;
  1250. };
  1251. function readPromoStatus() {
  1252. let promoStatus = PromoStatus.UNKNOWNERROR;
  1253. try {
  1254. if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeAccepted) > 0) {
  1255. return PromoStatus.ACCEPTED;
  1256. } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeUsed) > 0) {
  1257. return PromoStatus.USEDBEFORE;
  1258. } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeInvalid) > 0) {
  1259. return PromoStatus.INVALID;
  1260. } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeInvalid2) > 0) {
  1261. return PromoStatus.INVALID;
  1262. } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeInvalid3) > 0) {
  1263. return PromoStatus.INVALID;
  1264. }
  1265. } catch ( err ) { }
  1266. return promoStatus;
  1267. };
  1268. function validatePromoString() {
  1269. };
  1270. function readPromoCode() {
  1271. var urlSplit = window.location.href.split('/');
  1272. return urlSplit[urlSplit.length - 1];
  1273. };
  1274. function displayStatusUi() {
  1275. $( 'body' ).prepend( '<div class="withdraw-button bg-2" style="top:30%; z-index:1500;" href="#">⚙️ <span id="process-status">Processing</span></div>' );
  1276. };
  1277. return {
  1278. run: run,
  1279. runPromotion: runPromotion,
  1280. findPromotionTag: findPromotionTag,
  1281. waitInteractions: waitInteractions,
  1282. isFullyLoaded: isFullyLoaded,
  1283. doLogin: doLogin
  1284. };
  1285. },
  1286. createCFHistory: function() {
  1287. let rollsMeta = [
  1288. { id: 0, range: '0000-9885', count: 0 },
  1289. { id: 1, range: '9886-9985', count: 0 },
  1290. { id: 2, range: '9986-9993', count: 0 },
  1291. { id: 3, range: '9994-9997', count: 0 },
  1292. { id: 4, range: '9998-9999', count: 0 },
  1293. { id: 5, range: '10000', count: 0 }
  1294. ];
  1295. function initOrLoad() {
  1296. let storedData = persistence.load('CFHistory', true);
  1297. if(storedData) {
  1298. rollsMeta = storedData;
  1299. }
  1300. };
  1301. function addRoll(number) {
  1302. switch(true) {
  1303. case (number <= 9885):
  1304. rollsMeta[0].count++;
  1305. break;
  1306. case (number <= 9985):
  1307. rollsMeta[1].count++;
  1308. break;
  1309. case (number <= 9993):
  1310. rollsMeta[2].count++;
  1311. break;
  1312. case (number <= 9997):
  1313. rollsMeta[3].count++;
  1314. break;
  1315. case (number <= 9999):
  1316. rollsMeta[4].count++;
  1317. break;
  1318. case (number == 10000):
  1319. rollsMeta[5].count++;
  1320. break;
  1321. default:
  1322. break;
  1323. }
  1324. save();
  1325. };
  1326. function getRollsMeta() {
  1327. return rollsMeta.map(x => x.count);
  1328. };
  1329. function save() {
  1330. persistence.save('CFHistory', rollsMeta, true);
  1331. };
  1332. return {
  1333. initOrLoad: initOrLoad,
  1334. addRoll: addRoll,
  1335. getRollsMeta: getRollsMeta
  1336. }
  1337. },
  1338. createFBProcessor: function() {
  1339. let timeWaiting= 0;
  1340. let countdownMinutes;
  1341. function run() {
  1342. setTimeout(findCountdownOrRollButton, helpers.randomMs(12000, 15000));
  1343. };
  1344. function findCountdownOrRollButton() {
  1345. if ( isCountdownVisible() ) {
  1346. timeWaiting = 0;
  1347. countdownMinutes = +document.querySelectorAll('.free_play_time_remaining.hasCountdown .countdown_amount')[0].innerHTML + 1;
  1348. let result = {};
  1349. result.balance = readBalance();
  1350. result.nextRoll = helpers.addMinutes(new Date(), countdownMinutes.toString());
  1351. shared.closeWindow(result);
  1352. return;
  1353. }
  1354. if ( isRollButtonVisible() ) {
  1355. if (config.fb.activateRPBonus) {
  1356. if (!document.getElementById('bonus_container_free_points')) {
  1357. document.querySelector('a.rewards_link').click();
  1358. activateBonus(0);
  1359. }
  1360. }
  1361. if (isHCaptchaVisible()) {
  1362. waitForCaptcha();
  1363. } else {
  1364. clickRoll();
  1365. }
  1366. }
  1367. };
  1368. function isCountdownVisible() {
  1369. return document.querySelectorAll('.free_play_time_remaining.hasCountdown .countdown_amount').length > 0;
  1370. };
  1371. function isHCaptchaVisible() {
  1372. let hCaptchaFrame = document.querySelector('.h-captcha > iframe');
  1373. if (hCaptchaFrame && $(hCaptchaFrame).is(':visible')) {
  1374. return true;
  1375. }
  1376. return false;
  1377. };
  1378. function isRollButtonVisible() {
  1379. return $(document.getElementById('free_play_form_button')).is(':visible');
  1380. };
  1381. function waitForCaptcha() {
  1382. if ( document.querySelector('.h-captcha > iframe').getAttribute('data-hcaptcha-response').length > 0) {
  1383. clickRoll();
  1384. } else {
  1385. if (timeWaiting/1000 > config.timeout * 60) {
  1386. shared.closeWithError('TIMEOUT', '');
  1387. return;
  1388. }
  1389. timeWaiting += 10000;
  1390. setTimeout(waitForCaptcha, helpers.randomMs(10000, 12000));
  1391. }
  1392. };
  1393. function clickRoll() {
  1394. try {
  1395. document.getElementById('free_play_form_button').click();
  1396. setTimeout(processRunDetails, helpers.randomMs(3000, 10000));
  1397. } catch (err) {
  1398. shared.closeWithError('CLICK_ROLL_ERROR', err);
  1399. }
  1400. };
  1401. function processRunDetails() {
  1402. if ($(document.getElementById('winnings')).is(':visible')) {
  1403. closePopup();
  1404. let result = {};
  1405. result.claimed = readClaimed();
  1406. result.balance = readBalance();
  1407. if(result.claimed != 0) {
  1408. result.rolledNumber = readRolledNumber();
  1409. result.nextRoll = helpers.addMinutes(new Date(), "60");
  1410. }
  1411. shared.closeWindow(result);
  1412. return;
  1413. }
  1414. if ($(document.getElementById('same_ip_error')).is(':visible')) {
  1415. shared.closeWithError('ROLL_ERROR', document.getElementById('same_ip_error').innerHTML);
  1416. return;
  1417. }
  1418. if($('#free_play_error').is(':visible')) {
  1419. shared.closeWithError('ROLL_ERROR', $('.free_play_error')[0].innerHTML);
  1420. return;
  1421. }
  1422. if ($('.free_play_result_error').is(':visible')) {
  1423. shared.closeWithError('ROLL_ERROR', $('.free_play_result_error')[0].innerHTML);
  1424. return;
  1425. }
  1426. if (timeWaiting/1000 > config.timeout * 60) {
  1427. shared.closeWithError('TIMEOUT', '');
  1428. return;
  1429. }
  1430. timeWaiting += 5000;
  1431. setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
  1432. };
  1433. function closePopup() {
  1434. let closePopupBtn = document.querySelector('.reveal-modal.open .close-reveal-modal');
  1435. if (closePopupBtn) {
  1436. closePopupBtn.click();
  1437. }
  1438. };
  1439. function readRolledNumber() {
  1440. let rolled = 0;
  1441. try {
  1442. rolled = parseInt([... document.querySelectorAll('#free_play_digits span')].map( x => x.innerHTML).join(''));
  1443. } catch { }
  1444. return rolled;
  1445. };
  1446. function readBalance() {
  1447. let balance = 0;
  1448. try {
  1449. balance = document.getElementById('balance').innerHTML;
  1450. } catch { }
  1451. return balance;
  1452. };
  1453. function readClaimed() {
  1454. let claimed = 0;
  1455. try {
  1456. claimed = document.getElementById('winnings').innerHTML;
  1457. } catch { }
  1458. return claimed;
  1459. };
  1460. function activateBonus(i) {
  1461. if($(document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_error')).is(':visible')) {
  1462. let closeBtn = document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_box_close')
  1463. if ($(closeBtn).is(':visible')) {
  1464. closeBtn.click();
  1465. }
  1466. } else if ($(document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_success')).is(':visible')) {
  1467. let closeBtn = document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_box_close')
  1468. if ($(closeBtn).is(':visible')) {
  1469. closeBtn.click();
  1470. document.querySelector('#free_play_link_li a');
  1471. setTimeout(findCountdownOrRollButton, helpers.randomMs(10000, 12000));
  1472. return;
  1473. }
  1474. }
  1475. try {
  1476. let redeemButtons = document.querySelectorAll('#free_points_rewards button');
  1477. redeemButtons[i].click();
  1478. i = i + 1;
  1479. } catch (err) {
  1480. }
  1481. if(i > 4) {
  1482. document.querySelector('#free_play_link_li a');
  1483. setTimeout(findCountdownOrRollButton, helpers.randomMs(10000, 12000));
  1484. return;
  1485. }
  1486. setTimeout(activateBonus.bind(null, i), 5000);
  1487. };
  1488. return {
  1489. run: run
  1490. };
  1491. }
  1492. };
  1493. /**
  1494. * Prevents alert popups to be able to reload the faucet if invisible captcha validation fails
  1495. */
  1496. function overrideSelectNativeJS_Functions () {
  1497. window.alert = function alert (message) {
  1498. console.log (message);
  1499. }
  1500. }
  1501. function addJS_Node (text, s_URL, funcToRun) {
  1502. var scriptNode= document.createElement ('script');
  1503. scriptNode.type= "text/javascript";
  1504. if (text)scriptNode.textContent= text;
  1505. if (s_URL)scriptNode.src= s_URL;
  1506. if (funcToRun)scriptNode.textContent = '(' + funcToRun.toString() + ')()';
  1507. var element = document.getElementsByTagName ('head')[0] || document.body || document.documentElement;
  1508. element.appendChild (scriptNode);
  1509. }
  1510. function detectWeb() {
  1511. // Now detecting based on host to handle automatic redirects (for example: login request)
  1512. if(!shared.isOpenedByManager(window.location.host)) {
  1513. return;
  1514. }
  1515. let currentFromManager = shared.getCurrent();
  1516. if (currentFromManager.type == WebType.STORMGAIN) {
  1517. SGProcessor = objectGenerator.createSGProcessor();
  1518. setTimeout(SGProcessor.run, helpers.randomMs(10000, 20000));
  1519. return;
  1520. }
  1521. if (currentFromManager.type == WebType.CRYPTOSFAUCETS) {
  1522. let expectedCfUrlType = helpers.cf.getUrlType(currentFromManager.url);
  1523. let realCfUrlType = helpers.cf.getUrlType(window.location.href);
  1524. switch(expectedCfUrlType) {
  1525. case CFUrlType.FREE:
  1526. switch(realCfUrlType) {
  1527. case CFUrlType.FREE:
  1528. if(localeConfig.setToEnglish) {
  1529. let refValue = $('.nav-item a')[4].innerHTML;
  1530. if (refValue != 'Settings') {
  1531. window.location.href = '/set-language/en';
  1532. }
  1533. }
  1534. addJS_Node (null, null, overrideSelectNativeJS_Functions);
  1535. CFProcessor = objectGenerator.createCFProcessor();
  1536. interactions = objectGenerator.createInteractions();
  1537. setTimeout(CFProcessor.run, helpers.randomMs(1000, 3000));
  1538. break;
  1539. case CFUrlType.CONTACTTWITTER:
  1540. //TODO: mark as possibly banned
  1541. break;
  1542. case CFUrlType.HOME:
  1543. if (config.cf.autologin) {
  1544. addJS_Node (null, null, overrideSelectNativeJS_Functions);
  1545. CFProcessor = objectGenerator.createCFProcessor();
  1546. setTimeout(CFProcessor.doLogin, helpers.randomMs(1000, 3000));
  1547. } else {
  1548. shared.closeWithError('NEED_TO_LOGIN', '');
  1549. }
  1550. break;
  1551. default:
  1552. break;
  1553. }
  1554. break;
  1555. case CFUrlType.PROMOTION:
  1556. CFProcessor = objectGenerator.createCFProcessor();
  1557. interactions = objectGenerator.createInteractions();
  1558. setTimeout(CFProcessor.runPromotion, helpers.randomMs(5000, 10000));
  1559. break;
  1560. }
  1561. return;
  1562. }
  1563. if (currentFromManager.type == WebType.FREEBITCOIN) {
  1564. FBProcessor = objectGenerator.createFBProcessor();
  1565. setTimeout(FBProcessor.run, helpers.randomMs(2000, 5000));
  1566. return;
  1567. }
  1568. }
  1569. function init() {
  1570. shared = objectGenerator.createShared();
  1571. persistence = objectGenerator.createPersistence();
  1572. if(window.location.host === 'satology.onrender.com') {
  1573. manager = objectGenerator.createManager();
  1574. CFPromotions = objectGenerator.createCFPromotions();
  1575. ui = objectGenerator.createUi();
  1576. CFHistory = objectGenerator.createCFHistory();
  1577. manager.init();
  1578. } else {
  1579. detectWeb();
  1580. }
  1581. }
  1582. init();
  1583. })();

comments powered by Disqus